[DOC] Fix the block parameter name in Array#zip
[ruby.git] / array.c
blob967659d7fd05c8370852148236394c2fffd44d35
1 /**********************************************************************
3 array.c -
5 $Author$
6 created at: Fri Aug 6 09:46:12 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "debug_counter.h"
15 #include "id.h"
16 #include "internal.h"
17 #include "internal/array.h"
18 #include "internal/compar.h"
19 #include "internal/enum.h"
20 #include "internal/gc.h"
21 #include "internal/hash.h"
22 #include "internal/numeric.h"
23 #include "internal/object.h"
24 #include "internal/proc.h"
25 #include "internal/rational.h"
26 #include "internal/vm.h"
27 #include "probes.h"
28 #include "ruby/encoding.h"
29 #include "ruby/st.h"
30 #include "ruby/util.h"
31 #include "vm_core.h"
32 #include "builtin.h"
34 #if !ARRAY_DEBUG
35 # undef NDEBUG
36 # define NDEBUG
37 #endif
38 #include "ruby_assert.h"
40 VALUE rb_cArray;
41 VALUE rb_cArray_empty_frozen;
43 /* Flags of RArray
45 * 0: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
46 * The array is shared. The buffer this array points to is owned by
47 * another array (the shared root).
48 * 1: RARRAY_EMBED_FLAG
49 * The array is embedded (its contents follow the header, rather than
50 * being on a separately allocated buffer).
51 * 3-9: RARRAY_EMBED_LEN
52 * The length of the array when RARRAY_EMBED_FLAG is set.
53 * 12: RARRAY_SHARED_ROOT_FLAG
54 * The array is a shared root that does reference counting. The buffer
55 * this array points to is owned by this array but may be pointed to
56 * by other arrays.
57 * Note: Frozen arrays may be a shared root without this flag being
58 * set. Frozen arrays do not have reference counting because
59 * they cannot be modified. Not updating the reference count
60 * improves copy-on-write performance. Their reference count is
61 * assumed to be infinity.
62 * 14: RARRAY_PTR_IN_USE_FLAG
63 * The buffer of the array is in use. This is only used during
64 * debugging.
67 /* for OPTIMIZED_CMP: */
68 #define id_cmp idCmp
70 #define ARY_DEFAULT_SIZE 16
71 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
72 #define SMALL_ARRAY_LEN 16
74 RBIMPL_ATTR_MAYBE_UNUSED()
75 static int
76 should_be_T_ARRAY(VALUE ary)
78 return RB_TYPE_P(ary, T_ARRAY);
81 #define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
82 #define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
83 #define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
84 RARRAY(a)->as.heap.aux.capa)
86 #define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
87 #define ARY_EMBED_LEN(a) \
88 (RUBY_ASSERT(ARY_EMBED_P(a)), \
89 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
90 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
91 #define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
93 #define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
94 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
96 #define FL_SET_EMBED(a) do { \
97 RUBY_ASSERT(!ARY_SHARED_P(a)); \
98 FL_SET((a), RARRAY_EMBED_FLAG); \
99 ary_verify(a); \
100 } while (0)
102 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
103 #define FL_SET_SHARED(ary) do { \
104 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
105 FL_SET((ary), RARRAY_SHARED_FLAG); \
106 } while (0)
107 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
109 #define ARY_SET_PTR(ary, p) do { \
110 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
111 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
112 RARRAY(ary)->as.heap.ptr = (p); \
113 } while (0)
114 #define ARY_SET_EMBED_LEN(ary, n) do { \
115 long tmp_n = (n); \
116 RUBY_ASSERT(ARY_EMBED_P(ary)); \
117 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
118 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
119 } while (0)
120 #define ARY_SET_HEAP_LEN(ary, n) do { \
121 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
122 RARRAY(ary)->as.heap.len = (n); \
123 } while (0)
124 #define ARY_SET_LEN(ary, n) do { \
125 if (ARY_EMBED_P(ary)) { \
126 ARY_SET_EMBED_LEN((ary), (n)); \
128 else { \
129 ARY_SET_HEAP_LEN((ary), (n)); \
131 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
132 } while (0)
133 #define ARY_INCREASE_PTR(ary, n) do { \
134 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
135 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
136 RARRAY(ary)->as.heap.ptr += (n); \
137 } while (0)
138 #define ARY_INCREASE_LEN(ary, n) do { \
139 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
140 if (ARY_EMBED_P(ary)) { \
141 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
143 else { \
144 RARRAY(ary)->as.heap.len += (n); \
146 } while (0)
148 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
149 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
150 #define ARY_SET_CAPA(ary, n) do { \
151 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
152 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
153 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
154 RARRAY(ary)->as.heap.aux.capa = (n); \
155 } while (0)
157 #define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
158 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
159 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
160 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
161 RUBY_ASSERT((value) >= 0); \
162 RARRAY(ary)->as.heap.aux.capa = (value); \
163 } while (0)
164 #define FL_SET_SHARED_ROOT(ary) do { \
165 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
166 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
167 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
168 } while (0)
170 static inline void
171 ARY_SET(VALUE a, long i, VALUE v)
173 RUBY_ASSERT(!ARY_SHARED_P(a));
174 RUBY_ASSERT(!OBJ_FROZEN(a));
176 RARRAY_ASET(a, i, v);
178 #undef RARRAY_ASET
180 static long
181 ary_embed_capa(VALUE ary)
183 size_t size = rb_gc_obj_slot_size(ary) - offsetof(struct RArray, as.ary);
184 RUBY_ASSERT(size % sizeof(VALUE) == 0);
185 return size / sizeof(VALUE);
188 static size_t
189 ary_embed_size(long capa)
191 return offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
194 static bool
195 ary_embeddable_p(long capa)
197 return rb_gc_size_allocatable_p(ary_embed_size(capa));
200 bool
201 rb_ary_embeddable_p(VALUE ary)
203 /* An array cannot be turned embeddable when the array is:
204 * - Shared root: other objects may point to the buffer of this array
205 * so we cannot make it embedded.
206 * - Frozen: this array may also be a shared root without the shared root
207 * flag.
208 * - Shared: we don't want to re-embed an array that points to a shared
209 * root (to save memory).
211 return !(ARY_SHARED_ROOT_P(ary) || OBJ_FROZEN(ary) || ARY_SHARED_P(ary));
214 size_t
215 rb_ary_size_as_embedded(VALUE ary)
217 size_t real_size;
219 if (ARY_EMBED_P(ary)) {
220 real_size = ary_embed_size(ARY_EMBED_LEN(ary));
222 else if (rb_ary_embeddable_p(ary)) {
223 real_size = ary_embed_size(ARY_HEAP_CAPA(ary));
225 else {
226 real_size = sizeof(struct RArray);
228 return real_size;
232 #if ARRAY_DEBUG
233 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
235 static VALUE
236 ary_verify_(VALUE ary, const char *file, int line)
238 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
240 if (ARY_SHARED_P(ary)) {
241 VALUE root = ARY_SHARED_ROOT(ary);
242 const VALUE *ptr = ARY_HEAP_PTR(ary);
243 const VALUE *root_ptr = RARRAY_CONST_PTR(root);
244 long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
245 RUBY_ASSERT(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
246 RUBY_ASSERT(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
247 ary_verify(root);
249 else if (ARY_EMBED_P(ary)) {
250 RUBY_ASSERT(!ARY_SHARED_P(ary));
251 RUBY_ASSERT(RARRAY_LEN(ary) <= ary_embed_capa(ary));
253 else {
254 const VALUE *ptr = RARRAY_CONST_PTR(ary);
255 long i, len = RARRAY_LEN(ary);
256 volatile VALUE v;
257 if (len > 1) len = 1; /* check only HEAD */
258 for (i=0; i<len; i++) {
259 v = ptr[i]; /* access check */
261 v = v;
264 return ary;
266 #else
267 #define ary_verify(ary) ((void)0)
268 #endif
270 VALUE *
271 rb_ary_ptr_use_start(VALUE ary)
273 #if ARRAY_DEBUG
274 FL_SET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
275 #endif
276 return (VALUE *)RARRAY_CONST_PTR(ary);
279 void
280 rb_ary_ptr_use_end(VALUE ary)
282 #if ARRAY_DEBUG
283 FL_UNSET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
284 #endif
287 void
288 rb_mem_clear(VALUE *mem, long size)
290 while (size--) {
291 *mem++ = Qnil;
295 static void
296 ary_mem_clear(VALUE ary, long beg, long size)
298 RARRAY_PTR_USE(ary, ptr, {
299 rb_mem_clear(ptr + beg, size);
303 static inline void
304 memfill(register VALUE *mem, register long size, register VALUE val)
306 while (size--) {
307 *mem++ = val;
311 static void
312 ary_memfill(VALUE ary, long beg, long size, VALUE val)
314 RARRAY_PTR_USE(ary, ptr, {
315 memfill(ptr + beg, size, val);
316 RB_OBJ_WRITTEN(ary, Qundef, val);
320 static void
321 ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
323 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary));
325 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
326 rb_gc_writebarrier_remember(buff_owner_ary);
327 RARRAY_PTR_USE(ary, ptr, {
328 MEMCPY(ptr+beg, argv, VALUE, argc);
331 else {
332 int i;
333 RARRAY_PTR_USE(ary, ptr, {
334 for (i=0; i<argc; i++) {
335 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
341 static void
342 ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
344 ary_memcpy0(ary, beg, argc, argv, ary);
347 static VALUE *
348 ary_heap_alloc_buffer(size_t capa)
350 return ALLOC_N(VALUE, capa);
353 static void
354 ary_heap_free_ptr(VALUE ary, const VALUE *ptr, long size)
356 ruby_sized_xfree((void *)ptr, size);
359 static void
360 ary_heap_free(VALUE ary)
362 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
365 static size_t
366 ary_heap_realloc(VALUE ary, size_t new_capa)
368 RUBY_ASSERT(!OBJ_FROZEN(ary));
369 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, ARY_HEAP_CAPA(ary));
370 ary_verify(ary);
372 return new_capa;
375 void
376 rb_ary_make_embedded(VALUE ary)
378 RUBY_ASSERT(rb_ary_embeddable_p(ary));
379 if (!ARY_EMBED_P(ary)) {
380 const VALUE *buf = ARY_HEAP_PTR(ary);
381 long len = ARY_HEAP_LEN(ary);
383 FL_SET_EMBED(ary);
384 ARY_SET_EMBED_LEN(ary, len);
386 MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
388 ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
392 static void
393 ary_resize_capa(VALUE ary, long capacity)
395 RUBY_ASSERT(RARRAY_LEN(ary) <= capacity);
396 RUBY_ASSERT(!OBJ_FROZEN(ary));
397 RUBY_ASSERT(!ARY_SHARED_P(ary));
399 if (capacity > ary_embed_capa(ary)) {
400 size_t new_capa = capacity;
401 if (ARY_EMBED_P(ary)) {
402 long len = ARY_EMBED_LEN(ary);
403 VALUE *ptr = ary_heap_alloc_buffer(capacity);
405 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
406 FL_UNSET_EMBED(ary);
407 ARY_SET_PTR(ary, ptr);
408 ARY_SET_HEAP_LEN(ary, len);
410 else {
411 new_capa = ary_heap_realloc(ary, capacity);
413 ARY_SET_CAPA(ary, new_capa);
415 else {
416 if (!ARY_EMBED_P(ary)) {
417 long len = ARY_HEAP_LEN(ary);
418 long old_capa = ARY_HEAP_CAPA(ary);
419 const VALUE *ptr = ARY_HEAP_PTR(ary);
421 if (len > capacity) len = capacity;
422 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
423 ary_heap_free_ptr(ary, ptr, old_capa);
425 FL_SET_EMBED(ary);
426 ARY_SET_LEN(ary, len);
430 ary_verify(ary);
433 static inline void
434 ary_shrink_capa(VALUE ary)
436 long capacity = ARY_HEAP_LEN(ary);
437 long old_capa = ARY_HEAP_CAPA(ary);
438 RUBY_ASSERT(!ARY_SHARED_P(ary));
439 RUBY_ASSERT(old_capa >= capacity);
440 if (old_capa > capacity) {
441 size_t new_capa = ary_heap_realloc(ary, capacity);
442 ARY_SET_CAPA(ary, new_capa);
445 ary_verify(ary);
448 static void
449 ary_double_capa(VALUE ary, long min)
451 long new_capa = ARY_CAPA(ary) / 2;
453 if (new_capa < ARY_DEFAULT_SIZE) {
454 new_capa = ARY_DEFAULT_SIZE;
456 if (new_capa >= ARY_MAX_SIZE - min) {
457 new_capa = (ARY_MAX_SIZE - min) / 2;
459 new_capa += min;
460 ary_resize_capa(ary, new_capa);
462 ary_verify(ary);
465 static void
466 rb_ary_decrement_share(VALUE shared_root)
468 if (!OBJ_FROZEN(shared_root)) {
469 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
470 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
474 static void
475 rb_ary_unshare(VALUE ary)
477 VALUE shared_root = ARY_SHARED_ROOT(ary);
478 rb_ary_decrement_share(shared_root);
479 FL_UNSET_SHARED(ary);
482 static void
483 rb_ary_reset(VALUE ary)
485 if (ARY_OWNS_HEAP_P(ary)) {
486 ary_heap_free(ary);
488 else if (ARY_SHARED_P(ary)) {
489 rb_ary_unshare(ary);
492 FL_SET_EMBED(ary);
493 ARY_SET_EMBED_LEN(ary, 0);
496 static VALUE
497 rb_ary_increment_share(VALUE shared_root)
499 if (!OBJ_FROZEN(shared_root)) {
500 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
501 RUBY_ASSERT(num >= 0);
502 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
504 return shared_root;
507 static void
508 rb_ary_set_shared(VALUE ary, VALUE shared_root)
510 RUBY_ASSERT(!ARY_EMBED_P(ary));
511 RUBY_ASSERT(!OBJ_FROZEN(ary));
512 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root));
514 rb_ary_increment_share(shared_root);
515 FL_SET_SHARED(ary);
516 RB_OBJ_WRITE(ary, &RARRAY(ary)->as.heap.aux.shared_root, shared_root);
518 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
521 static inline void
522 rb_ary_modify_check(VALUE ary)
524 rb_check_frozen(ary);
525 ary_verify(ary);
528 void
529 rb_ary_cancel_sharing(VALUE ary)
531 if (ARY_SHARED_P(ary)) {
532 long shared_len, len = RARRAY_LEN(ary);
533 VALUE shared_root = ARY_SHARED_ROOT(ary);
535 ary_verify(shared_root);
537 if (len <= ary_embed_capa(ary)) {
538 const VALUE *ptr = ARY_HEAP_PTR(ary);
539 FL_UNSET_SHARED(ary);
540 FL_SET_EMBED(ary);
541 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
542 rb_ary_decrement_share(shared_root);
543 ARY_SET_EMBED_LEN(ary, len);
545 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
546 long shift = RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared_root);
547 FL_UNSET_SHARED(ary);
548 ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared_root));
549 ARY_SET_CAPA(ary, shared_len);
550 RARRAY_PTR_USE(ary, ptr, {
551 MEMMOVE(ptr, ptr+shift, VALUE, len);
553 FL_SET_EMBED(shared_root);
554 rb_ary_decrement_share(shared_root);
556 else {
557 VALUE *ptr = ary_heap_alloc_buffer(len);
558 MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
559 rb_ary_unshare(ary);
560 ARY_SET_CAPA(ary, len);
561 ARY_SET_PTR(ary, ptr);
564 rb_gc_writebarrier_remember(ary);
566 ary_verify(ary);
569 void
570 rb_ary_modify(VALUE ary)
572 rb_ary_modify_check(ary);
573 rb_ary_cancel_sharing(ary);
576 static VALUE
577 ary_ensure_room_for_push(VALUE ary, long add_len)
579 long old_len = RARRAY_LEN(ary);
580 long new_len = old_len + add_len;
581 long capa;
583 if (old_len > ARY_MAX_SIZE - add_len) {
584 rb_raise(rb_eIndexError, "index %ld too big", new_len);
586 if (ARY_SHARED_P(ary)) {
587 if (new_len > ary_embed_capa(ary)) {
588 VALUE shared_root = ARY_SHARED_ROOT(ary);
589 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
590 if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
591 rb_ary_modify_check(ary);
593 ary_verify(ary);
594 ary_verify(shared_root);
595 return shared_root;
597 else {
598 /* if array is shared, then it is likely it participate in push/shift pattern */
599 rb_ary_modify(ary);
600 capa = ARY_CAPA(ary);
601 if (new_len > capa - (capa >> 6)) {
602 ary_double_capa(ary, new_len);
604 ary_verify(ary);
605 return ary;
609 ary_verify(ary);
610 rb_ary_modify(ary);
612 else {
613 rb_ary_modify_check(ary);
615 capa = ARY_CAPA(ary);
616 if (new_len > capa) {
617 ary_double_capa(ary, new_len);
620 ary_verify(ary);
621 return ary;
625 * call-seq:
626 * freeze -> self
628 * Freezes +self+ (if not already frozen); returns +self+:
630 * a = []
631 * a.frozen? # => false
632 * a.freeze
633 * a.frozen? # => true
635 * No further changes may be made to +self+;
636 * raises FrozenError if a change is attempted.
638 * Related: Kernel#frozen?.
641 VALUE
642 rb_ary_freeze(VALUE ary)
644 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
646 if (OBJ_FROZEN(ary)) return ary;
648 if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) {
649 ary_shrink_capa(ary);
652 return rb_obj_freeze(ary);
655 /* This can be used to take a snapshot of an array (with
656 e.g. rb_ary_replace) and check later whether the array has been
657 modified from the snapshot. The snapshot is cheap, though if
658 something does modify the array it will pay the cost of copying
659 it. If Array#pop or Array#shift has been called, the array will
660 be still shared with the snapshot, but the array length will
661 differ. */
662 VALUE
663 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
665 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
666 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
667 ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
668 ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
669 return Qtrue;
671 return Qfalse;
674 static VALUE
675 ary_alloc_embed(VALUE klass, long capa)
677 size_t size = ary_embed_size(capa);
678 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
679 NEWOBJ_OF(ary, struct RArray, klass,
680 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
681 size, 0);
682 /* Created array is:
683 * FL_SET_EMBED((VALUE)ary);
684 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
686 return (VALUE)ary;
689 static VALUE
690 ary_alloc_heap(VALUE klass)
692 NEWOBJ_OF(ary, struct RArray, klass,
693 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
694 sizeof(struct RArray), 0);
695 return (VALUE)ary;
698 static VALUE
699 empty_ary_alloc(VALUE klass)
701 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
702 return ary_alloc_embed(klass, 0);
705 static VALUE
706 ary_new(VALUE klass, long capa)
708 VALUE ary;
710 if (capa < 0) {
711 rb_raise(rb_eArgError, "negative array size (or size too big)");
713 if (capa > ARY_MAX_SIZE) {
714 rb_raise(rb_eArgError, "array size too big");
717 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
719 if (ary_embeddable_p(capa)) {
720 ary = ary_alloc_embed(klass, capa);
722 else {
723 ary = ary_alloc_heap(klass);
724 ARY_SET_CAPA(ary, capa);
725 RUBY_ASSERT(!ARY_EMBED_P(ary));
727 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
728 ARY_SET_HEAP_LEN(ary, 0);
731 return ary;
734 VALUE
735 rb_ary_new_capa(long capa)
737 return ary_new(rb_cArray, capa);
740 VALUE
741 rb_ary_new(void)
743 return rb_ary_new_capa(0);
746 VALUE
747 (rb_ary_new_from_args)(long n, ...)
749 va_list ar;
750 VALUE ary;
751 long i;
753 ary = rb_ary_new2(n);
755 va_start(ar, n);
756 for (i=0; i<n; i++) {
757 ARY_SET(ary, i, va_arg(ar, VALUE));
759 va_end(ar);
761 ARY_SET_LEN(ary, n);
762 return ary;
765 VALUE
766 rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
768 VALUE ary;
770 ary = ary_new(klass, n);
771 if (n > 0 && elts) {
772 ary_memcpy(ary, 0, n, elts);
773 ARY_SET_LEN(ary, n);
776 return ary;
779 VALUE
780 rb_ary_new_from_values(long n, const VALUE *elts)
782 return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
785 static VALUE
786 ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
788 size_t size = ary_embed_size(capa);
789 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
790 NEWOBJ_OF(ary, struct RArray, klass,
791 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
792 size, ec);
793 /* Created array is:
794 * FL_SET_EMBED((VALUE)ary);
795 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
797 return (VALUE)ary;
800 static VALUE
801 ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
803 NEWOBJ_OF(ary, struct RArray, klass,
804 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
805 sizeof(struct RArray), ec);
806 return (VALUE)ary;
809 static VALUE
810 ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
812 VALUE ary;
814 if (capa < 0) {
815 rb_raise(rb_eArgError, "negative array size (or size too big)");
817 if (capa > ARY_MAX_SIZE) {
818 rb_raise(rb_eArgError, "array size too big");
821 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
823 if (ary_embeddable_p(capa)) {
824 ary = ec_ary_alloc_embed(ec, klass, capa);
826 else {
827 ary = ec_ary_alloc_heap(ec, klass);
828 ARY_SET_CAPA(ary, capa);
829 RUBY_ASSERT(!ARY_EMBED_P(ary));
831 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
832 ARY_SET_HEAP_LEN(ary, 0);
835 return ary;
838 VALUE
839 rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
841 VALUE ary;
843 ary = ec_ary_new(ec, rb_cArray, n);
844 if (n > 0 && elts) {
845 ary_memcpy(ary, 0, n, elts);
846 ARY_SET_LEN(ary, n);
849 return ary;
852 VALUE
853 rb_ary_hidden_new(long capa)
855 VALUE ary = ary_new(0, capa);
856 return ary;
859 VALUE
860 rb_ary_hidden_new_fill(long capa)
862 VALUE ary = rb_ary_hidden_new(capa);
863 ary_memfill(ary, 0, capa, Qnil);
864 ARY_SET_LEN(ary, capa);
865 return ary;
868 void
869 rb_ary_free(VALUE ary)
871 if (ARY_OWNS_HEAP_P(ary)) {
872 if (USE_DEBUG_COUNTER &&
873 !ARY_SHARED_ROOT_P(ary) &&
874 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
875 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
878 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
879 ary_heap_free(ary);
881 else {
882 RB_DEBUG_COUNTER_INC(obj_ary_embed);
885 if (ARY_SHARED_P(ary)) {
886 RB_DEBUG_COUNTER_INC(obj_ary_shared);
888 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
889 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
893 static VALUE fake_ary_flags;
895 static VALUE
896 init_fake_ary_flags(void)
898 struct RArray fake_ary = {0};
899 fake_ary.basic.flags = T_ARRAY;
900 VALUE ary = (VALUE)&fake_ary;
901 rb_ary_freeze(ary);
902 return fake_ary.basic.flags;
905 VALUE
906 rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len)
908 fake_ary->basic.flags = fake_ary_flags;
909 RBASIC_CLEAR_CLASS((VALUE)fake_ary);
911 // bypass frozen checks
912 fake_ary->as.heap.ptr = list;
913 fake_ary->as.heap.len = len;
914 fake_ary->as.heap.aux.capa = len;
915 return (VALUE)fake_ary;
918 size_t
919 rb_ary_memsize(VALUE ary)
921 if (ARY_OWNS_HEAP_P(ary)) {
922 return ARY_CAPA(ary) * sizeof(VALUE);
924 else {
925 return 0;
929 static VALUE
930 ary_make_shared(VALUE ary)
932 ary_verify(ary);
934 if (ARY_SHARED_P(ary)) {
935 return ARY_SHARED_ROOT(ary);
937 else if (ARY_SHARED_ROOT_P(ary)) {
938 return ary;
940 else if (OBJ_FROZEN(ary)) {
941 return ary;
943 else {
944 long capa = ARY_CAPA(ary);
945 long len = RARRAY_LEN(ary);
947 /* Shared roots cannot be embedded because the reference count
948 * (refcnt) is stored in as.heap.aux.capa. */
949 VALUE shared = ary_alloc_heap(0);
950 FL_SET_SHARED_ROOT(shared);
952 if (ARY_EMBED_P(ary)) {
953 VALUE *ptr = ary_heap_alloc_buffer(capa);
954 ARY_SET_PTR(shared, ptr);
955 ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary));
957 FL_UNSET_EMBED(ary);
958 ARY_SET_HEAP_LEN(ary, len);
959 ARY_SET_PTR(ary, ptr);
961 else {
962 ARY_SET_PTR(shared, RARRAY_CONST_PTR(ary));
965 ARY_SET_LEN(shared, capa);
966 ary_mem_clear(shared, len, capa - len);
967 rb_ary_set_shared(ary, shared);
969 ary_verify(shared);
970 ary_verify(ary);
972 return shared;
976 static VALUE
977 ary_make_substitution(VALUE ary)
979 long len = RARRAY_LEN(ary);
981 if (ary_embeddable_p(len)) {
982 VALUE subst = rb_ary_new_capa(len);
983 RUBY_ASSERT(ARY_EMBED_P(subst));
985 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
986 ARY_SET_EMBED_LEN(subst, len);
987 return subst;
989 else {
990 return rb_ary_increment_share(ary_make_shared(ary));
994 VALUE
995 rb_assoc_new(VALUE car, VALUE cdr)
997 return rb_ary_new3(2, car, cdr);
1000 VALUE
1001 rb_to_array_type(VALUE ary)
1003 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1005 #define to_ary rb_to_array_type
1007 VALUE
1008 rb_check_array_type(VALUE ary)
1010 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1013 VALUE
1014 rb_check_to_array(VALUE ary)
1016 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1019 VALUE
1020 rb_to_array(VALUE ary)
1022 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1026 * call-seq:
1027 * Array.try_convert(object) -> object, new_array, or nil
1029 * Attempts to return an array, based on the given +object+.
1031 * If +object+ is an array, returns +object+.
1033 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1034 * calls <tt>object.to_ary</tt>:
1035 * if the return value is an array or +nil+, returns that value;
1036 * if not, raises TypeError.
1038 * Otherwise returns +nil+.
1040 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1043 static VALUE
1044 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
1046 return rb_check_array_type(ary);
1049 /* :nodoc: */
1050 static VALUE
1051 rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
1053 VALUE ary;
1055 if (klass == rb_cArray) {
1056 long size = 0;
1057 if (argc > 0 && FIXNUM_P(argv[0])) {
1058 size = FIX2LONG(argv[0]);
1059 if (size < 0) size = 0;
1062 ary = ary_new(klass, size);
1064 rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
1066 else {
1067 ary = rb_class_new_instance_pass_kw(argc, argv, klass);
1070 return ary;
1074 * call-seq:
1075 * Array.new -> new_empty_array
1076 * Array.new(array) -> new_array
1077 * Array.new(size, default_value = nil) -> new_array
1078 * Array.new(size = 0) {|index| ... } -> new_array
1080 * Returns a new array.
1082 * With no block and no argument given, returns a new empty array:
1084 * Array.new # => []
1086 * With no block and array argument given, returns a new array with the same elements:
1088 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1090 * With no block and integer argument given, returns a new array containing
1091 * that many instances of the given +default_value+:
1093 * Array.new(0) # => []
1094 * Array.new(3) # => [nil, nil, nil]
1095 * Array.new(2, 3) # => [3, 3]
1097 * With a block given, returns an array of the given +size+;
1098 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1099 * the element at that +index+ in the returned array is the blocks return value:
1101 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1103 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1105 * array = Array.new(2, {})
1106 * array # => [{}, {}]
1107 * array[0][:a] = 1
1108 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1110 * If you want the elements of the array to be distinct, you should pass a block:
1112 * array = Array.new(2) { {} }
1113 * array # => [{}, {}]
1114 * array[0][:a] = 1
1115 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1117 * Raises TypeError if the first argument is not either an array
1118 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1119 * Raises ArgumentError if the first argument is a negative integer.
1121 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1124 static VALUE
1125 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1127 long len;
1128 VALUE size, val;
1130 rb_ary_modify(ary);
1131 if (argc == 0) {
1132 rb_ary_reset(ary);
1133 RUBY_ASSERT(ARY_EMBED_P(ary));
1134 RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
1135 if (rb_block_given_p()) {
1136 rb_warning("given block not used");
1138 return ary;
1140 rb_scan_args(argc, argv, "02", &size, &val);
1141 if (argc == 1 && !FIXNUM_P(size)) {
1142 val = rb_check_array_type(size);
1143 if (!NIL_P(val)) {
1144 rb_ary_replace(ary, val);
1145 return ary;
1149 len = NUM2LONG(size);
1150 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1151 if (len < 0) {
1152 rb_raise(rb_eArgError, "negative array size");
1154 if (len > ARY_MAX_SIZE) {
1155 rb_raise(rb_eArgError, "array size too big");
1157 /* recheck after argument conversion */
1158 rb_ary_modify(ary);
1159 ary_resize_capa(ary, len);
1160 if (rb_block_given_p()) {
1161 long i;
1163 if (argc == 2) {
1164 rb_warn("block supersedes default value argument");
1166 for (i=0; i<len; i++) {
1167 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
1168 ARY_SET_LEN(ary, i + 1);
1171 else {
1172 ary_memfill(ary, 0, len, val);
1173 ARY_SET_LEN(ary, len);
1175 return ary;
1179 * Returns a new array, populated with the given objects:
1181 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1182 * Array[] # => []
1183 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1185 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1188 static VALUE
1189 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1191 VALUE ary = ary_new(klass, argc);
1192 if (argc > 0 && argv) {
1193 ary_memcpy(ary, 0, argc, argv);
1194 ARY_SET_LEN(ary, argc);
1197 return ary;
1200 void
1201 rb_ary_store(VALUE ary, long idx, VALUE val)
1203 long len = RARRAY_LEN(ary);
1205 if (idx < 0) {
1206 idx += len;
1207 if (idx < 0) {
1208 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1209 idx - len, -len);
1212 else if (idx >= ARY_MAX_SIZE) {
1213 rb_raise(rb_eIndexError, "index %ld too big", idx);
1216 rb_ary_modify(ary);
1217 if (idx >= ARY_CAPA(ary)) {
1218 ary_double_capa(ary, idx);
1220 if (idx > len) {
1221 ary_mem_clear(ary, len, idx - len + 1);
1224 if (idx >= len) {
1225 ARY_SET_LEN(ary, idx + 1);
1227 ARY_SET(ary, idx, val);
1230 static VALUE
1231 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1233 RUBY_ASSERT(offset >= 0);
1234 RUBY_ASSERT(len >= 0);
1235 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1237 VALUE result = ary_alloc_heap(klass);
1238 size_t embed_capa = ary_embed_capa(result);
1239 if ((size_t)len <= embed_capa) {
1240 FL_SET_EMBED(result);
1241 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
1242 ARY_SET_EMBED_LEN(result, len);
1244 else {
1245 VALUE shared = ary_make_shared(ary);
1247 /* The ary_make_shared call may allocate, which can trigger a GC
1248 * compaction. This can cause the array to be embedded because it has
1249 * a length of 0. */
1250 FL_UNSET_EMBED(result);
1252 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
1253 ARY_SET_LEN(result, RARRAY_LEN(ary));
1254 rb_ary_set_shared(result, shared);
1256 ARY_INCREASE_PTR(result, offset);
1257 ARY_SET_LEN(result, len);
1259 ary_verify(shared);
1262 ary_verify(result);
1263 return result;
1266 static VALUE
1267 ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
1269 RUBY_ASSERT(offset >= 0);
1270 RUBY_ASSERT(len >= 0);
1271 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1272 RUBY_ASSERT(step != 0);
1274 const long orig_len = len;
1276 if (step > 0 && step >= len) {
1277 VALUE result = ary_new(klass, 1);
1278 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1279 const VALUE *values = RARRAY_CONST_PTR(ary);
1281 RB_OBJ_WRITE(result, ptr, values[offset]);
1282 ARY_SET_EMBED_LEN(result, 1);
1283 return result;
1285 else if (step < 0 && step < -len) {
1286 step = -len;
1289 long ustep = (step < 0) ? -step : step;
1290 len = roomof(len, ustep);
1292 long i;
1293 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1295 VALUE result = ary_new(klass, len);
1296 if (ARY_EMBED_P(result)) {
1297 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1298 const VALUE *values = RARRAY_CONST_PTR(ary);
1300 for (i = 0; i < len; ++i) {
1301 RB_OBJ_WRITE(result, ptr+i, values[j]);
1302 j += step;
1304 ARY_SET_EMBED_LEN(result, len);
1306 else {
1307 const VALUE *values = RARRAY_CONST_PTR(ary);
1309 RARRAY_PTR_USE(result, ptr, {
1310 for (i = 0; i < len; ++i) {
1311 RB_OBJ_WRITE(result, ptr+i, values[j]);
1312 j += step;
1315 ARY_SET_LEN(result, len);
1318 return result;
1321 static VALUE
1322 ary_make_shared_copy(VALUE ary)
1324 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
1327 enum ary_take_pos_flags
1329 ARY_TAKE_FIRST = 0,
1330 ARY_TAKE_LAST = 1
1333 static VALUE
1334 ary_take_first_or_last_n(VALUE ary, long n, enum ary_take_pos_flags last)
1336 long len = RARRAY_LEN(ary);
1337 long offset = 0;
1339 if (n > len) {
1340 n = len;
1342 else if (n < 0) {
1343 rb_raise(rb_eArgError, "negative array size");
1345 if (last) {
1346 offset = len - n;
1348 return ary_make_partial(ary, rb_cArray, offset, n);
1351 static VALUE
1352 ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1354 argc = rb_check_arity(argc, 0, 1);
1355 /* the case optional argument is omitted should be handled in
1356 * callers of this function. if another arity case is added,
1357 * this arity check needs to rewrite. */
1358 RUBY_ASSERT_ALWAYS(argc == 1);
1359 return ary_take_first_or_last_n(ary, NUM2LONG(argv[0]), last);
1363 * call-seq:
1364 * self << object -> self
1366 * Appends +object+ as the last element in +self+; returns +self+:
1368 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1370 * Appends +object+ as a single element, even if it is another array:
1372 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1374 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1377 VALUE
1378 rb_ary_push(VALUE ary, VALUE item)
1380 long idx = RARRAY_LEN((ary_verify(ary), ary));
1381 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1382 RARRAY_PTR_USE(ary, ptr, {
1383 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1385 ARY_SET_LEN(ary, idx + 1);
1386 ary_verify(ary);
1387 return ary;
1390 VALUE
1391 rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1393 long oldlen = RARRAY_LEN(ary);
1394 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1395 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1396 ARY_SET_LEN(ary, oldlen + len);
1397 return ary;
1401 * call-seq:
1402 * push(*objects) -> self
1403 * append(*objects) -> self
1405 * Appends each argument in +objects+ to +self+; returns +self+:
1407 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1408 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1410 * Appends each argument as a single element, even if it is another array:
1412 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1413 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1415 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1418 static VALUE
1419 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1421 return rb_ary_cat(ary, argv, argc);
1424 VALUE
1425 rb_ary_pop(VALUE ary)
1427 long n;
1428 rb_ary_modify_check(ary);
1429 n = RARRAY_LEN(ary);
1430 if (n == 0) return Qnil;
1431 if (ARY_OWNS_HEAP_P(ary) &&
1432 n * 3 < ARY_CAPA(ary) &&
1433 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1435 ary_resize_capa(ary, n * 2);
1437 --n;
1438 ARY_SET_LEN(ary, n);
1439 ary_verify(ary);
1440 return RARRAY_AREF(ary, n);
1444 * call-seq:
1445 * pop -> object or nil
1446 * pop(count) -> new_array
1448 * Removes and returns trailing elements of +self+.
1450 * With no argument given, removes and returns the last element, if available;
1451 * otherwise returns +nil+:
1453 * a = [:foo, 'bar', 2]
1454 * a.pop # => 2
1455 * a # => [:foo, "bar"]
1456 * [].pop # => nil
1458 * With non-negative integer argument +count+ given,
1459 * returns a new array containing the trailing +count+ elements of +self+, as available:
1461 * a = [:foo, 'bar', 2]
1462 * a.pop(2) # => ["bar", 2]
1463 * a # => [:foo]
1465 * a = [:foo, 'bar', 2]
1466 * a.pop(50) # => [:foo, "bar", 2]
1467 * a # => []
1469 * Related: Array#push;
1470 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1473 static VALUE
1474 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1476 VALUE result;
1478 if (argc == 0) {
1479 return rb_ary_pop(ary);
1482 rb_ary_modify_check(ary);
1483 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1484 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1485 ary_verify(ary);
1486 return result;
1489 VALUE
1490 rb_ary_shift(VALUE ary)
1492 VALUE top;
1493 long len = RARRAY_LEN(ary);
1495 if (len == 0) {
1496 rb_ary_modify_check(ary);
1497 return Qnil;
1500 top = RARRAY_AREF(ary, 0);
1502 rb_ary_behead(ary, 1);
1504 return top;
1508 * call-seq:
1509 * shift -> object or nil
1510 * shift(count) -> new_array or nil
1512 * Removes and returns leading elements from +self+.
1514 * With no argument, removes and returns one element, if available,
1515 * or +nil+ otherwise:
1517 * a = [0, 1, 2, 3]
1518 * a.shift # => 0
1519 * a # => [1, 2, 3]
1520 * [].shift # => nil
1522 * With non-negative numeric argument +count+ given,
1523 * removes and returns the first +count+ elements:
1525 * a = [0, 1, 2, 3]
1526 * a.shift(2) # => [0, 1]
1527 * a # => [2, 3]
1528 * a.shift(1.1) # => [2]
1529 * a # => [3]
1530 * a.shift(0) # => []
1531 * a # => [3]
1533 * If +count+ is large,
1534 * removes and returns all elements:
1536 * a = [0, 1, 2, 3]
1537 * a.shift(50) # => [0, 1, 2, 3]
1538 * a # => []
1540 * If +self+ is empty, returns a new empty array.
1542 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1545 static VALUE
1546 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1548 VALUE result;
1549 long n;
1551 if (argc == 0) {
1552 return rb_ary_shift(ary);
1555 rb_ary_modify_check(ary);
1556 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1557 n = RARRAY_LEN(result);
1558 rb_ary_behead(ary,n);
1560 return result;
1563 VALUE
1564 rb_ary_behead(VALUE ary, long n)
1566 if (n <= 0) {
1567 return ary;
1570 rb_ary_modify_check(ary);
1572 if (!ARY_SHARED_P(ary)) {
1573 if (ARY_EMBED_P(ary) || RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
1574 RARRAY_PTR_USE(ary, ptr, {
1575 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary) - n);
1576 }); /* WB: no new reference */
1577 ARY_INCREASE_LEN(ary, -n);
1578 ary_verify(ary);
1579 return ary;
1582 ary_mem_clear(ary, 0, n);
1583 ary_make_shared(ary);
1585 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1586 ary_mem_clear(ary, 0, n);
1589 ARY_INCREASE_PTR(ary, n);
1590 ARY_INCREASE_LEN(ary, -n);
1591 ary_verify(ary);
1593 return ary;
1596 static VALUE
1597 make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
1599 if (head - sharedp < argc) {
1600 long room = capa - len - argc;
1602 room -= room >> 4;
1603 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1604 head = sharedp + argc + room;
1606 ARY_SET_PTR(ary, head - argc);
1607 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1609 ary_verify(ary);
1610 return ARY_SHARED_ROOT(ary);
1613 static VALUE
1614 ary_modify_for_unshift(VALUE ary, int argc)
1616 long len = RARRAY_LEN(ary);
1617 long new_len = len + argc;
1618 long capa;
1619 const VALUE *head, *sharedp;
1621 rb_ary_modify(ary);
1622 capa = ARY_CAPA(ary);
1623 if (capa - (capa >> 6) <= new_len) {
1624 ary_double_capa(ary, new_len);
1627 /* use shared array for big "queues" */
1628 if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
1629 ary_verify(ary);
1631 /* make a room for unshifted items */
1632 capa = ARY_CAPA(ary);
1633 ary_make_shared(ary);
1635 head = sharedp = RARRAY_CONST_PTR(ary);
1636 return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
1638 else {
1639 /* sliding items */
1640 RARRAY_PTR_USE(ary, ptr, {
1641 MEMMOVE(ptr + argc, ptr, VALUE, len);
1644 ary_verify(ary);
1645 return ary;
1649 static VALUE
1650 ary_ensure_room_for_unshift(VALUE ary, int argc)
1652 long len = RARRAY_LEN(ary);
1653 long new_len = len + argc;
1655 if (len > ARY_MAX_SIZE - argc) {
1656 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1658 else if (! ARY_SHARED_P(ary)) {
1659 return ary_modify_for_unshift(ary, argc);
1661 else {
1662 VALUE shared_root = ARY_SHARED_ROOT(ary);
1663 long capa = RARRAY_LEN(shared_root);
1665 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1666 return ary_modify_for_unshift(ary, argc);
1668 else if (new_len > capa) {
1669 return ary_modify_for_unshift(ary, argc);
1671 else {
1672 const VALUE * head = RARRAY_CONST_PTR(ary);
1673 void *sharedp = (void *)RARRAY_CONST_PTR(shared_root);
1675 rb_ary_modify_check(ary);
1676 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1682 * call-seq:
1683 * unshift(*objects) -> self
1684 * prepend(*objects) -> self
1686 * Prepends the given +objects+ to +self+:
1688 * a = [:foo, 'bar', 2]
1689 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1691 * Related: Array#shift;
1692 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1695 VALUE
1696 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1698 long len = RARRAY_LEN(ary);
1699 VALUE target_ary;
1701 if (argc == 0) {
1702 rb_ary_modify_check(ary);
1703 return ary;
1706 target_ary = ary_ensure_room_for_unshift(ary, argc);
1707 ary_memcpy0(ary, 0, argc, argv, target_ary);
1708 ARY_SET_LEN(ary, len + argc);
1709 return ary;
1712 VALUE
1713 rb_ary_unshift(VALUE ary, VALUE item)
1715 return rb_ary_unshift_m(1, &item, ary);
1718 /* faster version - use this if you don't need to treat negative offset */
1719 static inline VALUE
1720 rb_ary_elt(VALUE ary, long offset)
1722 long len = RARRAY_LEN(ary);
1723 if (len == 0) return Qnil;
1724 if (offset < 0 || len <= offset) {
1725 return Qnil;
1727 return RARRAY_AREF(ary, offset);
1730 VALUE
1731 rb_ary_entry(VALUE ary, long offset)
1733 return rb_ary_entry_internal(ary, offset);
1736 VALUE
1737 rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
1739 VALUE klass;
1740 long alen = RARRAY_LEN(ary);
1742 if (beg > alen) return Qnil;
1743 if (beg < 0 || len < 0) return Qnil;
1745 if (alen < len || alen < beg + len) {
1746 len = alen - beg;
1748 klass = rb_cArray;
1749 if (len == 0) return ary_new(klass, 0);
1750 if (step == 0)
1751 rb_raise(rb_eArgError, "slice step cannot be zero");
1752 if (step == 1)
1753 return ary_make_partial(ary, klass, beg, len);
1754 else
1755 return ary_make_partial_step(ary, klass, beg, len, step);
1758 VALUE
1759 rb_ary_subseq(VALUE ary, long beg, long len)
1761 return rb_ary_subseq_step(ary, beg, len, 1);
1764 static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1767 * call-seq:
1768 * self[index] -> object or nil
1769 * self[start, length] -> object or nil
1770 * self[range] -> object or nil
1771 * self[aseq] -> object or nil
1772 * slice(index) -> object or nil
1773 * slice(start, length) -> object or nil
1774 * slice(range) -> object or nil
1775 * slice(aseq) -> object or nil
1777 * Returns elements from +self+; does not modify +self+.
1779 * In brief:
1781 * a = [:foo, 'bar', 2]
1783 * # Single argument index: returns one element.
1784 * a[0] # => :foo # Zero-based index.
1785 * a[-1] # => 2 # Negative index counts backwards from end.
1787 * # Arguments start and length: returns an array.
1788 * a[1, 2] # => ["bar", 2]
1789 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1791 * # Single argument range: returns an array.
1792 * a[0..1] # => [:foo, "bar"]
1793 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1794 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1796 * When a single integer argument +index+ is given, returns the element at offset +index+:
1798 * a = [:foo, 'bar', 2]
1799 * a[0] # => :foo
1800 * a[2] # => 2
1801 * a # => [:foo, "bar", 2]
1803 * If +index+ is negative, counts backwards from the end of +self+:
1805 * a = [:foo, 'bar', 2]
1806 * a[-1] # => 2
1807 * a[-2] # => "bar"
1809 * If +index+ is out of range, returns +nil+.
1811 * When two Integer arguments +start+ and +length+ are given,
1812 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1814 * a = [:foo, 'bar', 2]
1815 * a[0, 2] # => [:foo, "bar"]
1816 * a[1, 2] # => ["bar", 2]
1818 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1819 * returns all elements from offset +start+ to the end:
1821 * a = [:foo, 'bar', 2]
1822 * a[0, 4] # => [:foo, "bar", 2]
1823 * a[1, 3] # => ["bar", 2]
1824 * a[2, 2] # => [2]
1826 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1827 * returns a new empty +Array+.
1829 * If +length+ is negative, returns +nil+.
1831 * When a single Range argument +range+ is given,
1832 * treats <tt>range.min</tt> as +start+ above
1833 * and <tt>range.size</tt> as +length+ above:
1835 * a = [:foo, 'bar', 2]
1836 * a[0..1] # => [:foo, "bar"]
1837 * a[1..2] # => ["bar", 2]
1839 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1841 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1843 * a = [:foo, 'bar', 2]
1844 * a[0..-1] # => [:foo, "bar", 2]
1845 * a[0..-2] # => [:foo, "bar"]
1846 * a[0..-3] # => [:foo]
1848 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1850 * a = [:foo, 'bar', 2]
1851 * a[-1..2] # => [2]
1852 * a[-2..2] # => ["bar", 2]
1853 * a[-3..2] # => [:foo, "bar", 2]
1855 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1857 * a = [:foo, 'bar', 2]
1858 * a[4..1] # => nil
1859 * a[4..0] # => nil
1860 * a[4..-1] # => nil
1862 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1863 * returns an +Array+ of elements corresponding to the indexes produced by
1864 * the sequence.
1866 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1867 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1869 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1870 * is larger than array size, throws RangeError.
1872 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1873 * a[(1..11).step(2)]
1874 * # RangeError (((1..11).step(2)) out of range)
1875 * a[(7..).step(2)]
1876 * # RangeError (((7..).step(2)) out of range)
1878 * If given a single argument, and its type is not one of the listed, tries to
1879 * convert it to Integer, and raises if it is impossible:
1881 * a = [:foo, 'bar', 2]
1882 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1883 * a[:foo]
1885 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1888 VALUE
1889 rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
1891 rb_check_arity(argc, 1, 2);
1892 if (argc == 2) {
1893 return rb_ary_aref2(ary, argv[0], argv[1]);
1895 return rb_ary_aref1(ary, argv[0]);
1898 static VALUE
1899 rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1901 long beg = NUM2LONG(b);
1902 long len = NUM2LONG(e);
1903 if (beg < 0) {
1904 beg += RARRAY_LEN(ary);
1906 return rb_ary_subseq(ary, beg, len);
1909 VALUE
1910 rb_ary_aref1(VALUE ary, VALUE arg)
1912 long beg, len, step;
1914 /* special case - speeding up */
1915 if (FIXNUM_P(arg)) {
1916 return rb_ary_entry(ary, FIX2LONG(arg));
1918 /* check if idx is Range or ArithmeticSequence */
1919 switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
1920 case Qfalse:
1921 break;
1922 case Qnil:
1923 return Qnil;
1924 default:
1925 return rb_ary_subseq_step(ary, beg, len, step);
1928 return rb_ary_entry(ary, NUM2LONG(arg));
1932 * call-seq:
1933 * at(index) -> object or nil
1935 * Returns the element of +self+ specified by the given +index+
1936 * or +nil+ if there is no such element;
1937 * +index+ must be an
1938 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1940 * For non-negative +index+, returns the element of +self+ at offset +index+:
1942 * a = [:foo, 'bar', 2]
1943 * a.at(0) # => :foo
1944 * a.at(2) # => 2
1945 * a.at(2.0) # => 2
1947 * For negative +index+, counts backwards from the end of +self+:
1949 * a.at(-2) # => "bar"
1951 * Related: Array#[];
1952 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1955 VALUE
1956 rb_ary_at(VALUE ary, VALUE pos)
1958 return rb_ary_entry(ary, NUM2LONG(pos));
1961 #if 0
1962 static VALUE
1963 rb_ary_first(int argc, VALUE *argv, VALUE ary)
1965 if (argc == 0) {
1966 if (RARRAY_LEN(ary) == 0) return Qnil;
1967 return RARRAY_AREF(ary, 0);
1969 else {
1970 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1973 #endif
1975 static VALUE
1976 ary_first(VALUE self)
1978 return (RARRAY_LEN(self) == 0) ? Qnil : RARRAY_AREF(self, 0);
1981 static VALUE
1982 ary_last(VALUE self)
1984 long len = RARRAY_LEN(self);
1985 return (len == 0) ? Qnil : RARRAY_AREF(self, len-1);
1988 VALUE
1989 rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
1991 if (argc == 0) {
1992 return ary_last(ary);
1994 else {
1995 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
2000 * call-seq:
2001 * fetch(index) -> element
2002 * fetch(index, default_value) -> element or default_value
2003 * fetch(index) {|index| ... } -> element or block_return_value
2005 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2006 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2008 * With the single argument +index+ and no block,
2009 * returns the element at offset +index+:
2011 * a = [:foo, 'bar', 2]
2012 * a.fetch(1) # => "bar"
2013 * a.fetch(1.1) # => "bar"
2015 * If +index+ is negative, counts from the end of the array:
2017 * a = [:foo, 'bar', 2]
2018 * a.fetch(-1) # => 2
2019 * a.fetch(-2) # => "bar"
2021 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2022 * returns +default_value+ if +index+ is out-of-range:
2024 * a = [:foo, 'bar', 2]
2025 * a.fetch(1, nil) # => "bar"
2026 * a.fetch(3, :foo) # => :foo
2028 * With argument +index+ and a block,
2029 * returns the element at offset +index+ if index is in range
2030 * (and the block is not called); otherwise calls the block with index and returns its return value:
2032 * a = [:foo, 'bar', 2]
2033 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2034 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2036 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2039 static VALUE
2040 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
2042 VALUE pos, ifnone;
2043 long block_given;
2044 long idx;
2046 rb_scan_args(argc, argv, "11", &pos, &ifnone);
2047 block_given = rb_block_given_p();
2048 if (block_given && argc == 2) {
2049 rb_warn("block supersedes default value argument");
2051 idx = NUM2LONG(pos);
2053 if (idx < 0) {
2054 idx += RARRAY_LEN(ary);
2056 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
2057 if (block_given) return rb_yield(pos);
2058 if (argc == 1) {
2059 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
2060 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
2062 return ifnone;
2064 return RARRAY_AREF(ary, idx);
2068 * call-seq:
2069 * find_index(object) -> integer or nil
2070 * find_index {|element| ... } -> integer or nil
2071 * find_index -> new_enumerator
2072 * index(object) -> integer or nil
2073 * index {|element| ... } -> integer or nil
2074 * index -> new_enumerator
2076 * Returns the zero-based integer index of a specified element, or +nil+.
2078 * With only argument +object+ given,
2079 * returns the index of the first element +element+
2080 * for which <tt>object == element</tt>:
2082 * a = [:foo, 'bar', 2, 'bar']
2083 * a.index('bar') # => 1
2085 * Returns +nil+ if no such element found.
2087 * With only a block given,
2088 * calls the block with each successive element;
2089 * returns the index of the first element for which the block returns a truthy value:
2091 * a = [:foo, 'bar', 2, 'bar']
2092 * a.index {|element| element == 'bar' } # => 1
2094 * Returns +nil+ if the block never returns a truthy value.
2096 * With neither an argument nor a block given, returns a new Enumerator.
2098 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2101 static VALUE
2102 rb_ary_index(int argc, VALUE *argv, VALUE ary)
2104 VALUE val;
2105 long i;
2107 if (argc == 0) {
2108 RETURN_ENUMERATOR(ary, 0, 0);
2109 for (i=0; i<RARRAY_LEN(ary); i++) {
2110 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2111 return LONG2NUM(i);
2114 return Qnil;
2116 rb_check_arity(argc, 0, 1);
2117 val = argv[0];
2118 if (rb_block_given_p())
2119 rb_warn("given block not used");
2120 for (i=0; i<RARRAY_LEN(ary); i++) {
2121 VALUE e = RARRAY_AREF(ary, i);
2122 if (rb_equal(e, val)) {
2123 return LONG2NUM(i);
2126 return Qnil;
2130 * call-seq:
2131 * rindex(object) -> integer or nil
2132 * rindex {|element| ... } -> integer or nil
2133 * rindex -> new_enumerator
2135 * Returns the index of the last element for which <tt>object == element</tt>.
2137 * With argument +object+ given, returns the index of the last such element found:
2139 * a = [:foo, 'bar', 2, 'bar']
2140 * a.rindex('bar') # => 3
2142 * Returns +nil+ if no such object found.
2144 * With a block given, calls the block with each successive element;
2145 * returns the index of the last element for which the block returns a truthy value:
2147 * a = [:foo, 'bar', 2, 'bar']
2148 * a.rindex {|element| element == 'bar' } # => 3
2150 * Returns +nil+ if the block never returns a truthy value.
2152 * When neither an argument nor a block is given, returns a new Enumerator.
2154 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2157 static VALUE
2158 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
2160 VALUE val;
2161 long i = RARRAY_LEN(ary), len;
2163 if (argc == 0) {
2164 RETURN_ENUMERATOR(ary, 0, 0);
2165 while (i--) {
2166 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
2167 return LONG2NUM(i);
2168 if (i > (len = RARRAY_LEN(ary))) {
2169 i = len;
2172 return Qnil;
2174 rb_check_arity(argc, 0, 1);
2175 val = argv[0];
2176 if (rb_block_given_p())
2177 rb_warn("given block not used");
2178 while (i--) {
2179 VALUE e = RARRAY_AREF(ary, i);
2180 if (rb_equal(e, val)) {
2181 return LONG2NUM(i);
2183 if (i > RARRAY_LEN(ary)) {
2184 break;
2187 return Qnil;
2190 VALUE
2191 rb_ary_to_ary(VALUE obj)
2193 VALUE tmp = rb_check_array_type(obj);
2195 if (!NIL_P(tmp)) return tmp;
2196 return rb_ary_new3(1, obj);
2199 static void
2200 rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
2202 long olen;
2203 long rofs;
2205 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2206 olen = RARRAY_LEN(ary);
2207 if (beg < 0) {
2208 beg += olen;
2209 if (beg < 0) {
2210 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2211 beg - olen, -olen);
2214 if (olen < len || olen < beg + len) {
2215 len = olen - beg;
2219 const VALUE *optr = RARRAY_CONST_PTR(ary);
2220 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2223 if (beg >= olen) {
2224 VALUE target_ary;
2225 if (beg > ARY_MAX_SIZE - rlen) {
2226 rb_raise(rb_eIndexError, "index %ld too big", beg);
2228 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2229 len = beg + rlen;
2230 ary_mem_clear(ary, olen, beg - olen);
2231 if (rlen > 0) {
2232 if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
2233 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2235 ARY_SET_LEN(ary, len);
2237 else {
2238 long alen;
2240 if (olen - len > ARY_MAX_SIZE - rlen) {
2241 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2243 rb_ary_modify(ary);
2244 alen = olen + rlen - len;
2245 if (alen >= ARY_CAPA(ary)) {
2246 ary_double_capa(ary, alen);
2249 if (len != rlen) {
2250 RARRAY_PTR_USE(ary, ptr,
2251 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2252 VALUE, olen - (beg + len)));
2253 ARY_SET_LEN(ary, alen);
2255 if (rlen > 0) {
2256 if (rofs == -1) {
2257 rb_gc_writebarrier_remember(ary);
2259 else {
2260 /* In this case, we're copying from a region in this array, so
2261 * we don't need to fire the write barrier. */
2262 rptr = RARRAY_CONST_PTR(ary) + rofs;
2265 /* do not use RARRAY_PTR() because it can causes GC.
2266 * ary can contain T_NONE object because it is not cleared.
2268 RARRAY_PTR_USE(ary, ptr,
2269 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2274 void
2275 rb_ary_set_len(VALUE ary, long len)
2277 long capa;
2279 rb_ary_modify_check(ary);
2280 if (ARY_SHARED_P(ary)) {
2281 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2283 if (len > (capa = (long)ARY_CAPA(ary))) {
2284 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2286 ARY_SET_LEN(ary, len);
2289 VALUE
2290 rb_ary_resize(VALUE ary, long len)
2292 long olen;
2294 rb_ary_modify(ary);
2295 olen = RARRAY_LEN(ary);
2296 if (len == olen) return ary;
2297 if (len > ARY_MAX_SIZE) {
2298 rb_raise(rb_eIndexError, "index %ld too big", len);
2300 if (len > olen) {
2301 if (len > ARY_CAPA(ary)) {
2302 ary_double_capa(ary, len);
2304 ary_mem_clear(ary, olen, len - olen);
2305 ARY_SET_LEN(ary, len);
2307 else if (ARY_EMBED_P(ary)) {
2308 ARY_SET_EMBED_LEN(ary, len);
2310 else if (len <= ary_embed_capa(ary)) {
2311 const VALUE *ptr = ARY_HEAP_PTR(ary);
2312 long ptr_capa = ARY_HEAP_SIZE(ary);
2313 bool is_malloc_ptr = !ARY_SHARED_P(ary);
2315 FL_SET_EMBED(ary);
2317 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
2318 ARY_SET_EMBED_LEN(ary, len);
2320 if (is_malloc_ptr) ruby_sized_xfree((void *)ptr, ptr_capa);
2322 else {
2323 if (olen > len + ARY_DEFAULT_SIZE) {
2324 size_t new_capa = ary_heap_realloc(ary, len);
2325 ARY_SET_CAPA(ary, new_capa);
2327 ARY_SET_HEAP_LEN(ary, len);
2329 ary_verify(ary);
2330 return ary;
2333 static VALUE
2334 ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2336 rb_ary_store(ary, key, val);
2337 return val;
2340 static VALUE
2341 ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2343 VALUE rpl = rb_ary_to_ary(val);
2344 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl));
2345 RB_GC_GUARD(rpl);
2346 return val;
2350 * call-seq:
2351 * self[index] = object -> object
2352 * self[start, length] = object -> object
2353 * self[range] = object -> object
2355 * Assigns elements in +self+, based on the given +object+; returns +object+.
2357 * In brief:
2359 * a_orig = [:foo, 'bar', 2]
2361 * # With argument index.
2362 * a = a_orig.dup
2363 * a[0] = 'foo' # => "foo"
2364 * a # => ["foo", "bar", 2]
2365 * a = a_orig.dup
2366 * a[7] = 'foo' # => "foo"
2367 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2369 * # With arguments start and length.
2370 * a = a_orig.dup
2371 * a[0, 2] = 'foo' # => "foo"
2372 * a # => ["foo", 2]
2373 * a = a_orig.dup
2374 * a[6, 50] = 'foo' # => "foo"
2375 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2377 * # With argument range.
2378 * a = a_orig.dup
2379 * a[0..1] = 'foo' # => "foo"
2380 * a # => ["foo", 2]
2381 * a = a_orig.dup
2382 * a[6..50] = 'foo' # => "foo"
2383 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2385 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2387 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2389 * a = [:foo, 'bar', 2]
2390 * a[0] = 'foo' # => "foo"
2391 * a # => ["foo", "bar", 2]
2393 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2395 * a = [:foo, 'bar', 2]
2396 * a[7] = 'foo' # => "foo"
2397 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2399 * If +index+ is negative, counts backwards from the end of the array:
2401 * a = [:foo, 'bar', 2]
2402 * a[-1] = 'two' # => "two"
2403 * a # => [:foo, "bar", "two"]
2405 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2406 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2407 * and assigns +object+ at offset +start+:
2409 * a = [:foo, 'bar', 2]
2410 * a[0, 2] = 'foo' # => "foo"
2411 * a # => ["foo", 2]
2413 * If +start+ is negative, counts backwards from the end of the array:
2415 * a = [:foo, 'bar', 2]
2416 * a[-2, 2] = 'foo' # => "foo"
2417 * a # => [:foo, "foo"]
2419 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2420 * extends the array with +nil+, assigns +object+ at offset +start+,
2421 * and ignores +length+:
2423 * a = [:foo, 'bar', 2]
2424 * a[6, 50] = 'foo' # => "foo"
2425 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2427 * If +length+ is zero, shifts elements at and following offset +start+
2428 * and assigns +object+ at offset +start+:
2430 * a = [:foo, 'bar', 2]
2431 * a[1, 0] = 'foo' # => "foo"
2432 * a # => [:foo, "foo", "bar", 2]
2434 * If +length+ is too large for the existing array, does not extend the array:
2436 * a = [:foo, 'bar', 2]
2437 * a[1, 5] = 'foo' # => "foo"
2438 * a # => [:foo, "foo"]
2440 * When Range argument +range+ is given and +object+ is not an +Array+,
2441 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2442 * and assigns +object+ at offset +start+:
2444 * a = [:foo, 'bar', 2]
2445 * a[0..1] = 'foo' # => "foo"
2446 * a # => ["foo", 2]
2448 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2450 * a = [:foo, 'bar', 2]
2451 * a[-2..2] = 'foo' # => "foo"
2452 * a # => [:foo, "foo"]
2454 * If the array length is less than <tt>range.begin</tt>,
2455 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2456 * and ignores +length+:
2458 * a = [:foo, 'bar', 2]
2459 * a[6..50] = 'foo' # => "foo"
2460 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2462 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2463 * and assigns +object+ at offset +start+:
2465 * a = [:foo, 'bar', 2]
2466 * a[1..0] = 'foo' # => "foo"
2467 * a # => [:foo, "foo", "bar", 2]
2469 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2470 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2472 * a = [:foo, 'bar', 2]
2473 * a[1..-1] = 'foo' # => "foo"
2474 * a # => [:foo, "foo"]
2475 * a = [:foo, 'bar', 2]
2476 * a[1..-2] = 'foo' # => "foo"
2477 * a # => [:foo, "foo", 2]
2478 * a = [:foo, 'bar', 2]
2479 * a[1..-3] = 'foo' # => "foo"
2480 * a # => [:foo, "foo", "bar", 2]
2481 * a = [:foo, 'bar', 2]
2483 * If <tt>range.end</tt> is too large for the existing array,
2484 * replaces array elements, but does not extend the array with +nil+ values:
2486 * a = [:foo, 'bar', 2]
2487 * a[1..5] = 'foo' # => "foo"
2488 * a # => [:foo, "foo"]
2490 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2493 static VALUE
2494 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2496 long offset, beg, len;
2498 rb_check_arity(argc, 2, 3);
2499 rb_ary_modify_check(ary);
2500 if (argc == 3) {
2501 beg = NUM2LONG(argv[0]);
2502 len = NUM2LONG(argv[1]);
2503 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2505 if (FIXNUM_P(argv[0])) {
2506 offset = FIX2LONG(argv[0]);
2507 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2509 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2510 /* check if idx is Range */
2511 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2514 offset = NUM2LONG(argv[0]);
2515 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2519 * call-seq:
2520 * insert(index, *objects) -> self
2522 * Inserts the given +objects+ as elements of +self+;
2523 * returns +self+.
2525 * When +index+ is non-negative, inserts +objects+
2526 * _before_ the element at offset +index+:
2528 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2529 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2531 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2533 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2534 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2536 * When +index+ is negative, inserts +objects+
2537 * _after_ the element at offset <tt>index + self.size</tt>:
2539 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2540 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2542 * With no +objects+ given, does nothing:
2544 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2545 * a.insert(1) # => ["a", "b", "c"]
2546 * a.insert(50) # => ["a", "b", "c"]
2547 * a.insert(-50) # => ["a", "b", "c"]
2549 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2551 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2554 static VALUE
2555 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2557 long pos;
2559 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
2560 rb_ary_modify_check(ary);
2561 pos = NUM2LONG(argv[0]);
2562 if (argc == 1) return ary;
2563 if (pos == -1) {
2564 pos = RARRAY_LEN(ary);
2566 else if (pos < 0) {
2567 long minpos = -RARRAY_LEN(ary) - 1;
2568 if (pos < minpos) {
2569 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2570 pos, minpos);
2572 pos++;
2574 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2575 return ary;
2578 static VALUE
2579 rb_ary_length(VALUE ary);
2581 static VALUE
2582 ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2584 return rb_ary_length(ary);
2587 // Primitive to avoid a race condition in Array#each.
2588 // Return `true` and write `value` and `index` if the element exists.
2589 static VALUE
2590 ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
2592 long i = NUM2LONG(*index);
2593 if (i >= RARRAY_LEN(self)) {
2594 return Qfalse;
2596 *value = RARRAY_AREF(self, i);
2597 *index = LONG2NUM(i + 1);
2598 return Qtrue;
2602 * call-seq:
2603 * each {|element| ... } -> self
2604 * each -> new_enumerator
2606 * With a block given, iterates over the elements of +self+,
2607 * passing each element to the block;
2608 * returns +self+:
2610 * a = [:foo, 'bar', 2]
2611 * a.each {|element| puts "#{element.class} #{element}" }
2613 * Output:
2615 * Symbol foo
2616 * String bar
2617 * Integer 2
2619 * Allows the array to be modified during iteration:
2621 * a = [:foo, 'bar', 2]
2622 * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2624 * Output:
2626 * foo
2627 * bar
2629 * With no block given, returns a new Enumerator.
2631 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2634 VALUE
2635 rb_ary_each(VALUE ary)
2637 long i;
2638 ary_verify(ary);
2639 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2640 for (i=0; i<RARRAY_LEN(ary); i++) {
2641 rb_yield(RARRAY_AREF(ary, i));
2643 return ary;
2647 * call-seq:
2648 * each_index {|index| ... } -> self
2649 * each_index -> new_enumerator
2651 * With a block given, iterates over the elements of +self+,
2652 * passing each <i>array index</i> to the block;
2653 * returns +self+:
2655 * a = [:foo, 'bar', 2]
2656 * a.each_index {|index| puts "#{index} #{a[index]}" }
2658 * Output:
2660 * 0 foo
2661 * 1 bar
2662 * 2 2
2664 * Allows the array to be modified during iteration:
2666 * a = [:foo, 'bar', 2]
2667 * a.each_index {|index| puts index; a.clear if index > 0 }
2668 * a # => []
2670 * Output:
2675 * With no block given, returns a new Enumerator.
2677 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2680 static VALUE
2681 rb_ary_each_index(VALUE ary)
2683 long i;
2684 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2686 for (i=0; i<RARRAY_LEN(ary); i++) {
2687 rb_yield(LONG2NUM(i));
2689 return ary;
2693 * call-seq:
2694 * reverse_each {|element| ... } -> self
2695 * reverse_each -> Enumerator
2697 * When a block given, iterates backwards over the elements of +self+,
2698 * passing, in reverse order, each element to the block;
2699 * returns +self+:
2701 * a = []
2702 * [0, 1, 2].reverse_each {|element| a.push(element) }
2703 * a # => [2, 1, 0]
2705 * Allows the array to be modified during iteration:
2707 * a = ['a', 'b', 'c']
2708 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2709 * a # => []
2711 * When no block given, returns a new Enumerator.
2713 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2716 static VALUE
2717 rb_ary_reverse_each(VALUE ary)
2719 long len;
2721 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2722 len = RARRAY_LEN(ary);
2723 while (len--) {
2724 long nlen;
2725 rb_yield(RARRAY_AREF(ary, len));
2726 nlen = RARRAY_LEN(ary);
2727 if (nlen < len) {
2728 len = nlen;
2731 return ary;
2735 * call-seq:
2736 * length -> integer
2737 * size -> integer
2739 * Returns the count of elements in +self+:
2741 * [0, 1, 2].length # => 3
2742 * [].length # => 0
2744 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2747 static VALUE
2748 rb_ary_length(VALUE ary)
2750 long len = RARRAY_LEN(ary);
2751 return LONG2NUM(len);
2755 * call-seq:
2756 * array.empty? -> true or false
2758 * Returns +true+ if the count of elements in +self+ is zero,
2759 * +false+ otherwise.
2761 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2764 static VALUE
2765 rb_ary_empty_p(VALUE ary)
2767 return RBOOL(RARRAY_LEN(ary) == 0);
2770 VALUE
2771 rb_ary_dup(VALUE ary)
2773 long len = RARRAY_LEN(ary);
2774 VALUE dup = rb_ary_new2(len);
2775 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2776 ARY_SET_LEN(dup, len);
2778 ary_verify(ary);
2779 ary_verify(dup);
2780 return dup;
2783 VALUE
2784 rb_ary_resurrect(VALUE ary)
2786 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2789 extern VALUE rb_output_fs;
2791 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2793 static VALUE
2794 recursive_join(VALUE obj, VALUE argp, int recur)
2796 VALUE *arg = (VALUE *)argp;
2797 VALUE ary = arg[0];
2798 VALUE sep = arg[1];
2799 VALUE result = arg[2];
2800 int *first = (int *)arg[3];
2802 if (recur) {
2803 rb_raise(rb_eArgError, "recursive array join");
2805 else {
2806 ary_join_1(obj, ary, sep, 0, result, first);
2808 return Qnil;
2811 static long
2812 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2814 long i;
2815 VALUE val;
2817 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2818 for (i=0; i<max; i++) {
2819 val = RARRAY_AREF(ary, i);
2820 if (!RB_TYPE_P(val, T_STRING)) break;
2821 if (i > 0 && !NIL_P(sep))
2822 rb_str_buf_append(result, sep);
2823 rb_str_buf_append(result, val);
2825 return i;
2828 static void
2829 ary_join_1_str(VALUE dst, VALUE src, int *first)
2831 rb_str_buf_append(dst, src);
2832 if (*first) {
2833 rb_enc_copy(dst, src);
2834 *first = FALSE;
2838 static void
2839 ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
2841 if (val == ary) {
2842 rb_raise(rb_eArgError, "recursive array join");
2844 else {
2845 VALUE args[4];
2847 *first = FALSE;
2848 args[0] = val;
2849 args[1] = sep;
2850 args[2] = result;
2851 args[3] = (VALUE)first;
2852 rb_exec_recursive(recursive_join, obj, (VALUE)args);
2856 static void
2857 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
2859 VALUE val, tmp;
2861 for (; i<RARRAY_LEN(ary); i++) {
2862 if (i > 0 && !NIL_P(sep))
2863 rb_str_buf_append(result, sep);
2865 val = RARRAY_AREF(ary, i);
2866 if (RB_TYPE_P(val, T_STRING)) {
2867 ary_join_1_str(result, val, first);
2869 else if (RB_TYPE_P(val, T_ARRAY)) {
2870 ary_join_1_ary(val, ary, sep, result, val, first);
2872 else if (!NIL_P(tmp = rb_check_string_type(val))) {
2873 ary_join_1_str(result, tmp, first);
2875 else if (!NIL_P(tmp = rb_check_array_type(val))) {
2876 ary_join_1_ary(val, ary, sep, result, tmp, first);
2878 else {
2879 ary_join_1_str(result, rb_obj_as_string(val), first);
2884 VALUE
2885 rb_ary_join(VALUE ary, VALUE sep)
2887 long len = 1, i;
2888 VALUE val, tmp, result;
2890 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
2892 if (!NIL_P(sep)) {
2893 StringValue(sep);
2894 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
2896 for (i=0; i<RARRAY_LEN(ary); i++) {
2897 val = RARRAY_AREF(ary, i);
2898 tmp = rb_check_string_type(val);
2900 if (NIL_P(tmp) || tmp != val) {
2901 int first;
2902 long n = RARRAY_LEN(ary);
2903 if (i > n) i = n;
2904 result = rb_str_buf_new(len + (n-i)*10);
2905 rb_enc_associate(result, rb_usascii_encoding());
2906 i = ary_join_0(ary, sep, i, result);
2907 first = i == 0;
2908 ary_join_1(ary, ary, sep, i, result, &first);
2909 return result;
2912 len += RSTRING_LEN(tmp);
2915 result = rb_str_new(0, len);
2916 rb_str_set_len(result, 0);
2918 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
2920 return result;
2924 * call-seq:
2925 * array.join(separator = $,) -> new_string
2927 * Returns the new string formed by joining the converted elements of +self+;
2928 * for each element +element+:
2930 * - Converts recursively using <tt>element.join(separator)</tt>
2931 * if +element+ is a <tt>kind_of?(Array)</tt>.
2932 * - Otherwise, converts using <tt>element.to_s</tt>.
2934 * With no argument given, joins using the output field separator, <tt>$,</tt>:
2936 * a = [:foo, 'bar', 2]
2937 * $, # => nil
2938 * a.join # => "foobar2"
2940 * With string argument +separator+ given, joins using that separator:
2942 * a = [:foo, 'bar', 2]
2943 * a.join("\n") # => "foo\nbar\n2"
2945 * Joins recursively for nested arrays:
2947 * a = [:foo, [:bar, [:baz, :bat]]]
2948 * a.join # => "foobarbazbat"
2950 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2952 static VALUE
2953 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
2955 VALUE sep;
2957 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
2958 sep = rb_output_fs;
2959 if (!NIL_P(sep)) {
2960 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
2964 return rb_ary_join(ary, sep);
2967 static VALUE
2968 inspect_ary(VALUE ary, VALUE dummy, int recur)
2970 long i;
2971 VALUE s, str;
2973 if (recur) return rb_usascii_str_new_cstr("[...]");
2974 str = rb_str_buf_new2("[");
2975 for (i=0; i<RARRAY_LEN(ary); i++) {
2976 s = rb_inspect(RARRAY_AREF(ary, i));
2977 if (i > 0) rb_str_buf_cat2(str, ", ");
2978 else rb_enc_copy(str, s);
2979 rb_str_buf_append(str, s);
2981 rb_str_buf_cat2(str, "]");
2982 return str;
2986 * call-seq:
2987 * inspect -> new_string
2988 * to_s -> new_string
2990 * Returns the new string formed by calling method <tt>#inspect</tt>
2991 * on each array element:
2993 * a = [:foo, 'bar', 2]
2994 * a.inspect # => "[:foo, \"bar\", 2]"
2996 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2999 static VALUE
3000 rb_ary_inspect(VALUE ary)
3002 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
3003 return rb_exec_recursive(inspect_ary, ary, 0);
3006 VALUE
3007 rb_ary_to_s(VALUE ary)
3009 return rb_ary_inspect(ary);
3013 * call-seq:
3014 * to_a -> self or new_array
3016 * When +self+ is an instance of +Array+, returns +self+.
3018 * Otherwise, returns a new array containing the elements of +self+:
3020 * class MyArray < Array; end
3021 * my_a = MyArray.new(['foo', 'bar', 'two'])
3022 * a = my_a.to_a
3023 * a # => ["foo", "bar", "two"]
3024 * a.class # => Array # Not MyArray.
3026 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3029 static VALUE
3030 rb_ary_to_a(VALUE ary)
3032 if (rb_obj_class(ary) != rb_cArray) {
3033 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
3034 rb_ary_replace(dup, ary);
3035 return dup;
3037 return ary;
3041 * call-seq:
3042 * to_h -> new_hash
3043 * to_h {|element| ... } -> new_hash
3045 * Returns a new hash formed from +self+.
3047 * With no block given, each element of +self+ must be a 2-element sub-array;
3048 * forms each sub-array into a key-value pair in the new hash:
3050 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3051 * a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3052 * [].to_h # => {}
3054 * With a block given, the block must return a 2-element array;
3055 * calls the block with each element of +self+;
3056 * forms each returned array into a key-value pair in the returned hash:
3058 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3059 * a.to_h {|element| [element, element.class] }
3060 * # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
3062 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3065 static VALUE
3066 rb_ary_to_h(VALUE ary)
3068 long i;
3069 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
3070 int block_given = rb_block_given_p();
3072 for (i=0; i<RARRAY_LEN(ary); i++) {
3073 const VALUE e = rb_ary_elt(ary, i);
3074 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3075 const VALUE key_value_pair = rb_check_array_type(elt);
3076 if (NIL_P(key_value_pair)) {
3077 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
3078 rb_obj_class(elt), i);
3080 if (RARRAY_LEN(key_value_pair) != 2) {
3081 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
3082 i, RARRAY_LEN(key_value_pair));
3084 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3086 return hash;
3090 * call-seq:
3091 * array.to_ary -> self
3093 * Returns +self+.
3096 static VALUE
3097 rb_ary_to_ary_m(VALUE ary)
3099 return ary;
3102 static void
3103 ary_reverse(VALUE *p1, VALUE *p2)
3105 while (p1 < p2) {
3106 VALUE tmp = *p1;
3107 *p1++ = *p2;
3108 *p2-- = tmp;
3112 VALUE
3113 rb_ary_reverse(VALUE ary)
3115 VALUE *p2;
3116 long len = RARRAY_LEN(ary);
3118 rb_ary_modify(ary);
3119 if (len > 1) {
3120 RARRAY_PTR_USE(ary, p1, {
3121 p2 = p1 + len - 1; /* points last item */
3122 ary_reverse(p1, p2);
3123 }); /* WB: no new reference */
3125 return ary;
3129 * call-seq:
3130 * reverse! -> self
3132 * Reverses the order of the elements of +self+;
3133 * returns +self+:
3135 * a = [0, 1, 2]
3136 * a.reverse! # => [2, 1, 0]
3137 * a # => [2, 1, 0]
3139 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3142 static VALUE
3143 rb_ary_reverse_bang(VALUE ary)
3145 return rb_ary_reverse(ary);
3149 * call-seq:
3150 * reverse -> new_array
3152 * Returns a new array containing the elements of +self+ in reverse order:
3154 * [0, 1, 2].reverse # => [2, 1, 0]
3156 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3159 static VALUE
3160 rb_ary_reverse_m(VALUE ary)
3162 long len = RARRAY_LEN(ary);
3163 VALUE dup = rb_ary_new2(len);
3165 if (len > 0) {
3166 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3167 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3168 do *p2-- = *p1++; while (--len > 0);
3170 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3171 return dup;
3174 static inline long
3175 rotate_count(long cnt, long len)
3177 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3180 static void
3181 ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3183 if (cnt == 1) {
3184 VALUE tmp = *ptr;
3185 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3186 *(ptr + len - 1) = tmp;
3188 else if (cnt == len - 1) {
3189 VALUE tmp = *(ptr + len - 1);
3190 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3191 *ptr = tmp;
3193 else {
3194 --len;
3195 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3196 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3197 if (len > 0) ary_reverse(ptr, ptr + len);
3201 VALUE
3202 rb_ary_rotate(VALUE ary, long cnt)
3204 rb_ary_modify(ary);
3206 if (cnt != 0) {
3207 long len = RARRAY_LEN(ary);
3208 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3209 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3210 return ary;
3213 return Qnil;
3217 * call-seq:
3218 * rotate!(count = 1) -> self
3220 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3222 * With non-negative numeric +count+,
3223 * rotates +count+ elements from the beginning to the end:
3225 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3226 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3228 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3230 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3232 * If +count+ is zero, rotates no elements:
3234 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3236 * With a negative numeric +count+, rotates in the opposite direction,
3237 * from end to beginning:
3239 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3241 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3243 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3245 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3248 static VALUE
3249 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3251 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3252 rb_ary_rotate(ary, n);
3253 return ary;
3257 * call-seq:
3258 * rotate(count = 1) -> new_array
3260 * Returns a new array formed from +self+ with elements
3261 * rotated from one end to the other.
3263 * With non-negative numeric +count+,
3264 * rotates elements from the beginning to the end:
3266 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3267 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3269 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3271 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3273 * With a +count+ of zero, rotates no elements:
3275 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3277 * With negative numeric +count+, rotates in the opposite direction,
3278 * from the end to the beginning:
3280 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3282 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3284 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3286 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3289 static VALUE
3290 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3292 VALUE rotated;
3293 const VALUE *ptr;
3294 long len;
3295 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3297 len = RARRAY_LEN(ary);
3298 rotated = rb_ary_new2(len);
3299 if (len > 0) {
3300 cnt = rotate_count(cnt, len);
3301 ptr = RARRAY_CONST_PTR(ary);
3302 len -= cnt;
3303 ary_memcpy(rotated, 0, len, ptr + cnt);
3304 ary_memcpy(rotated, len, cnt, ptr);
3306 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3307 return rotated;
3310 struct ary_sort_data {
3311 VALUE ary;
3312 VALUE receiver;
3315 static VALUE
3316 sort_reentered(VALUE ary)
3318 if (RBASIC(ary)->klass) {
3319 rb_raise(rb_eRuntimeError, "sort reentered");
3321 return Qnil;
3324 static void
3325 sort_returned(struct ary_sort_data *data)
3327 if (rb_obj_frozen_p(data->receiver)) {
3328 rb_raise(rb_eFrozenError, "array frozen during sort");
3330 sort_reentered(data->ary);
3333 static int
3334 sort_1(const void *ap, const void *bp, void *dummy)
3336 struct ary_sort_data *data = dummy;
3337 VALUE retval = sort_reentered(data->ary);
3338 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3339 VALUE args[2];
3340 int n;
3342 args[0] = a;
3343 args[1] = b;
3344 retval = rb_yield_values2(2, args);
3345 n = rb_cmpint(retval, a, b);
3346 sort_returned(data);
3347 return n;
3350 static int
3351 sort_2(const void *ap, const void *bp, void *dummy)
3353 struct ary_sort_data *data = dummy;
3354 VALUE retval = sort_reentered(data->ary);
3355 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3356 int n;
3358 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3359 if ((long)a > (long)b) return 1;
3360 if ((long)a < (long)b) return -1;
3361 return 0;
3363 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3364 return rb_str_cmp(a, b);
3366 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3367 return rb_float_cmp(a, b);
3370 retval = rb_funcallv(a, id_cmp, 1, &b);
3371 n = rb_cmpint(retval, a, b);
3372 sort_returned(data);
3374 return n;
3378 * call-seq:
3379 * sort! -> self
3380 * sort! {|a, b| ... } -> self
3382 * Like Array#sort, but returns +self+ with its elements sorted in place.
3384 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3387 VALUE
3388 rb_ary_sort_bang(VALUE ary)
3390 rb_ary_modify(ary);
3391 RUBY_ASSERT(!ARY_SHARED_P(ary));
3392 if (RARRAY_LEN(ary) > 1) {
3393 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3394 struct ary_sort_data data;
3395 long len = RARRAY_LEN(ary);
3396 RBASIC_CLEAR_CLASS(tmp);
3397 data.ary = tmp;
3398 data.receiver = ary;
3399 RARRAY_PTR_USE(tmp, ptr, {
3400 ruby_qsort(ptr, len, sizeof(VALUE),
3401 rb_block_given_p()?sort_1:sort_2, &data);
3402 }); /* WB: no new reference */
3403 rb_ary_modify(ary);
3404 if (ARY_EMBED_P(tmp)) {
3405 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3406 rb_ary_unshare(ary);
3407 FL_SET_EMBED(ary);
3409 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3410 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3412 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3413 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3415 else {
3416 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3417 FL_UNSET_SHARED(ary);
3418 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3420 else {
3421 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3422 if (ARY_EMBED_P(ary)) {
3423 FL_UNSET_EMBED(ary);
3425 else if (ARY_SHARED_P(ary)) {
3426 /* ary might be destructively operated in the given block */
3427 rb_ary_unshare(ary);
3429 else {
3430 ary_heap_free(ary);
3432 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3433 ARY_SET_HEAP_LEN(ary, len);
3434 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3436 /* tmp was lost ownership for the ptr */
3437 FL_UNSET(tmp, FL_FREEZE);
3438 FL_SET_EMBED(tmp);
3439 ARY_SET_EMBED_LEN(tmp, 0);
3440 FL_SET(tmp, FL_FREEZE);
3442 /* tmp will be GC'ed. */
3443 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3445 ary_verify(ary);
3446 return ary;
3450 * call-seq:
3451 * sort -> new_array
3452 * sort {|a, b| ... } -> new_array
3454 * Returns a new array containing the elements of +self+, sorted.
3456 * With no block given, compares elements using operator <tt>#<=></tt>
3457 * (see Object#<=>):
3459 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3461 * With a block given, calls the block with each combination of pairs of elements from +self+;
3462 * for each pair +a+ and +b+, the block should return a numeric:
3464 * - Negative when +b+ is to follow +a+.
3465 * - Zero when +a+ and +b+ are equivalent.
3466 * - Positive when +a+ is to follow +b+.
3468 * Example:
3470 * a = [3, 2, 0, 1]
3471 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3472 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3474 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3475 * and may be unstable.
3477 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3480 VALUE
3481 rb_ary_sort(VALUE ary)
3483 ary = rb_ary_dup(ary);
3484 rb_ary_sort_bang(ary);
3485 return ary;
3488 static VALUE rb_ary_bsearch_index(VALUE ary);
3491 * call-seq:
3492 * bsearch {|element| ... } -> found_element or nil
3493 * bsearch -> new_enumerator
3495 * Returns the element from +self+ found by a binary search,
3496 * or +nil+ if the search found no suitable element.
3498 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3500 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3503 static VALUE
3504 rb_ary_bsearch(VALUE ary)
3506 VALUE index_result = rb_ary_bsearch_index(ary);
3508 if (FIXNUM_P(index_result)) {
3509 return rb_ary_entry(ary, FIX2LONG(index_result));
3511 return index_result;
3515 * call-seq:
3516 * bsearch_index {|element| ... } -> integer or nil
3517 * bsearch_index -> new_enumerator
3519 * Returns the integer index of the element from +self+ found by a binary search,
3520 * or +nil+ if the search found no suitable element.
3522 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3524 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3527 static VALUE
3528 rb_ary_bsearch_index(VALUE ary)
3530 long low = 0, high = RARRAY_LEN(ary), mid;
3531 int smaller = 0, satisfied = 0;
3532 VALUE v, val;
3534 RETURN_ENUMERATOR(ary, 0, 0);
3535 while (low < high) {
3536 mid = low + ((high - low) / 2);
3537 val = rb_ary_entry(ary, mid);
3538 v = rb_yield(val);
3539 if (FIXNUM_P(v)) {
3540 if (v == INT2FIX(0)) return INT2FIX(mid);
3541 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3543 else if (v == Qtrue) {
3544 satisfied = 1;
3545 smaller = 1;
3547 else if (!RTEST(v)) {
3548 smaller = 0;
3550 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3551 const VALUE zero = INT2FIX(0);
3552 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3553 case 0: return INT2FIX(mid);
3554 case 1: smaller = 0; break;
3555 case -1: smaller = 1;
3558 else {
3559 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3560 " (must be numeric, true, false or nil)",
3561 rb_obj_class(v));
3563 if (smaller) {
3564 high = mid;
3566 else {
3567 low = mid + 1;
3570 if (!satisfied) return Qnil;
3571 return INT2FIX(low);
3575 static VALUE
3576 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3578 return rb_yield(i);
3582 * call-seq:
3583 * sort_by! {|element| ... } -> self
3584 * sort_by! -> new_enumerator
3586 * With a block given, sorts the elements of +self+ in place;
3587 * returns self.
3589 * Calls the block with each successive element;
3590 * sorts elements based on the values returned from the block:
3592 * a = ['aaaa', 'bbb', 'cc', 'd']
3593 * a.sort_by! {|element| element.size }
3594 * a # => ["d", "cc", "bbb", "aaaa"]
3596 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3598 * With no block given, returns a new Enumerator.
3600 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3603 static VALUE
3604 rb_ary_sort_by_bang(VALUE ary)
3606 VALUE sorted;
3608 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3609 rb_ary_modify(ary);
3610 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3611 rb_ary_replace(ary, sorted);
3612 return ary;
3617 * call-seq:
3618 * collect {|element| ... } -> new_array
3619 * collect -> new_enumerator
3620 * map {|element| ... } -> new_array
3621 * map -> new_enumerator
3623 * With a block given, calls the block with each element of +self+;
3624 * returns a new array whose elements are the return values from the block:
3626 * a = [:foo, 'bar', 2]
3627 * a1 = a.map {|element| element.class }
3628 * a1 # => [Symbol, String, Integer]
3630 * With no block given, returns a new Enumerator.
3632 * Related: #collect!;
3633 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3636 static VALUE
3637 rb_ary_collect(VALUE ary)
3639 long i;
3640 VALUE collect;
3642 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3643 collect = rb_ary_new2(RARRAY_LEN(ary));
3644 for (i = 0; i < RARRAY_LEN(ary); i++) {
3645 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3647 return collect;
3652 * call-seq:
3653 * collect! {|element| ... } -> new_array
3654 * collect! -> new_enumerator
3655 * map! {|element| ... } -> new_array
3656 * map! -> new_enumerator
3658 * With a block given, calls the block with each element of +self+
3659 * and replaces the element with the block's return value;
3660 * returns +self+:
3662 * a = [:foo, 'bar', 2]
3663 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3665 * With no block given, returns a new Enumerator.
3667 * Related: #collect;
3668 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3671 static VALUE
3672 rb_ary_collect_bang(VALUE ary)
3674 long i;
3676 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3677 rb_ary_modify(ary);
3678 for (i = 0; i < RARRAY_LEN(ary); i++) {
3679 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3681 return ary;
3684 VALUE
3685 rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3687 VALUE result = rb_ary_new2(argc);
3688 long beg, len, i, j;
3690 for (i=0; i<argc; i++) {
3691 if (FIXNUM_P(argv[i])) {
3692 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3693 continue;
3695 /* check if idx is Range */
3696 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3697 long end = olen < beg+len ? olen : beg+len;
3698 for (j = beg; j < end; j++) {
3699 rb_ary_push(result, (*func)(obj, j));
3701 if (beg + len > j)
3702 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3703 continue;
3705 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3707 return result;
3710 static VALUE
3711 append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3713 long beg, len;
3714 if (FIXNUM_P(idx)) {
3715 beg = FIX2LONG(idx);
3717 /* check if idx is Range */
3718 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3719 if (len > 0) {
3720 const VALUE *const src = RARRAY_CONST_PTR(ary);
3721 const long end = beg + len;
3722 const long prevlen = RARRAY_LEN(result);
3723 if (beg < olen) {
3724 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3726 if (end > olen) {
3727 rb_ary_store(result, prevlen + len - 1, Qnil);
3730 return result;
3732 else {
3733 beg = NUM2LONG(idx);
3735 return rb_ary_push(result, rb_ary_entry(ary, beg));
3739 * call-seq:
3740 * values_at(*specifiers) -> new_array
3742 * Returns elements from +self+ in a new array; does not modify +self+.
3744 * The objects included in the returned array are the elements of +self+
3745 * selected by the given +specifiers+,
3746 * each of which must be a numeric index or a Range.
3748 * In brief:
3750 * a = ['a', 'b', 'c', 'd']
3752 * # Index specifiers.
3753 * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat.
3754 * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
3755 * a.values_at(-50, 50) # => [nil, nil] # Outside of self.
3757 * # Range specifiers.
3758 * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end.
3759 * a.values_at(1...3) # => ["b", "c"] # End excluded.
3760 * a.values_at(3..1) # => [] # No such elements.
3762 * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards.
3763 * a.values_at(-50..3) # Raises RangeError.
3765 * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards.
3766 * a.values_at(1..-50) # => [] # No such elements.
3768 * # Mixture of specifiers.
3769 * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]
3771 * With no +specifiers+ given, returns a new empty array:
3773 * a = ['a', 'b', 'c', 'd']
3774 * a.values_at # => []
3776 * For each numeric specifier +index+, includes an element:
3778 * - For each non-negative numeric specifier +index+ that is in-range (less than <tt>self.size</tt>),
3779 * includes the element at offset +index+:
3781 * a.values_at(0, 2) # => ["a", "c"]
3782 * a.values_at(0.1, 2.9) # => ["a", "c"]
3784 * - For each negative numeric +index+ that is in-range (greater than or equal to <tt>- self.size</tt>),
3785 * counts backwards from the end of +self+:
3787 * a.values_at(-1, -4) # => ["d", "a"]
3789 * The given indexes may be in any order, and may repeat:
3791 * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]
3793 * For each +index+ that is out-of-range, includes +nil+:
3795 * a.values_at(4, -5) # => [nil, nil]
3797 * For each Range specifier +range+, includes elements
3798 * according to <tt>range.begin</tt> and <tt>range.end</tt>:
3800 * - If both <tt>range.begin</tt> and <tt>range.end</tt>
3801 * are non-negative and in-range (less than <tt>self.size</tt>),
3802 * includes elements from index <tt>range.begin</tt>
3803 * through <tt>range.end - 1</tt> (if <tt>range.exclude_end?</tt>),
3804 * or through <tt>range.end</tt> (otherwise):
3806 * a.values_at(1..2) # => ["b", "c"]
3807 * a.values_at(1...2) # => ["b"]
3809 * - If <tt>range.begin</tt> is negative and in-range (greater than or equal to <tt>- self.size</tt>),
3810 * counts backwards from the end of +self+:
3812 * a.values_at(-2..3) # => ["c", "d"]
3814 * - If <tt>range.begin</tt> is negative and out-of-range, raises an exception:
3816 * a.values_at(-5..3) # Raises RangeError.
3818 * - If <tt>range.end</tt> is positive and out-of-range,
3819 * extends the returned array with +nil+ elements:
3821 * a.values_at(1..5) # => ["b", "c", "d", nil, nil]
3823 * - If <tt>range.end</tt> is negative and in-range,
3824 * counts backwards from the end of +self+:
3826 * a.values_at(1..-2) # => ["b", "c"]
3828 * - If <tt>range.end</tt> is negative and out-of-range,
3829 * returns an empty array:
3831 * a.values_at(1..-5) # => []
3833 * The given ranges may be in any order and may repeat:
3835 * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"]
3837 * The given specifiers may be any mixture of indexes and ranges:
3839 * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"]
3841 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3844 static VALUE
3845 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
3847 long i, olen = RARRAY_LEN(ary);
3848 VALUE result = rb_ary_new_capa(argc);
3849 for (i = 0; i < argc; ++i) {
3850 append_values_at_single(result, ary, olen, argv[i]);
3852 RB_GC_GUARD(ary);
3853 return result;
3858 * call-seq:
3859 * select {|element| ... } -> new_array
3860 * select -> new_enumerator
3861 * filter {|element| ... } -> new_array
3862 * filter -> new_enumerator
3864 * With a block given, calls the block with each element of +self+;
3865 * returns a new array containing those elements of +self+
3866 * for which the block returns a truthy value:
3868 * a = [:foo, 'bar', 2, :bam]
3869 * a.select {|element| element.to_s.start_with?('b') }
3870 * # => ["bar", :bam]
3872 * With no block given, returns a new Enumerator.
3874 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3877 static VALUE
3878 rb_ary_select(VALUE ary)
3880 VALUE result;
3881 long i;
3883 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3884 result = rb_ary_new2(RARRAY_LEN(ary));
3885 for (i = 0; i < RARRAY_LEN(ary); i++) {
3886 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
3887 rb_ary_push(result, rb_ary_elt(ary, i));
3890 return result;
3893 struct select_bang_arg {
3894 VALUE ary;
3895 long len[2];
3898 static VALUE
3899 select_bang_i(VALUE a)
3901 volatile struct select_bang_arg *arg = (void *)a;
3902 VALUE ary = arg->ary;
3903 long i1, i2;
3905 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
3906 VALUE v = RARRAY_AREF(ary, i1);
3907 if (!RTEST(rb_yield(v))) continue;
3908 if (i1 != i2) {
3909 rb_ary_store(ary, i2, v);
3911 arg->len[1] = ++i2;
3913 return (i1 == i2) ? Qnil : ary;
3916 static VALUE
3917 select_bang_ensure(VALUE a)
3919 volatile struct select_bang_arg *arg = (void *)a;
3920 VALUE ary = arg->ary;
3921 long len = RARRAY_LEN(ary);
3922 long i1 = arg->len[0], i2 = arg->len[1];
3924 if (i2 < len && i2 < i1) {
3925 long tail = 0;
3926 rb_ary_modify(ary);
3927 if (i1 < len) {
3928 tail = len - i1;
3929 RARRAY_PTR_USE(ary, ptr, {
3930 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
3933 ARY_SET_LEN(ary, i2 + tail);
3935 return ary;
3939 * call-seq:
3940 * select! {|element| ... } -> self or nil
3941 * select! -> new_enumerator
3942 * filter! {|element| ... } -> self or nil
3943 * filter! -> new_enumerator
3945 * With a block given, calls the block with each element of +self+;
3946 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3948 * Returns +self+ if any elements were removed:
3950 * a = [:foo, 'bar', 2, :bam]
3951 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3953 * Returns +nil+ if no elements were removed.
3955 * With no block given, returns a new Enumerator.
3957 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3960 static VALUE
3961 rb_ary_select_bang(VALUE ary)
3963 struct select_bang_arg args;
3965 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3966 rb_ary_modify(ary);
3968 args.ary = ary;
3969 args.len[0] = args.len[1] = 0;
3970 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
3974 * call-seq:
3975 * keep_if {|element| ... } -> self
3976 * keep_if -> new_enumerator
3978 * With a block given, calls the block with each element of +self+;
3979 * removes the element from +self+ if the block does not return a truthy value:
3981 * a = [:foo, 'bar', 2, :bam]
3982 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3984 * With no block given, returns a new Enumerator.
3986 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3989 static VALUE
3990 rb_ary_keep_if(VALUE ary)
3992 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3993 rb_ary_select_bang(ary);
3994 return ary;
3997 static void
3998 ary_resize_smaller(VALUE ary, long len)
4000 rb_ary_modify(ary);
4001 if (RARRAY_LEN(ary) > len) {
4002 ARY_SET_LEN(ary, len);
4003 if (len * 2 < ARY_CAPA(ary) &&
4004 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
4005 ary_resize_capa(ary, len * 2);
4011 * call-seq:
4012 * delete(object) -> last_removed_object
4013 * delete(object) {|element| ... } -> last_removed_object or block_return
4015 * Removes zero or more elements from +self+.
4017 * With no block given,
4018 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4019 * returns the last removed element:
4021 * a = [0, 1, 2, 2.0]
4022 * a.delete(2) # => 2.0
4023 * a # => [0, 1]
4025 * Returns +nil+ if no elements removed:
4027 * a.delete(2) # => nil
4029 * With a block given,
4030 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4032 * If any such elements are found, ignores the block
4033 * and returns the last removed element:
4035 * a = [0, 1, 2, 2.0]
4036 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4037 * a # => [0, 1]
4039 * If no such element is found, returns the block's return value:
4041 * a.delete(2) {|element| "Element #{element} not found." }
4042 * # => "Element 2 not found."
4044 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4047 VALUE
4048 rb_ary_delete(VALUE ary, VALUE item)
4050 VALUE v = item;
4051 long i1, i2;
4053 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4054 VALUE e = RARRAY_AREF(ary, i1);
4056 if (rb_equal(e, item)) {
4057 v = e;
4058 continue;
4060 if (i1 != i2) {
4061 rb_ary_store(ary, i2, e);
4063 i2++;
4065 if (RARRAY_LEN(ary) == i2) {
4066 if (rb_block_given_p()) {
4067 return rb_yield(item);
4069 return Qnil;
4072 ary_resize_smaller(ary, i2);
4074 ary_verify(ary);
4075 return v;
4078 void
4079 rb_ary_delete_same(VALUE ary, VALUE item)
4081 long i1, i2;
4083 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4084 VALUE e = RARRAY_AREF(ary, i1);
4086 if (e == item) {
4087 continue;
4089 if (i1 != i2) {
4090 rb_ary_store(ary, i2, e);
4092 i2++;
4094 if (RARRAY_LEN(ary) == i2) {
4095 return;
4098 ary_resize_smaller(ary, i2);
4101 VALUE
4102 rb_ary_delete_at(VALUE ary, long pos)
4104 long len = RARRAY_LEN(ary);
4105 VALUE del;
4107 if (pos >= len) return Qnil;
4108 if (pos < 0) {
4109 pos += len;
4110 if (pos < 0) return Qnil;
4113 rb_ary_modify(ary);
4114 del = RARRAY_AREF(ary, pos);
4115 RARRAY_PTR_USE(ary, ptr, {
4116 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4118 ARY_INCREASE_LEN(ary, -1);
4119 ary_verify(ary);
4120 return del;
4124 * call-seq:
4125 * delete_at(index) -> removed_object or nil
4127 * Removes the element of +self+ at the given +index+, which must be an
4128 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4130 * When +index+ is non-negative, deletes the element at offset +index+:
4132 * a = [:foo, 'bar', 2]
4133 * a.delete_at(1) # => "bar"
4134 * a # => [:foo, 2]
4136 * When +index+ is negative, counts backward from the end of the array:
4138 * a = [:foo, 'bar', 2]
4139 * a.delete_at(-2) # => "bar"
4140 * a # => [:foo, 2]
4142 * When +index+ is out of range, returns +nil+.
4144 * a = [:foo, 'bar', 2]
4145 * a.delete_at(3) # => nil
4146 * a.delete_at(-4) # => nil
4148 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4151 static VALUE
4152 rb_ary_delete_at_m(VALUE ary, VALUE pos)
4154 return rb_ary_delete_at(ary, NUM2LONG(pos));
4157 static VALUE
4158 ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
4160 const long orig_len = RARRAY_LEN(ary);
4162 if (len < 0) {
4163 return Qnil;
4165 else if (pos < -orig_len) {
4166 return Qnil;
4168 else if (pos < 0) {
4169 pos += orig_len;
4171 else if (orig_len < pos) {
4172 return Qnil;
4174 if (orig_len < pos + len) {
4175 len = orig_len - pos;
4177 if (len == 0) {
4178 return rb_ary_new2(0);
4180 else {
4181 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4182 rb_ary_splice(ary, pos, len, 0, 0);
4183 return arg2;
4188 * call-seq:
4189 * slice!(index) -> object or nil
4190 * slice!(start, length) -> new_array or nil
4191 * slice!(range) -> new_array or nil
4193 * Removes and returns elements from +self+.
4195 * With numeric argument +index+ given,
4196 * removes and returns the element at offset +index+:
4198 * a = ['a', 'b', 'c', 'd']
4199 * a.slice!(2) # => "c"
4200 * a # => ["a", "b", "d"]
4201 * a.slice!(2.1) # => "d"
4202 * a # => ["a", "b"]
4204 * If +index+ is negative, counts backwards from the end of +self+:
4206 * a = ['a', 'b', 'c', 'd']
4207 * a.slice!(-2) # => "c"
4208 * a # => ["a", "b", "d"]
4210 * If +index+ is out of range, returns +nil+.
4212 * With numeric arguments +start+ and +length+ given,
4213 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4214 * returns the removed objects in a new array:
4216 * a = ['a', 'b', 'c', 'd']
4217 * a.slice!(1, 2) # => ["b", "c"]
4218 * a # => ["a", "d"]
4219 * a.slice!(0.1, 1.1) # => ["a"]
4220 * a # => ["d"]
4222 * If +start+ is negative, counts backwards from the end of +self+:
4224 * a = ['a', 'b', 'c', 'd']
4225 * a.slice!(-2, 1) # => ["c"]
4226 * a # => ["a", "b", "d"]
4228 * If +start+ is out-of-range, returns +nil+:
4230 * a = ['a', 'b', 'c', 'd']
4231 * a.slice!(5, 1) # => nil
4232 * a.slice!(-5, 1) # => nil
4234 * If <tt>start + length</tt> exceeds the array size,
4235 * removes and returns all elements from offset +start+ to the end:
4237 * a = ['a', 'b', 'c', 'd']
4238 * a.slice!(2, 50) # => ["c", "d"]
4239 * a # => ["a", "b"]
4241 * If <tt>start == a.size</tt> and +length+ is non-negative,
4242 * returns a new empty array.
4244 * If +length+ is negative, returns +nil+.
4246 * With Range argument +range+ given,
4247 * treats <tt>range.min</tt> as +start+ (as above)
4248 * and <tt>range.size</tt> as +length+ (as above):
4250 * a = ['a', 'b', 'c', 'd']
4251 * a.slice!(1..2) # => ["b", "c"]
4252 * a # => ["a", "d"]
4254 * If <tt>range.start == a.size</tt>, returns a new empty array:
4256 * a = ['a', 'b', 'c', 'd']
4257 * a.slice!(4..5) # => []
4259 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4261 * a = ['a', 'b', 'c', 'd']
4262 a.slice!(5..6) # => nil
4264 * If <tt>range.start</tt> is negative,
4265 * calculates the start index by counting backwards from the end of +self+:
4267 * a = ['a', 'b', 'c', 'd']
4268 * a.slice!(-2..2) # => ["c"]
4270 * If <tt>range.end</tt> is negative,
4271 * calculates the end index by counting backwards from the end of +self+:
4273 * a = ['a', 'b', 'c', 'd']
4274 * a.slice!(0..-2) # => ["a", "b", "c"]
4276 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4279 static VALUE
4280 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4282 VALUE arg1;
4283 long pos, len;
4285 rb_ary_modify_check(ary);
4286 rb_check_arity(argc, 1, 2);
4287 arg1 = argv[0];
4289 if (argc == 2) {
4290 pos = NUM2LONG(argv[0]);
4291 len = NUM2LONG(argv[1]);
4292 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4295 if (!FIXNUM_P(arg1)) {
4296 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4297 case Qtrue:
4298 /* valid range */
4299 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4300 case Qnil:
4301 /* invalid range */
4302 return Qnil;
4303 default:
4304 /* not a range */
4305 break;
4309 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4312 static VALUE
4313 ary_reject(VALUE orig, VALUE result)
4315 long i;
4317 for (i = 0; i < RARRAY_LEN(orig); i++) {
4318 VALUE v = RARRAY_AREF(orig, i);
4320 if (!RTEST(rb_yield(v))) {
4321 rb_ary_push(result, v);
4324 return result;
4327 static VALUE
4328 reject_bang_i(VALUE a)
4330 volatile struct select_bang_arg *arg = (void *)a;
4331 VALUE ary = arg->ary;
4332 long i1, i2;
4334 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4335 VALUE v = RARRAY_AREF(ary, i1);
4336 if (RTEST(rb_yield(v))) continue;
4337 if (i1 != i2) {
4338 rb_ary_store(ary, i2, v);
4340 arg->len[1] = ++i2;
4342 return (i1 == i2) ? Qnil : ary;
4345 static VALUE
4346 ary_reject_bang(VALUE ary)
4348 struct select_bang_arg args;
4349 rb_ary_modify_check(ary);
4350 args.ary = ary;
4351 args.len[0] = args.len[1] = 0;
4352 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4356 * call-seq:
4357 * reject! {|element| ... } -> self or nil
4358 * reject! -> new_enumerator
4360 * With a block given, calls the block with each element of +self+;
4361 * removes each element for which the block returns a truthy value.
4363 * Returns +self+ if any elements removed:
4365 * a = [:foo, 'bar', 2, 'bat']
4366 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4368 * Returns +nil+ if no elements removed.
4370 * With no block given, returns a new Enumerator.
4372 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4375 static VALUE
4376 rb_ary_reject_bang(VALUE ary)
4378 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4379 rb_ary_modify(ary);
4380 return ary_reject_bang(ary);
4384 * call-seq:
4385 * reject {|element| ... } -> new_array
4386 * reject -> new_enumerator
4388 * With a block given, returns a new array whose elements are all those from +self+
4389 * for which the block returns +false+ or +nil+:
4391 * a = [:foo, 'bar', 2, 'bat']
4392 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4393 * a1 # => [:foo, 2]
4395 * With no block given, returns a new Enumerator.
4397 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4400 static VALUE
4401 rb_ary_reject(VALUE ary)
4403 VALUE rejected_ary;
4405 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4406 rejected_ary = rb_ary_new();
4407 ary_reject(ary, rejected_ary);
4408 return rejected_ary;
4412 * call-seq:
4413 * delete_if {|element| ... } -> self
4414 * delete_if -> new_numerator
4416 * With a block given, calls the block with each element of +self+;
4417 * removes the element if the block returns a truthy value;
4418 * returns +self+:
4420 * a = [:foo, 'bar', 2, 'bat']
4421 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4423 * With no block given, returns a new Enumerator.
4425 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4428 static VALUE
4429 rb_ary_delete_if(VALUE ary)
4431 ary_verify(ary);
4432 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4433 ary_reject_bang(ary);
4434 return ary;
4437 static VALUE
4438 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4440 VALUE *args = (VALUE *)cbarg;
4441 if (argc > 1) val = rb_ary_new4(argc, argv);
4442 rb_ary_push(args[0], val);
4443 if (--args[1] == 0) rb_iter_break();
4444 return Qnil;
4447 static VALUE
4448 take_items(VALUE obj, long n)
4450 VALUE result = rb_check_array_type(obj);
4451 VALUE args[2];
4453 if (n == 0) return result;
4454 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4455 result = rb_ary_new2(n);
4456 args[0] = result; args[1] = (VALUE)n;
4457 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4458 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4459 rb_obj_class(obj));
4460 return result;
4465 * call-seq:
4466 * zip(*other_arrays) -> new_array
4467 * zip(*other_arrays) {|sub_array| ... } -> nil
4469 * With no block given, combines +self+ with the collection of +other_arrays+;
4470 * returns a new array of sub-arrays:
4472 * [0, 1].zip(['zero', 'one'], [:zero, :one])
4473 * # => [[0, "zero", :zero], [1, "one", :one]]
4475 * Returned:
4477 * - The outer array is of size <tt>self.size</tt>.
4478 * - Each sub-array is of size <tt>other_arrays.size + 1</tt>.
4479 * - The _nth_ sub-array contains (in order):
4481 * - The _nth_ element of +self+.
4482 * - The _nth_ element of each of the other arrays, as available.
4484 * Example:
4486 * a = [0, 1]
4487 * zipped = a.zip(['zero', 'one'], [:zero, :one])
4488 * # => [[0, "zero", :zero], [1, "one", :one]]
4489 * zipped.size # => 2 # Same size as a.
4490 * zipped.first.size # => 3 # Size of other arrays plus 1.
4492 * When the other arrays are all the same size as +self+,
4493 * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays
4494 * (including +self+), with no omissions or additions:
4496 * a = [:a0, :a1, :a2, :a3]
4497 * b = [:b0, :b1, :b2, :b3]
4498 * c = [:c0, :c1, :c2, :c3]
4499 * d = a.zip(b, c)
4500 * pp d
4501 * # =>
4502 * [[:a0, :b0, :c0],
4503 * [:a1, :b1, :c1],
4504 * [:a2, :b2, :c2],
4505 * [:a3, :b3, :c3]]
4507 * When one of the other arrays is smaller than +self+,
4508 * pads the corresponding sub-array with +nil+ elements:
4510 * a = [:a0, :a1, :a2, :a3]
4511 * b = [:b0, :b1, :b2]
4512 * c = [:c0, :c1]
4513 * d = a.zip(b, c)
4514 * pp d
4515 * # =>
4516 * [[:a0, :b0, :c0],
4517 * [:a1, :b1, :c1],
4518 * [:a2, :b2, nil],
4519 * [:a3, nil, nil]]
4521 * When one of the other arrays is larger than +self+,
4522 * _ignores_ its trailing elements:
4524 * a = [:a0, :a1, :a2, :a3]
4525 * b = [:b0, :b1, :b2, :b3, :b4]
4526 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4527 * d = a.zip(b, c)
4528 * pp d
4529 * # =>
4530 * [[:a0, :b0, :c0],
4531 * [:a1, :b1, :c1],
4532 * [:a2, :b2, :c2],
4533 * [:a3, :b3, :c3]]
4535 * With a block given, calls the block with each of the other arrays;
4536 * returns +nil+:
4538 * d = []
4539 * a = [:a0, :a1, :a2, :a3]
4540 * b = [:b0, :b1, :b2, :b3]
4541 * c = [:c0, :c1, :c2, :c3]
4542 * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
4543 * pp d
4544 * # =>
4545 * [[:c0, :b0, :a0],
4546 * [:c1, :b1, :a1],
4547 * [:c2, :b2, :a2],
4548 * [:c3, :b3, :a3]]
4550 * For an *object* in *other_arrays* that is not actually an array,
4551 * forms the the "other array" as <tt>object.to_ary</tt>, if defined,
4552 * or as <tt>object.each.to_a</tt> otherwise.
4554 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4557 static VALUE
4558 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4560 int i, j;
4561 long len = RARRAY_LEN(ary);
4562 VALUE result = Qnil;
4564 for (i=0; i<argc; i++) {
4565 argv[i] = take_items(argv[i], len);
4568 if (rb_block_given_p()) {
4569 int arity = rb_block_arity();
4571 if (arity > 1) {
4572 VALUE work, *tmp;
4574 tmp = ALLOCV_N(VALUE, work, argc+1);
4576 for (i=0; i<RARRAY_LEN(ary); i++) {
4577 tmp[0] = RARRAY_AREF(ary, i);
4578 for (j=0; j<argc; j++) {
4579 tmp[j+1] = rb_ary_elt(argv[j], i);
4581 rb_yield_values2(argc+1, tmp);
4584 if (work) ALLOCV_END(work);
4586 else {
4587 for (i=0; i<RARRAY_LEN(ary); i++) {
4588 VALUE tmp = rb_ary_new2(argc+1);
4590 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4591 for (j=0; j<argc; j++) {
4592 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4594 rb_yield(tmp);
4598 else {
4599 result = rb_ary_new_capa(len);
4601 for (i=0; i<len; i++) {
4602 VALUE tmp = rb_ary_new_capa(argc+1);
4604 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4605 for (j=0; j<argc; j++) {
4606 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4608 rb_ary_push(result, tmp);
4612 return result;
4616 * call-seq:
4617 * transpose -> new_array
4619 * Returns a new array that is +self+
4620 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4622 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4623 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4625 * The elements of +self+ must all be the same size.
4627 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4630 static VALUE
4631 rb_ary_transpose(VALUE ary)
4633 long elen = -1, alen, i, j;
4634 VALUE tmp, result = 0;
4636 alen = RARRAY_LEN(ary);
4637 if (alen == 0) return rb_ary_dup(ary);
4638 for (i=0; i<alen; i++) {
4639 tmp = to_ary(rb_ary_elt(ary, i));
4640 if (elen < 0) { /* first element */
4641 elen = RARRAY_LEN(tmp);
4642 result = rb_ary_new2(elen);
4643 for (j=0; j<elen; j++) {
4644 rb_ary_store(result, j, rb_ary_new2(alen));
4647 else if (elen != RARRAY_LEN(tmp)) {
4648 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4649 RARRAY_LEN(tmp), elen);
4651 for (j=0; j<elen; j++) {
4652 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4655 return result;
4659 * call-seq:
4660 * initialize_copy(other_array) -> self
4661 * replace(other_array) -> self
4663 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4664 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4665 * returns +self+:
4667 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4668 * a.replace(['d', 'e']) # => ["d", "e"]
4670 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4673 VALUE
4674 rb_ary_replace(VALUE copy, VALUE orig)
4676 rb_ary_modify_check(copy);
4677 orig = to_ary(orig);
4678 if (copy == orig) return copy;
4680 rb_ary_reset(copy);
4682 /* orig has enough space to embed the contents of orig. */
4683 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4684 RUBY_ASSERT(ARY_EMBED_P(copy));
4685 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4686 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4688 /* orig is embedded but copy does not have enough space to embed the
4689 * contents of orig. */
4690 else if (ARY_EMBED_P(orig)) {
4691 long len = ARY_EMBED_LEN(orig);
4692 VALUE *ptr = ary_heap_alloc_buffer(len);
4694 FL_UNSET_EMBED(copy);
4695 ARY_SET_PTR(copy, ptr);
4696 ARY_SET_LEN(copy, len);
4697 ARY_SET_CAPA(copy, len);
4699 // No allocation and exception expected that could leave `copy` in a
4700 // bad state from the edits above.
4701 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
4703 /* Otherwise, orig is on heap and copy does not have enough space to embed
4704 * the contents of orig. */
4705 else {
4706 VALUE shared_root = ary_make_shared(orig);
4707 FL_UNSET_EMBED(copy);
4708 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4709 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4710 rb_ary_set_shared(copy, shared_root);
4712 ary_verify(copy);
4713 return copy;
4717 * call-seq:
4718 * clear -> self
4720 * Removes all elements from +self+; returns +self+:
4722 * a = [:foo, 'bar', 2]
4723 * a.clear # => []
4725 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4728 VALUE
4729 rb_ary_clear(VALUE ary)
4731 rb_ary_modify_check(ary);
4732 if (ARY_SHARED_P(ary)) {
4733 rb_ary_unshare(ary);
4734 FL_SET_EMBED(ary);
4735 ARY_SET_EMBED_LEN(ary, 0);
4737 else {
4738 ARY_SET_LEN(ary, 0);
4739 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4740 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4743 ary_verify(ary);
4744 return ary;
4748 * call-seq:
4749 * fill(object, start = nil, count = nil) -> new_array
4750 * fill(object, range) -> new_array
4751 * fill(start = nil, count = nil) {|element| ... } -> new_array
4752 * fill(range) {|element| ... } -> new_array
4754 * Replaces selected elements in +self+;
4755 * may add elements to +self+;
4756 * always returns +self+ (never a new array).
4758 * In brief:
4760 * # Non-negative start.
4761 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4762 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4764 * # Extends with specified values if necessary.
4765 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4766 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4768 * # Fills with nils if necessary.
4769 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4770 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4772 * # For negative start, counts backwards from the end.
4773 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4774 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4776 * # Range.
4777 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4778 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4780 * When arguments +start+ and +count+ are given,
4781 * they select the elements of +self+ to be replaced;
4782 * each must be an
4783 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
4784 * (or +nil+):
4786 * - +start+ specifies the zero-based offset of the first element to be replaced;
4787 * +nil+ means zero.
4788 * - +count+ is the number of consecutive elements to be replaced;
4789 * +nil+ means "all the rest."
4791 * With argument +object+ given,
4792 * that one object is used for all replacements:
4794 * o = Object.new # => #<Object:0x0000014e7bff7600>
4795 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4796 * a.fill(o, 1, 2)
4797 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
4799 * With a block given, the block is called once for each element to be replaced;
4800 * the value passed to the block is the _index_ of the element to be replaced
4801 * (not the element itself);
4802 * the block's return value replaces the element:
4804 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4805 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
4807 * For arguments +start+ and +count+:
4809 * - If +start+ is non-negative,
4810 * replaces +count+ elements beginning at offset +start+:
4812 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
4813 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4814 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
4816 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4817 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4818 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
4820 * Extends +self+ if necessary:
4822 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4823 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
4825 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4826 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
4828 * Fills with +nil+ if necessary:
4830 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
4831 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4833 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
4834 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4836 * Does nothing if +count+ is non-positive:
4838 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
4839 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
4840 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
4842 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4843 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4844 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4846 * - If +start+ is negative, counts backwards from the end of +self+:
4848 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
4849 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4851 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
4852 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4854 * Extends +self+ if necessary:
4856 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
4857 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
4859 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
4860 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
4862 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
4864 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
4865 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
4867 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4868 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4870 * Does nothing if +count+ is non-positive:
4872 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
4873 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
4875 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4876 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4878 * When argument +range+ is given,
4879 * it must be a Range object whose members are numeric;
4880 * its +begin+ and +end+ values determine the elements of +self+
4881 * to be replaced:
4883 * - If both +begin+ and +end+ are positive, they specify the first and last elements
4884 * to be replaced:
4886 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4887 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4889 * If +end+ is smaller than +begin+, replaces no elements:
4891 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
4892 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
4894 * - If either is negative (or both are negative), counts backwards from the end of +self+:
4896 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
4897 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
4898 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
4900 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4901 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4902 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4904 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
4906 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
4907 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
4909 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4910 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4912 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
4913 * replaces elements to the end of +self+:
4915 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
4916 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
4918 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
4919 * replaces elements from the beginning of +self+:
4921 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
4922 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
4924 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4927 static VALUE
4928 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
4930 VALUE item = Qundef, arg1, arg2;
4931 long beg = 0, end = 0, len = 0;
4933 if (rb_block_given_p()) {
4934 rb_scan_args(argc, argv, "02", &arg1, &arg2);
4935 argc += 1; /* hackish */
4937 else {
4938 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
4940 switch (argc) {
4941 case 1:
4942 beg = 0;
4943 len = RARRAY_LEN(ary);
4944 break;
4945 case 2:
4946 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
4947 break;
4949 /* fall through */
4950 case 3:
4951 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
4952 if (beg < 0) {
4953 beg = RARRAY_LEN(ary) + beg;
4954 if (beg < 0) beg = 0;
4956 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
4957 break;
4959 rb_ary_modify(ary);
4960 if (len < 0) {
4961 return ary;
4963 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
4964 rb_raise(rb_eArgError, "argument too big");
4966 end = beg + len;
4967 if (RARRAY_LEN(ary) < end) {
4968 if (end >= ARY_CAPA(ary)) {
4969 ary_resize_capa(ary, end);
4971 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
4972 ARY_SET_LEN(ary, end);
4975 if (UNDEF_P(item)) {
4976 VALUE v;
4977 long i;
4979 for (i=beg; i<end; i++) {
4980 v = rb_yield(LONG2NUM(i));
4981 if (i>=RARRAY_LEN(ary)) break;
4982 ARY_SET(ary, i, v);
4985 else {
4986 ary_memfill(ary, beg, len, item);
4988 return ary;
4992 * call-seq:
4993 * self + other_array -> new_array
4995 * Returns a new array containing all elements of +self+
4996 * followed by all elements of +other_array+:
4998 * a = [0, 1] + [2, 3]
4999 * a # => [0, 1, 2, 3]
5001 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5004 VALUE
5005 rb_ary_plus(VALUE x, VALUE y)
5007 VALUE z;
5008 long len, xlen, ylen;
5010 y = to_ary(y);
5011 xlen = RARRAY_LEN(x);
5012 ylen = RARRAY_LEN(y);
5013 len = xlen + ylen;
5014 z = rb_ary_new2(len);
5016 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
5017 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
5018 ARY_SET_LEN(z, len);
5019 return z;
5022 static VALUE
5023 ary_append(VALUE x, VALUE y)
5025 long n = RARRAY_LEN(y);
5026 if (n > 0) {
5027 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
5029 RB_GC_GUARD(y);
5030 return x;
5034 * call-seq:
5035 * concat(*other_arrays) -> self
5037 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
5039 * a = [0, 1]
5040 * a.concat(['two', 'three'], [:four, :five], a)
5041 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5043 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5046 static VALUE
5047 rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
5049 rb_ary_modify_check(ary);
5051 if (argc == 1) {
5052 rb_ary_concat(ary, argv[0]);
5054 else if (argc > 1) {
5055 int i;
5056 VALUE args = rb_ary_hidden_new(argc);
5057 for (i = 0; i < argc; i++) {
5058 rb_ary_concat(args, argv[i]);
5060 ary_append(ary, args);
5063 ary_verify(ary);
5064 return ary;
5067 VALUE
5068 rb_ary_concat(VALUE x, VALUE y)
5070 return ary_append(x, to_ary(y));
5074 * call-seq:
5075 * self * n -> new_array
5076 * self * string_separator -> new_string
5078 * When non-negative integer argument +n+ is given,
5079 * returns a new array built by concatenating +n+ copies of +self+:
5081 * a = ['x', 'y']
5082 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5084 * When string argument +string_separator+ is given,
5085 * equivalent to <tt>self.join(string_separator)</tt>:
5087 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
5091 static VALUE
5092 rb_ary_times(VALUE ary, VALUE times)
5094 VALUE ary2, tmp;
5095 const VALUE *ptr;
5096 long t, len;
5098 tmp = rb_check_string_type(times);
5099 if (!NIL_P(tmp)) {
5100 return rb_ary_join(ary, tmp);
5103 len = NUM2LONG(times);
5104 if (len == 0) {
5105 ary2 = ary_new(rb_cArray, 0);
5106 goto out;
5108 if (len < 0) {
5109 rb_raise(rb_eArgError, "negative argument");
5111 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
5112 rb_raise(rb_eArgError, "argument too big");
5114 len *= RARRAY_LEN(ary);
5116 ary2 = ary_new(rb_cArray, len);
5117 ARY_SET_LEN(ary2, len);
5119 ptr = RARRAY_CONST_PTR(ary);
5120 t = RARRAY_LEN(ary);
5121 if (0 < t) {
5122 ary_memcpy(ary2, 0, t, ptr);
5123 while (t <= len/2) {
5124 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5125 t *= 2;
5127 if (t < len) {
5128 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5131 out:
5132 return ary2;
5136 * call-seq:
5137 * assoc(object) -> found_array or nil
5139 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5140 * and <tt>ele[0] == object</tt>:
5142 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5143 * a.assoc(4) # => [4, 5, 6]
5145 * Returns +nil+ if no such element is found.
5147 * Related: Array#rassoc;
5148 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5151 VALUE
5152 rb_ary_assoc(VALUE ary, VALUE key)
5154 long i;
5155 VALUE v;
5157 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5158 v = rb_check_array_type(RARRAY_AREF(ary, i));
5159 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5160 rb_equal(RARRAY_AREF(v, 0), key))
5161 return v;
5163 return Qnil;
5167 * call-seq:
5168 * rassoc(object) -> found_array or nil
5170 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5171 * and <tt>ele[1] == object</tt>:
5173 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5174 * a.rassoc(4) # => [2, 4]
5175 * a.rassoc(5) # => [4, 5, 6]
5177 * Returns +nil+ if no such element is found.
5179 * Related: Array#assoc;
5180 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5183 VALUE
5184 rb_ary_rassoc(VALUE ary, VALUE value)
5186 long i;
5187 VALUE v;
5189 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5190 v = rb_check_array_type(RARRAY_AREF(ary, i));
5191 if (RB_TYPE_P(v, T_ARRAY) &&
5192 RARRAY_LEN(v) > 1 &&
5193 rb_equal(RARRAY_AREF(v, 1), value))
5194 return v;
5196 return Qnil;
5199 static VALUE
5200 recursive_equal(VALUE ary1, VALUE ary2, int recur)
5202 long i, len1;
5203 const VALUE *p1, *p2;
5205 if (recur) return Qtrue; /* Subtle! */
5207 /* rb_equal() can evacuate ptrs */
5208 p1 = RARRAY_CONST_PTR(ary1);
5209 p2 = RARRAY_CONST_PTR(ary2);
5210 len1 = RARRAY_LEN(ary1);
5212 for (i = 0; i < len1; i++) {
5213 if (*p1 != *p2) {
5214 if (rb_equal(*p1, *p2)) {
5215 len1 = RARRAY_LEN(ary1);
5216 if (len1 != RARRAY_LEN(ary2))
5217 return Qfalse;
5218 if (len1 < i)
5219 return Qtrue;
5220 p1 = RARRAY_CONST_PTR(ary1) + i;
5221 p2 = RARRAY_CONST_PTR(ary2) + i;
5223 else {
5224 return Qfalse;
5227 p1++;
5228 p2++;
5230 return Qtrue;
5234 * call-seq:
5235 * self == other_array -> true or false
5237 * Returns whether both:
5239 * - +self+ and +other_array+ are the same size.
5240 * - Their corresponding elements are the same;
5241 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5242 * <tt>self[i] == other_array[i]</tt>.
5244 * Examples:
5246 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5247 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5248 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5249 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5251 * This method is different from method Array#eql?,
5252 * which compares elements using <tt>Object#eql?</tt>.
5254 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5257 static VALUE
5258 rb_ary_equal(VALUE ary1, VALUE ary2)
5260 if (ary1 == ary2) return Qtrue;
5261 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5262 if (!rb_respond_to(ary2, idTo_ary)) {
5263 return Qfalse;
5265 return rb_equal(ary2, ary1);
5267 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5268 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5269 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5272 static VALUE
5273 recursive_eql(VALUE ary1, VALUE ary2, int recur)
5275 long i;
5277 if (recur) return Qtrue; /* Subtle! */
5278 for (i=0; i<RARRAY_LEN(ary1); i++) {
5279 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5280 return Qfalse;
5282 return Qtrue;
5286 * call-seq:
5287 * eql?(other_array) -> true or false
5289 * Returns +true+ if +self+ and +other_array+ are the same size,
5290 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5292 * a0 = [:foo, 'bar', 2]
5293 * a1 = [:foo, 'bar', 2]
5294 * a1.eql?(a0) # => true
5296 * Otherwise, returns +false+.
5298 * This method is different from method Array#==,
5299 * which compares using method <tt>Object#==</tt>.
5301 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5304 static VALUE
5305 rb_ary_eql(VALUE ary1, VALUE ary2)
5307 if (ary1 == ary2) return Qtrue;
5308 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5309 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5310 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5311 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5314 VALUE
5315 rb_ary_hash_values(long len, const VALUE *elements)
5317 long i;
5318 st_index_t h;
5319 VALUE n;
5321 h = rb_hash_start(len);
5322 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5323 for (i=0; i<len; i++) {
5324 n = rb_hash(elements[i]);
5325 h = rb_hash_uint(h, NUM2LONG(n));
5327 h = rb_hash_end(h);
5328 return ST2FIX(h);
5332 * call-seq:
5333 * hash -> integer
5335 * Returns the integer hash value for +self+.
5337 * Two arrays with the same content will have the same hash value
5338 * (and will compare using eql?):
5340 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5341 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5342 * ['a', 'b'].hash == ['a'].hash # => false
5346 static VALUE
5347 rb_ary_hash(VALUE ary)
5349 return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
5353 * call-seq:
5354 * include?(object) -> true or false
5356 * Returns whether for some element +element+ in +self+,
5357 * <tt>object == element</tt>:
5359 * [0, 1, 2].include?(2) # => true
5360 * [0, 1, 2].include?(2.0) # => true
5361 * [0, 1, 2].include?(2.1) # => false
5363 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5366 VALUE
5367 rb_ary_includes(VALUE ary, VALUE item)
5369 long i;
5370 VALUE e;
5372 for (i=0; i<RARRAY_LEN(ary); i++) {
5373 e = RARRAY_AREF(ary, i);
5374 if (rb_equal(e, item)) {
5375 return Qtrue;
5378 return Qfalse;
5381 static VALUE
5382 rb_ary_includes_by_eql(VALUE ary, VALUE item)
5384 long i;
5385 VALUE e;
5387 for (i=0; i<RARRAY_LEN(ary); i++) {
5388 e = RARRAY_AREF(ary, i);
5389 if (rb_eql(item, e)) {
5390 return Qtrue;
5393 return Qfalse;
5396 static VALUE
5397 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5399 long i, len;
5401 if (recur) return Qundef; /* Subtle! */
5402 len = RARRAY_LEN(ary1);
5403 if (len > RARRAY_LEN(ary2)) {
5404 len = RARRAY_LEN(ary2);
5406 for (i=0; i<len; i++) {
5407 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5408 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5409 if (v != INT2FIX(0)) {
5410 return v;
5413 return Qundef;
5417 * call-seq:
5418 * self <=> other_array -> -1, 0, or 1
5420 * Returns -1, 0, or 1 as +self+ is determined
5421 * to be less than, equal to, or greater than +other_array+.
5423 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5425 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5426 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5428 * [0, 1, 2] <=> [0, 0, 2] # => 1
5430 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5432 * [0, 1, 2] <=> [0, 2, 2] # => -1
5434 * - Continues if <tt>result[i]</tt> is 0.
5436 * When every +result+ is 0,
5437 * returns <tt>self.size <=> other_array.size</tt>
5438 * (see Integer#<=>):
5440 * [0, 1, 2] <=> [0, 1] # => 1
5441 * [0, 1, 2] <=> [0, 1, 2] # => 0
5442 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5444 * Note that when +other_array+ is larger than +self+,
5445 * its trailing elements do not affect the result:
5447 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5448 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5449 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5451 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5454 VALUE
5455 rb_ary_cmp(VALUE ary1, VALUE ary2)
5457 long len;
5458 VALUE v;
5460 ary2 = rb_check_array_type(ary2);
5461 if (NIL_P(ary2)) return Qnil;
5462 if (ary1 == ary2) return INT2FIX(0);
5463 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5464 if (!UNDEF_P(v)) return v;
5465 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5466 if (len == 0) return INT2FIX(0);
5467 if (len > 0) return INT2FIX(1);
5468 return INT2FIX(-1);
5471 static VALUE
5472 ary_add_hash(VALUE hash, VALUE ary)
5474 long i;
5476 for (i=0; i<RARRAY_LEN(ary); i++) {
5477 VALUE elt = RARRAY_AREF(ary, i);
5478 rb_hash_add_new_element(hash, elt, elt);
5480 return hash;
5483 static inline VALUE
5484 ary_tmp_hash_new(VALUE ary)
5486 long size = RARRAY_LEN(ary);
5487 VALUE hash = rb_hash_new_with_size(size);
5489 RBASIC_CLEAR_CLASS(hash);
5490 return hash;
5493 static VALUE
5494 ary_make_hash(VALUE ary)
5496 VALUE hash = ary_tmp_hash_new(ary);
5497 return ary_add_hash(hash, ary);
5500 static VALUE
5501 ary_add_hash_by(VALUE hash, VALUE ary)
5503 long i;
5505 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5506 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5507 rb_hash_add_new_element(hash, k, v);
5509 return hash;
5512 static VALUE
5513 ary_make_hash_by(VALUE ary)
5515 VALUE hash = ary_tmp_hash_new(ary);
5516 return ary_add_hash_by(hash, ary);
5520 * call-seq:
5521 * self - other_array -> new_array
5523 * Returns a new array containing only those elements of +self+
5524 * that are not found in +other_array+;
5525 * the order from +self+ is preserved:
5527 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5528 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5529 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5531 * Element are compared using method <tt>#eql?</tt>
5532 * (as defined in each element of +self+).
5534 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5537 VALUE
5538 rb_ary_diff(VALUE ary1, VALUE ary2)
5540 VALUE ary3;
5541 VALUE hash;
5542 long i;
5544 ary2 = to_ary(ary2);
5545 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5546 ary3 = rb_ary_new();
5548 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5549 for (i=0; i<RARRAY_LEN(ary1); i++) {
5550 VALUE elt = rb_ary_elt(ary1, i);
5551 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5552 rb_ary_push(ary3, elt);
5554 return ary3;
5557 hash = ary_make_hash(ary2);
5558 for (i=0; i<RARRAY_LEN(ary1); i++) {
5559 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5560 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5563 return ary3;
5567 * call-seq:
5568 * difference(*other_arrays = []) -> new_array
5570 * Returns a new array containing only those elements from +self+
5571 * that are not found in any of the given +other_arrays+;
5572 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5574 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5575 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5576 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5577 * [0, 1, 2].difference # => [0, 1, 2]
5579 * Returns a copy of +self+ if no arguments are given.
5581 * Related: Array#-;
5582 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5585 static VALUE
5586 rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5588 VALUE ary_diff;
5589 long i, length;
5590 volatile VALUE t0;
5591 bool *is_hash = ALLOCV_N(bool, t0, argc);
5592 ary_diff = rb_ary_new();
5593 length = RARRAY_LEN(ary);
5595 for (i = 0; i < argc; i++) {
5596 argv[i] = to_ary(argv[i]);
5597 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5598 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5601 for (i = 0; i < RARRAY_LEN(ary); i++) {
5602 int j;
5603 VALUE elt = rb_ary_elt(ary, i);
5604 for (j = 0; j < argc; j++) {
5605 if (is_hash[j]) {
5606 if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
5607 break;
5609 else {
5610 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5613 if (j == argc) rb_ary_push(ary_diff, elt);
5616 ALLOCV_END(t0);
5618 return ary_diff;
5623 * call-seq:
5624 * self & other_array -> new_array
5626 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5627 * that is, containing those elements found in both +self+ and +other_array+:
5629 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5631 * Omits duplicates:
5633 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5635 * Preserves order from +self+:
5637 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5639 * Identifies common elements using method <tt>#eql?</tt>
5640 * (as defined in each element of +self+).
5642 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5646 static VALUE
5647 rb_ary_and(VALUE ary1, VALUE ary2)
5649 VALUE hash, ary3, v;
5650 st_data_t vv;
5651 long i;
5653 ary2 = to_ary(ary2);
5654 ary3 = rb_ary_new();
5655 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5657 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5658 for (i=0; i<RARRAY_LEN(ary1); i++) {
5659 v = RARRAY_AREF(ary1, i);
5660 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5661 if (rb_ary_includes_by_eql(ary3, v)) continue;
5662 rb_ary_push(ary3, v);
5664 return ary3;
5667 hash = ary_make_hash(ary2);
5669 for (i=0; i<RARRAY_LEN(ary1); i++) {
5670 v = RARRAY_AREF(ary1, i);
5671 vv = (st_data_t)v;
5672 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5673 rb_ary_push(ary3, v);
5677 return ary3;
5681 * call-seq:
5682 * intersection(*other_arrays) -> new_array
5684 * Returns a new array containing each element in +self+ that is +#eql?+
5685 * to at least one element in each of the given +other_arrays+;
5686 * duplicates are omitted:
5688 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5690 * Each element must correctly implement method <tt>#hash</tt>.
5692 * Order from +self+ is preserved:
5694 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5696 * Returns a copy of +self+ if no arguments are given.
5698 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5701 static VALUE
5702 rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5704 VALUE result = rb_ary_dup(ary);
5705 int i;
5707 for (i = 0; i < argc; i++) {
5708 result = rb_ary_and(result, argv[i]);
5711 return result;
5714 static int
5715 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5717 if (existing) return ST_STOP;
5718 *key = *value = (VALUE)arg;
5719 return ST_CONTINUE;
5722 static void
5723 rb_ary_union(VALUE ary_union, VALUE ary)
5725 long i;
5726 for (i = 0; i < RARRAY_LEN(ary); i++) {
5727 VALUE elt = rb_ary_elt(ary, i);
5728 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5729 rb_ary_push(ary_union, elt);
5733 static void
5734 rb_ary_union_hash(VALUE hash, VALUE ary2)
5736 long i;
5737 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5738 VALUE elt = RARRAY_AREF(ary2, i);
5739 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5740 RB_OBJ_WRITTEN(hash, Qundef, elt);
5746 * call-seq:
5747 * self | other_array -> new_array
5749 * Returns the union of +self+ and +other_array+;
5750 * duplicates are removed; order is preserved;
5751 * items are compared using <tt>eql?</tt>:
5753 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5754 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5755 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5757 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5760 static VALUE
5761 rb_ary_or(VALUE ary1, VALUE ary2)
5763 VALUE hash;
5765 ary2 = to_ary(ary2);
5766 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5767 VALUE ary3 = rb_ary_new();
5768 rb_ary_union(ary3, ary1);
5769 rb_ary_union(ary3, ary2);
5770 return ary3;
5773 hash = ary_make_hash(ary1);
5774 rb_ary_union_hash(hash, ary2);
5776 return rb_hash_values(hash);
5780 * call-seq:
5781 * union(*other_arrays) -> new_array
5783 * Returns a new array that is the union of the elements of +self+
5784 * and all given arrays +other_arrays+;
5785 * items are compared using <tt>eql?</tt>:
5787 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5789 * Removes duplicates (preserving the first found):
5791 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5793 * Preserves order (preserving the position of the first found):
5795 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
5797 * With no arguments given, returns a copy of +self+.
5799 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5802 static VALUE
5803 rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
5805 int i;
5806 long sum;
5807 VALUE hash;
5809 sum = RARRAY_LEN(ary);
5810 for (i = 0; i < argc; i++) {
5811 argv[i] = to_ary(argv[i]);
5812 sum += RARRAY_LEN(argv[i]);
5815 if (sum <= SMALL_ARRAY_LEN) {
5816 VALUE ary_union = rb_ary_new();
5818 rb_ary_union(ary_union, ary);
5819 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5821 return ary_union;
5824 hash = ary_make_hash(ary);
5825 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5827 return rb_hash_values(hash);
5831 * call-seq:
5832 * intersect?(other_array) -> true or false
5834 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5836 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5837 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5839 * Each element must correctly implement method <tt>#hash</tt>.
5841 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5844 static VALUE
5845 rb_ary_intersect_p(VALUE ary1, VALUE ary2)
5847 VALUE hash, v, result, shorter, longer;
5848 st_data_t vv;
5849 long i;
5851 ary2 = to_ary(ary2);
5852 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
5854 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5855 for (i=0; i<RARRAY_LEN(ary1); i++) {
5856 v = RARRAY_AREF(ary1, i);
5857 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
5859 return Qfalse;
5862 shorter = ary1;
5863 longer = ary2;
5864 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
5865 longer = ary1;
5866 shorter = ary2;
5869 hash = ary_make_hash(shorter);
5870 result = Qfalse;
5872 for (i=0; i<RARRAY_LEN(longer); i++) {
5873 v = RARRAY_AREF(longer, i);
5874 vv = (st_data_t)v;
5875 if (rb_hash_stlike_lookup(hash, vv, 0)) {
5876 result = Qtrue;
5877 break;
5881 return result;
5884 static VALUE
5885 ary_max_generic(VALUE ary, long i, VALUE vmax)
5887 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5889 VALUE v;
5890 for (; i < RARRAY_LEN(ary); ++i) {
5891 v = RARRAY_AREF(ary, i);
5893 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
5894 vmax = v;
5898 return vmax;
5901 static VALUE
5902 ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
5904 const long n = RARRAY_LEN(ary);
5905 RUBY_ASSERT(i > 0 && i < n);
5906 RUBY_ASSERT(FIXNUM_P(vmax));
5908 VALUE v;
5909 for (; i < n; ++i) {
5910 v = RARRAY_AREF(ary, i);
5912 if (FIXNUM_P(v)) {
5913 if ((long)vmax < (long)v) {
5914 vmax = v;
5917 else {
5918 return ary_max_generic(ary, i, vmax);
5922 return vmax;
5925 static VALUE
5926 ary_max_opt_float(VALUE ary, long i, VALUE vmax)
5928 const long n = RARRAY_LEN(ary);
5929 RUBY_ASSERT(i > 0 && i < n);
5930 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax));
5932 VALUE v;
5933 for (; i < n; ++i) {
5934 v = RARRAY_AREF(ary, i);
5936 if (RB_FLOAT_TYPE_P(v)) {
5937 if (rb_float_cmp(vmax, v) < 0) {
5938 vmax = v;
5941 else {
5942 return ary_max_generic(ary, i, vmax);
5946 return vmax;
5949 static VALUE
5950 ary_max_opt_string(VALUE ary, long i, VALUE vmax)
5952 const long n = RARRAY_LEN(ary);
5953 RUBY_ASSERT(i > 0 && i < n);
5954 RUBY_ASSERT(STRING_P(vmax));
5956 VALUE v;
5957 for (; i < n; ++i) {
5958 v = RARRAY_AREF(ary, i);
5960 if (STRING_P(v)) {
5961 if (rb_str_cmp(vmax, v) < 0) {
5962 vmax = v;
5965 else {
5966 return ary_max_generic(ary, i, vmax);
5970 return vmax;
5974 * call-seq:
5975 * max -> element
5976 * max(count) -> new_array
5977 * max {|a, b| ... } -> element
5978 * max(count) {|a, b| ... } -> new_array
5980 * Returns one of the following:
5982 * - The maximum-valued element from +self+.
5983 * - A new array of maximum-valued elements from +self+.
5985 * Does not modify +self+.
5987 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
5988 * with a numeric.
5990 * With no argument and no block, returns the element in +self+
5991 * having the maximum value per method <tt>#<=></tt>:
5993 * [1, 0, 3, 2].max # => 3
5995 * With non-negative numeric argument +count+ and no block,
5996 * returns a new array with at most +count+ elements,
5997 * in descending order, per method <tt>#<=></tt>:
5999 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
6000 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
6001 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
6002 * [1, 0, 3, 2].max(0) # => []
6004 * With a block given, the block must return a numeric.
6006 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6007 * returns the element having the maximum value per the block:
6009 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
6010 * # => "000"
6012 * With non-negative numeric argument +count+ and a block,
6013 * returns a new array with at most +count+ elements,
6014 * in descending order, per the block:
6016 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
6017 * # => ["000", "00"]
6019 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6021 static VALUE
6022 rb_ary_max(int argc, VALUE *argv, VALUE ary)
6024 VALUE result = Qundef, v;
6025 VALUE num;
6026 long i;
6028 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6029 return rb_nmin_run(ary, num, 0, 1, 1);
6031 const long n = RARRAY_LEN(ary);
6032 if (rb_block_given_p()) {
6033 for (i = 0; i < RARRAY_LEN(ary); i++) {
6034 v = RARRAY_AREF(ary, i);
6035 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
6036 result = v;
6040 else if (n > 0) {
6041 result = RARRAY_AREF(ary, 0);
6042 if (n > 1) {
6043 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6044 return ary_max_opt_fixnum(ary, 1, result);
6046 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6047 return ary_max_opt_string(ary, 1, result);
6049 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6050 return ary_max_opt_float(ary, 1, result);
6052 else {
6053 return ary_max_generic(ary, 1, result);
6057 if (UNDEF_P(result)) return Qnil;
6058 return result;
6061 static VALUE
6062 ary_min_generic(VALUE ary, long i, VALUE vmin)
6064 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6066 VALUE v;
6067 for (; i < RARRAY_LEN(ary); ++i) {
6068 v = RARRAY_AREF(ary, i);
6070 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
6071 vmin = v;
6075 return vmin;
6078 static VALUE
6079 ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
6081 const long n = RARRAY_LEN(ary);
6082 RUBY_ASSERT(i > 0 && i < n);
6083 RUBY_ASSERT(FIXNUM_P(vmin));
6085 VALUE a;
6086 for (; i < n; ++i) {
6087 a = RARRAY_AREF(ary, i);
6089 if (FIXNUM_P(a)) {
6090 if ((long)vmin > (long)a) {
6091 vmin = a;
6094 else {
6095 return ary_min_generic(ary, i, vmin);
6099 return vmin;
6102 static VALUE
6103 ary_min_opt_float(VALUE ary, long i, VALUE vmin)
6105 const long n = RARRAY_LEN(ary);
6106 RUBY_ASSERT(i > 0 && i < n);
6107 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin));
6109 VALUE a;
6110 for (; i < n; ++i) {
6111 a = RARRAY_AREF(ary, i);
6113 if (RB_FLOAT_TYPE_P(a)) {
6114 if (rb_float_cmp(vmin, a) > 0) {
6115 vmin = a;
6118 else {
6119 return ary_min_generic(ary, i, vmin);
6123 return vmin;
6126 static VALUE
6127 ary_min_opt_string(VALUE ary, long i, VALUE vmin)
6129 const long n = RARRAY_LEN(ary);
6130 RUBY_ASSERT(i > 0 && i < n);
6131 RUBY_ASSERT(STRING_P(vmin));
6133 VALUE a;
6134 for (; i < n; ++i) {
6135 a = RARRAY_AREF(ary, i);
6137 if (STRING_P(a)) {
6138 if (rb_str_cmp(vmin, a) > 0) {
6139 vmin = a;
6142 else {
6143 return ary_min_generic(ary, i, vmin);
6147 return vmin;
6151 * call-seq:
6152 * min -> element
6153 * min(count) -> new_array
6154 * min {|a, b| ... } -> element
6155 * min(count) {|a, b| ... } -> new_array
6157 * Returns one of the following:
6159 * - The minimum-valued element from +self+.
6160 * - A new array of minimum-valued elements from +self+.
6162 * Does not modify +self+.
6164 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6165 * with a numeric.
6167 * With no argument and no block, returns the element in +self+
6168 * having the minimum value per method <tt>#<=></tt>:
6170 * [1, 0, 3, 2].min # => 0
6172 * With non-negative numeric argument +count+ and no block,
6173 * returns a new array with at most +count+ elements,
6174 * in ascending order, per method <tt>#<=></tt>:
6176 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6177 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6178 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6179 * [1, 0, 3, 2].min(0) # => []
6181 * With a block given, the block must return a numeric.
6183 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6184 * returns the element having the minimum value per the block:
6186 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6187 * # => ""
6189 * With non-negative numeric argument +count+ and a block,
6190 * returns a new array with at most +count+ elements,
6191 * in ascending order, per the block:
6193 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6194 * # => ["", "0"]
6196 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6198 static VALUE
6199 rb_ary_min(int argc, VALUE *argv, VALUE ary)
6201 VALUE result = Qundef, v;
6202 VALUE num;
6203 long i;
6205 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6206 return rb_nmin_run(ary, num, 0, 0, 1);
6208 const long n = RARRAY_LEN(ary);
6209 if (rb_block_given_p()) {
6210 for (i = 0; i < RARRAY_LEN(ary); i++) {
6211 v = RARRAY_AREF(ary, i);
6212 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6213 result = v;
6217 else if (n > 0) {
6218 result = RARRAY_AREF(ary, 0);
6219 if (n > 1) {
6220 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6221 return ary_min_opt_fixnum(ary, 1, result);
6223 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6224 return ary_min_opt_string(ary, 1, result);
6226 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6227 return ary_min_opt_float(ary, 1, result);
6229 else {
6230 return ary_min_generic(ary, 1, result);
6234 if (UNDEF_P(result)) return Qnil;
6235 return result;
6239 * call-seq:
6240 * minmax -> array
6241 * minmax {|a, b| ... } -> array
6243 * Returns a 2-element array containing the minimum-valued and maximum-valued
6244 * elements from +self+;
6245 * does not modify +self+.
6247 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6249 * [1, 0, 3, 2].minmax # => [0, 3]
6251 * With a block given, the block must return a numeric;
6252 * the block is called <tt>self.size - 1</tt> times to compare elements;
6253 * returns the elements having the minimum and maximum values per the block:
6255 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6256 * # => ["", "000"]
6258 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6260 static VALUE
6261 rb_ary_minmax(VALUE ary)
6263 if (rb_block_given_p()) {
6264 return rb_call_super(0, NULL);
6266 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6269 static int
6270 push_value(st_data_t key, st_data_t val, st_data_t ary)
6272 rb_ary_push((VALUE)ary, (VALUE)val);
6273 return ST_CONTINUE;
6277 * call-seq:
6278 * uniq! -> self or nil
6279 * uniq! {|element| ... } -> self or nil
6281 * Removes duplicate elements from +self+, the first occurrence always being retained;
6282 * returns +self+ if any elements removed, +nil+ otherwise.
6284 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6285 * to compare elements:
6287 * a = [0, 0, 1, 1, 2, 2]
6288 * a.uniq! # => [0, 1, 2]
6289 * a.uniq! # => nil
6291 * With a block given, calls the block for each element;
6292 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6293 * to compare <i>block return values</i>;
6294 * that is, an element is a duplicate if its block return value
6295 * is the same as that of a previous element:
6297 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6298 * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
6299 * a.uniq! {|element| element.size } # => nil
6301 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6303 static VALUE
6304 rb_ary_uniq_bang(VALUE ary)
6306 VALUE hash;
6307 long hash_size;
6309 rb_ary_modify_check(ary);
6310 if (RARRAY_LEN(ary) <= 1)
6311 return Qnil;
6312 if (rb_block_given_p())
6313 hash = ary_make_hash_by(ary);
6314 else
6315 hash = ary_make_hash(ary);
6317 hash_size = RHASH_SIZE(hash);
6318 if (RARRAY_LEN(ary) == hash_size) {
6319 return Qnil;
6321 rb_ary_modify_check(ary);
6322 ARY_SET_LEN(ary, 0);
6323 if (ARY_SHARED_P(ary)) {
6324 rb_ary_unshare(ary);
6325 FL_SET_EMBED(ary);
6327 ary_resize_capa(ary, hash_size);
6328 rb_hash_foreach(hash, push_value, ary);
6330 return ary;
6334 * call-seq:
6335 * uniq -> new_array
6336 * uniq {|element| ... } -> new_array
6338 * Returns a new array containing those elements from +self+ that are not duplicates,
6339 * the first occurrence always being retained.
6341 * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
6342 * to compare elements:
6344 * a = [0, 0, 1, 1, 2, 2]
6345 * a.uniq # => [0, 1, 2]
6347 * With a block given, calls the block for each element;
6348 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6349 * to compare <i>block return values</i>;
6350 * that is, an element is a duplicate if its block return value
6351 * is the same as that of a previous element:
6353 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6354 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6356 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6359 static VALUE
6360 rb_ary_uniq(VALUE ary)
6362 VALUE hash, uniq;
6364 if (RARRAY_LEN(ary) <= 1) {
6365 hash = 0;
6366 uniq = rb_ary_dup(ary);
6368 else if (rb_block_given_p()) {
6369 hash = ary_make_hash_by(ary);
6370 uniq = rb_hash_values(hash);
6372 else {
6373 hash = ary_make_hash(ary);
6374 uniq = rb_hash_values(hash);
6377 return uniq;
6381 * call-seq:
6382 * compact! -> self or nil
6384 * Removes all +nil+ elements from +self+;
6385 * Returns +self+ if any elements are removed, +nil+ otherwise:
6387 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6388 * a.compact! # => [0, false, "", [], {}]
6389 * a # => [0, false, "", [], {}]
6390 * a.compact! # => nil
6392 * Related: Array#compact;
6393 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6396 static VALUE
6397 rb_ary_compact_bang(VALUE ary)
6399 VALUE *p, *t, *end;
6400 long n;
6402 rb_ary_modify(ary);
6403 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6404 end = p + RARRAY_LEN(ary);
6406 while (t < end) {
6407 if (NIL_P(*t)) t++;
6408 else *p++ = *t++;
6410 n = p - RARRAY_CONST_PTR(ary);
6411 if (RARRAY_LEN(ary) == n) {
6412 return Qnil;
6414 ary_resize_smaller(ary, n);
6416 return ary;
6420 * call-seq:
6421 * compact -> new_array
6423 * Returns a new array containing only the non-+nil+ elements from +self+;
6424 * element order is preserved:
6426 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6427 * a.compact # => [0, false, "", [], {}]
6429 * Related: Array#compact!;
6430 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6433 static VALUE
6434 rb_ary_compact(VALUE ary)
6436 ary = rb_ary_dup(ary);
6437 rb_ary_compact_bang(ary);
6438 return ary;
6442 * call-seq:
6443 * count -> integer
6444 * count(object) -> integer
6445 * count {|element| ... } -> integer
6447 * Returns a count of specified elements.
6449 * With no argument and no block, returns the count of all elements:
6451 * [0, :one, 'two', 3, 3.0].count # => 5
6453 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6455 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6457 * With no argument and a block given, calls the block with each element;
6458 * returns the count of elements for which the block returns a truthy value:
6460 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6462 * With argument +object+ and a block given, issues a warning, ignores the block,
6463 * and returns the count of elements <tt>==</tt> to +object+.
6465 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6468 static VALUE
6469 rb_ary_count(int argc, VALUE *argv, VALUE ary)
6471 long i, n = 0;
6473 if (rb_check_arity(argc, 0, 1) == 0) {
6474 VALUE v;
6476 if (!rb_block_given_p())
6477 return LONG2NUM(RARRAY_LEN(ary));
6479 for (i = 0; i < RARRAY_LEN(ary); i++) {
6480 v = RARRAY_AREF(ary, i);
6481 if (RTEST(rb_yield(v))) n++;
6484 else {
6485 VALUE obj = argv[0];
6487 if (rb_block_given_p()) {
6488 rb_warn("given block not used");
6490 for (i = 0; i < RARRAY_LEN(ary); i++) {
6491 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6495 return LONG2NUM(n);
6498 static VALUE
6499 flatten(VALUE ary, int level)
6501 long i;
6502 VALUE stack, result, tmp = 0, elt;
6503 VALUE memo = Qfalse;
6505 for (i = 0; i < RARRAY_LEN(ary); i++) {
6506 elt = RARRAY_AREF(ary, i);
6507 tmp = rb_check_array_type(elt);
6508 if (!NIL_P(tmp)) {
6509 break;
6512 if (i == RARRAY_LEN(ary)) {
6513 return ary;
6516 result = ary_new(0, RARRAY_LEN(ary));
6517 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6518 ARY_SET_LEN(result, i);
6520 stack = ary_new(0, ARY_DEFAULT_SIZE);
6521 rb_ary_push(stack, ary);
6522 rb_ary_push(stack, LONG2NUM(i + 1));
6524 if (level < 0) {
6525 memo = rb_obj_hide(rb_ident_hash_new());
6526 rb_hash_aset(memo, ary, Qtrue);
6527 rb_hash_aset(memo, tmp, Qtrue);
6530 ary = tmp;
6531 i = 0;
6533 while (1) {
6534 while (i < RARRAY_LEN(ary)) {
6535 elt = RARRAY_AREF(ary, i++);
6536 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6537 rb_ary_push(result, elt);
6538 continue;
6540 tmp = rb_check_array_type(elt);
6541 if (RBASIC(result)->klass) {
6542 if (RTEST(memo)) {
6543 rb_hash_clear(memo);
6545 rb_raise(rb_eRuntimeError, "flatten reentered");
6547 if (NIL_P(tmp)) {
6548 rb_ary_push(result, elt);
6550 else {
6551 if (memo) {
6552 if (rb_hash_aref(memo, tmp) == Qtrue) {
6553 rb_hash_clear(memo);
6554 rb_raise(rb_eArgError, "tried to flatten recursive array");
6556 rb_hash_aset(memo, tmp, Qtrue);
6558 rb_ary_push(stack, ary);
6559 rb_ary_push(stack, LONG2NUM(i));
6560 ary = tmp;
6561 i = 0;
6564 if (RARRAY_LEN(stack) == 0) {
6565 break;
6567 if (memo) {
6568 rb_hash_delete(memo, ary);
6570 tmp = rb_ary_pop(stack);
6571 i = NUM2LONG(tmp);
6572 ary = rb_ary_pop(stack);
6575 if (memo) {
6576 rb_hash_clear(memo);
6579 RBASIC_SET_CLASS(result, rb_cArray);
6580 return result;
6584 * call-seq:
6585 * flatten!(depth = nil) -> self or nil
6587 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6588 * +depth+ must be an
6589 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6590 * or +nil+.
6591 * At each level of recursion:
6593 * - Each element that is an array is "flattened"
6594 * (that is, replaced by its individual array elements).
6595 * - Each element that is not an array is unchanged
6596 * (even if the element is an object that has instance method +flatten+).
6598 * Returns +nil+ if no elements were flattened.
6600 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6602 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6603 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6604 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6605 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6606 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6607 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6609 * With +nil+ or negative argument +depth+, flattens all levels:
6611 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6612 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6614 * Related: Array#flatten;
6615 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6618 static VALUE
6619 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6621 int mod = 0, level = -1;
6622 VALUE result, lv;
6624 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6625 rb_ary_modify_check(ary);
6626 if (!NIL_P(lv)) level = NUM2INT(lv);
6627 if (level == 0) return Qnil;
6629 result = flatten(ary, level);
6630 if (result == ary) {
6631 return Qnil;
6633 if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6634 rb_ary_replace(ary, result);
6635 if (mod) ARY_SET_EMBED_LEN(result, 0);
6637 return ary;
6641 * call-seq:
6642 * flatten(depth = nil) -> new_array
6644 * Returns a new array that is a recursive flattening of +self+
6645 * to +depth+ levels of recursion;
6646 * +depth+ must be an
6647 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6648 * or +nil+.
6649 * At each level of recursion:
6651 * - Each element that is an array is "flattened"
6652 * (that is, replaced by its individual array elements).
6653 * - Each element that is not an array is unchanged
6654 * (even if the element is an object that has instance method +flatten+).
6656 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6658 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6659 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6660 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6661 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6662 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6663 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6664 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6666 * With +nil+ or negative +depth+, flattens all levels.
6668 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6669 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6671 * Related: Array#flatten!;
6672 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6675 static VALUE
6676 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6678 int level = -1;
6679 VALUE result;
6681 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6682 level = NUM2INT(argv[0]);
6683 if (level == 0) return ary_make_shared_copy(ary);
6686 result = flatten(ary, level);
6687 if (result == ary) {
6688 result = ary_make_shared_copy(ary);
6691 return result;
6694 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6696 static VALUE
6697 rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6699 long i, len;
6701 rb_ary_modify(ary);
6702 i = len = RARRAY_LEN(ary);
6703 RARRAY_PTR_USE(ary, ptr, {
6704 while (i) {
6705 long j = RAND_UPTO(i);
6706 VALUE tmp;
6707 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6708 rb_raise(rb_eRuntimeError, "modified during shuffle");
6710 tmp = ptr[--i];
6711 ptr[i] = ptr[j];
6712 ptr[j] = tmp;
6714 }); /* WB: no new reference */
6715 return ary;
6718 static VALUE
6719 rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6721 ary = rb_ary_dup(ary);
6722 rb_ary_shuffle_bang(ec, ary, randgen);
6723 return ary;
6726 static const rb_data_type_t ary_sample_memo_type = {
6727 .wrap_struct_name = "ary_sample_memo",
6728 .function = {
6729 .dfree = (RUBY_DATA_FUNC)st_free_table,
6731 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
6734 static VALUE
6735 ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6737 VALUE result;
6738 long n, len, i, j, k, idx[10];
6739 long rnds[numberof(idx)];
6740 long memo_threshold;
6742 len = RARRAY_LEN(ary);
6743 if (!to_array) {
6744 if (len < 2)
6745 i = 0;
6746 else
6747 i = RAND_UPTO(len);
6749 return rb_ary_elt(ary, i);
6751 n = NUM2LONG(nv);
6752 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
6753 if (n > len) n = len;
6754 if (n <= numberof(idx)) {
6755 for (i = 0; i < n; ++i) {
6756 rnds[i] = RAND_UPTO(len - i);
6759 k = len;
6760 len = RARRAY_LEN(ary);
6761 if (len < k && n <= numberof(idx)) {
6762 for (i = 0; i < n; ++i) {
6763 if (rnds[i] >= len) return rb_ary_new_capa(0);
6766 if (n > len) n = len;
6767 switch (n) {
6768 case 0:
6769 return rb_ary_new_capa(0);
6770 case 1:
6771 i = rnds[0];
6772 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
6773 case 2:
6774 i = rnds[0];
6775 j = rnds[1];
6776 if (j >= i) j++;
6777 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
6778 case 3:
6779 i = rnds[0];
6780 j = rnds[1];
6781 k = rnds[2];
6783 long l = j, g = i;
6784 if (j >= i) l = i, g = ++j;
6785 if (k >= l && (++k >= g)) ++k;
6787 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
6789 memo_threshold =
6790 len < 2560 ? len / 128 :
6791 len < 5120 ? len / 64 :
6792 len < 10240 ? len / 32 :
6793 len / 16;
6794 if (n <= numberof(idx)) {
6795 long sorted[numberof(idx)];
6796 sorted[0] = idx[0] = rnds[0];
6797 for (i=1; i<n; i++) {
6798 k = rnds[i];
6799 for (j = 0; j < i; ++j) {
6800 if (k < sorted[j]) break;
6801 ++k;
6803 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
6804 sorted[j] = idx[i] = k;
6806 result = rb_ary_new_capa(n);
6807 RARRAY_PTR_USE(result, ptr_result, {
6808 for (i=0; i<n; i++) {
6809 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
6813 else if (n <= memo_threshold / 2) {
6814 long max_idx = 0;
6815 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
6816 st_table *memo = st_init_numtable_with_size(n);
6817 RTYPEDDATA_DATA(vmemo) = memo;
6818 result = rb_ary_new_capa(n);
6819 RARRAY_PTR_USE(result, ptr_result, {
6820 for (i=0; i<n; i++) {
6821 long r = RAND_UPTO(len-i) + i;
6822 ptr_result[i] = r;
6823 if (r > max_idx) max_idx = r;
6825 len = RARRAY_LEN(ary);
6826 if (len <= max_idx) n = 0;
6827 else if (n > len) n = len;
6828 RARRAY_PTR_USE(ary, ptr_ary, {
6829 for (i=0; i<n; i++) {
6830 long j2 = j = ptr_result[i];
6831 long i2 = i;
6832 st_data_t value;
6833 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
6834 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
6835 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6836 ptr_result[i] = ptr_ary[j2];
6840 RTYPEDDATA_DATA(vmemo) = 0;
6841 st_free_table(memo);
6842 RB_GC_GUARD(vmemo);
6844 else {
6845 result = rb_ary_dup(ary);
6846 RBASIC_CLEAR_CLASS(result);
6847 RB_GC_GUARD(ary);
6848 RARRAY_PTR_USE(result, ptr_result, {
6849 for (i=0; i<n; i++) {
6850 j = RAND_UPTO(len-i) + i;
6851 nv = ptr_result[j];
6852 ptr_result[j] = ptr_result[i];
6853 ptr_result[i] = nv;
6856 RBASIC_SET_CLASS_RAW(result, rb_cArray);
6858 ARY_SET_LEN(result, n);
6860 return result;
6863 static VALUE
6864 ary_sized_alloc(rb_execution_context_t *ec, VALUE self)
6866 return rb_ary_new2(RARRAY_LEN(self));
6869 static VALUE
6870 ary_sample0(rb_execution_context_t *ec, VALUE ary)
6872 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
6875 static VALUE
6876 rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
6878 long mul;
6879 VALUE n = Qnil;
6880 if (args && (RARRAY_LEN(args) > 0)) {
6881 n = RARRAY_AREF(args, 0);
6883 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
6884 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
6885 mul = NUM2LONG(n);
6886 if (mul <= 0) return INT2FIX(0);
6887 n = LONG2FIX(mul);
6888 return rb_fix_mul_fix(rb_ary_length(self), n);
6892 * call-seq:
6893 * cycle(count = nil) {|element| ... } -> nil
6894 * cycle(count = nil) -> new_enumerator
6896 * With a block given, may call the block, depending on the value of argument +count+;
6897 * +count+ must be an
6898 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6899 * or +nil+.
6901 * When +count+ is positive,
6902 * calls the block with each element, then does so repeatedly,
6903 * until it has done so +count+ times; returns +nil+:
6905 * output = []
6906 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6907 * output # => [0, 1, 0, 1]
6909 * When +count+ is zero or negative, does not call the block:
6911 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6912 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6914 * When +count+ is +nil+, cycles forever:
6916 * # Prints 0 and 1 forever.
6917 * [0, 1].cycle {|element| puts element }
6918 * [0, 1].cycle(nil) {|element| puts element }
6920 * With no block given, returns a new Enumerator.
6922 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6924 static VALUE
6925 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
6927 long n, i;
6929 rb_check_arity(argc, 0, 1);
6931 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
6932 if (argc == 0 || NIL_P(argv[0])) {
6933 n = -1;
6935 else {
6936 n = NUM2LONG(argv[0]);
6937 if (n <= 0) return Qnil;
6940 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
6941 for (i=0; i<RARRAY_LEN(ary); i++) {
6942 rb_yield(RARRAY_AREF(ary, i));
6945 return Qnil;
6949 * Build a ruby array of the corresponding values and yield it to the
6950 * associated block.
6951 * Return the class of +values+ for reentry check.
6953 static int
6954 yield_indexed_values(const VALUE values, const long r, const long *const p)
6956 const VALUE result = rb_ary_new2(r);
6957 long i;
6959 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
6960 ARY_SET_LEN(result, r);
6961 rb_yield(result);
6962 return !RBASIC(values)->klass;
6966 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6968 * When we have a complete permutation of array indices, copy the values
6969 * at those indices into a new array and yield that array.
6971 * n: the size of the set
6972 * r: the number of elements in each permutation
6973 * p: the array (of size r) that we're filling in
6974 * used: an array of booleans: whether a given index is already used
6975 * values: the Ruby array that holds the actual values to permute
6977 static void
6978 permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
6980 long i = 0, index = 0;
6982 for (;;) {
6983 const char *const unused = memchr(&used[i], 0, n-i);
6984 if (!unused) {
6985 if (!index) break;
6986 i = p[--index]; /* pop index */
6987 used[i++] = 0; /* index unused */
6989 else {
6990 i = unused - used;
6991 p[index] = i;
6992 used[i] = 1; /* mark index used */
6993 ++index;
6994 if (index < r-1) { /* if not done yet */
6995 p[index] = i = 0;
6996 continue;
6998 for (i = 0; i < n; ++i) {
6999 if (used[i]) continue;
7000 p[index] = i;
7001 if (!yield_indexed_values(values, r, p)) {
7002 rb_raise(rb_eRuntimeError, "permute reentered");
7005 i = p[--index]; /* pop index */
7006 used[i] = 0; /* index unused */
7007 p[index] = ++i;
7013 * Returns the product of from, from-1, ..., from - how_many + 1.
7014 * https://en.wikipedia.org/wiki/Pochhammer_symbol
7016 static VALUE
7017 descending_factorial(long from, long how_many)
7019 VALUE cnt;
7020 if (how_many > 0) {
7021 cnt = LONG2FIX(from);
7022 while (--how_many > 0) {
7023 long v = --from;
7024 cnt = rb_int_mul(cnt, LONG2FIX(v));
7027 else {
7028 cnt = LONG2FIX(how_many == 0);
7030 return cnt;
7033 static VALUE
7034 binomial_coefficient(long comb, long size)
7036 VALUE r;
7037 long i;
7038 if (comb > size-comb) {
7039 comb = size-comb;
7041 if (comb < 0) {
7042 return LONG2FIX(0);
7044 else if (comb == 0) {
7045 return LONG2FIX(1);
7047 r = LONG2FIX(size);
7048 for (i = 1; i < comb; ++i) {
7049 r = rb_int_mul(r, LONG2FIX(size - i));
7050 r = rb_int_idiv(r, LONG2FIX(i + 1));
7052 return r;
7055 static VALUE
7056 rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7058 long n = RARRAY_LEN(ary);
7059 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
7061 return descending_factorial(n, k);
7065 * call-seq:
7066 * permutation(count = self.size) {|permutation| ... } -> self
7067 * permutation(count = self.size) -> new_enumerator
7069 * Iterates over permutations of the elements of +self+;
7070 * the order of permutations is indeterminate.
7072 * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
7073 * calls the block with each permutation of +self+ of size +count+;
7074 * returns +self+:
7076 * a = [0, 1, 2]
7077 * perms = []
7078 * a.permutation(1) {|perm| perms.push(perm) }
7079 * perms # => [[0], [1], [2]]
7081 * perms = []
7082 * a.permutation(2) {|perm| perms.push(perm) }
7083 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7085 * perms = []
7086 * a.permutation(3) {|perm| perms.push(perm) }
7087 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7089 * When +count+ is zero, calls the block once with a new empty array:
7091 * perms = []
7092 * a.permutation(0) {|perm| perms.push(perm) }
7093 * perms # => [[]]
7095 * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
7096 * does not call the block:
7098 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7099 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7101 * With no block given, returns a new Enumerator.
7103 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7106 static VALUE
7107 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
7109 long r, n, i;
7111 n = RARRAY_LEN(ary); /* Array length */
7112 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
7113 r = n;
7114 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
7115 r = NUM2LONG(argv[0]); /* Permutation size from argument */
7117 if (r < 0 || n < r) {
7118 /* no permutations: yield nothing */
7120 else if (r == 0) { /* exactly one permutation: the zero-length array */
7121 rb_yield(rb_ary_new2(0));
7123 else if (r == 1) { /* this is a special, easy case */
7124 for (i = 0; i < RARRAY_LEN(ary); i++) {
7125 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7128 else { /* this is the general case */
7129 volatile VALUE t0;
7130 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
7131 char *used = (char*)(p + r);
7132 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7133 RBASIC_CLEAR_CLASS(ary0);
7135 MEMZERO(used, char, n); /* initialize array */
7137 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7138 ALLOCV_END(t0);
7139 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7141 return ary;
7144 static void
7145 combinate0(const long len, const long n, long *const stack, const VALUE values)
7147 long lev = 0;
7149 MEMZERO(stack+1, long, n);
7150 stack[0] = -1;
7151 for (;;) {
7152 for (lev++; lev < n; lev++) {
7153 stack[lev+1] = stack[lev]+1;
7155 if (!yield_indexed_values(values, n, stack+1)) {
7156 rb_raise(rb_eRuntimeError, "combination reentered");
7158 do {
7159 if (lev == 0) return;
7160 stack[lev--]++;
7161 } while (stack[lev+1]+n == len+lev+1);
7165 static VALUE
7166 rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7168 long n = RARRAY_LEN(ary);
7169 long k = NUM2LONG(RARRAY_AREF(args, 0));
7171 return binomial_coefficient(k, n);
7175 * call-seq:
7176 * combination(count) {|element| ... } -> self
7177 * combination(count) -> new_enumerator
7179 * When a block and a positive
7180 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7181 * argument +count+ (<tt>0 < count <= self.size</tt>)
7182 * are given, calls the block with each combination of +self+ of size +count+;
7183 * returns +self+:
7185 * a = %w[a b c] # => ["a", "b", "c"]
7186 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7188 * Output:
7190 * ["a", "b"]
7191 * ["a", "c"]
7192 * ["b", "c"]
7194 * The order of the yielded combinations is not guaranteed.
7196 * When +count+ is zero, calls the block once with a new empty array:
7198 * a.combination(0) {|combination| p combination }
7199 * [].combination(0) {|combination| p combination }
7201 * Output:
7203 * []
7204 * []
7206 * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
7207 * does not call the block:
7209 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7210 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7212 * With no block given, returns a new Enumerator.
7214 * Related: Array#permutation;
7215 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7218 static VALUE
7219 rb_ary_combination(VALUE ary, VALUE num)
7221 long i, n, len;
7223 n = NUM2LONG(num);
7224 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7225 len = RARRAY_LEN(ary);
7226 if (n < 0 || len < n) {
7227 /* yield nothing */
7229 else if (n == 0) {
7230 rb_yield(rb_ary_new2(0));
7232 else if (n == 1) {
7233 for (i = 0; i < RARRAY_LEN(ary); i++) {
7234 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7237 else {
7238 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7239 volatile VALUE t0;
7240 long *stack = ALLOCV_N(long, t0, n+1);
7242 RBASIC_CLEAR_CLASS(ary0);
7243 combinate0(len, n, stack, ary0);
7244 ALLOCV_END(t0);
7245 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7247 return ary;
7251 * Compute repeated permutations of +r+ elements of the set
7252 * <code>[0..n-1]</code>.
7254 * When we have a complete repeated permutation of array indices, copy the
7255 * values at those indices into a new array and yield that array.
7257 * n: the size of the set
7258 * r: the number of elements in each permutation
7259 * p: the array (of size r) that we're filling in
7260 * values: the Ruby array that holds the actual values to permute
7262 static void
7263 rpermute0(const long n, const long r, long *const p, const VALUE values)
7265 long i = 0, index = 0;
7267 p[index] = i;
7268 for (;;) {
7269 if (++index < r-1) {
7270 p[index] = i = 0;
7271 continue;
7273 for (i = 0; i < n; ++i) {
7274 p[index] = i;
7275 if (!yield_indexed_values(values, r, p)) {
7276 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7279 do {
7280 if (index <= 0) return;
7281 } while ((i = ++p[--index]) >= n);
7285 static VALUE
7286 rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7288 long n = RARRAY_LEN(ary);
7289 long k = NUM2LONG(RARRAY_AREF(args, 0));
7291 if (k < 0) {
7292 return LONG2FIX(0);
7294 if (n <= 0) {
7295 return LONG2FIX(!k);
7297 return rb_int_positive_pow(n, (unsigned long)k);
7301 * call-seq:
7302 * repeated_permutation(size) {|permutation| ... } -> self
7303 * repeated_permutation(size) -> new_enumerator
7305 * With a block given, calls the block with each repeated permutation of length +size+
7306 * of the elements of +self+;
7307 * each permutation is an array;
7308 * returns +self+. The order of the permutations is indeterminate.
7310 * If a positive integer argument +size+ is given,
7311 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7312 * The number of permutations is <tt>self.size**size</tt>.
7314 * Examples:
7316 * - +size+ is 1:
7318 * p = []
7319 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7320 * p # => [[0], [1], [2]]
7322 * - +size+ is 2:
7324 * p = []
7325 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7326 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7328 * If +size+ is zero, calls the block once with an empty array.
7330 * If +size+ is negative, does not call the block:
7332 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7334 * With no block given, returns a new Enumerator.
7336 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7338 static VALUE
7339 rb_ary_repeated_permutation(VALUE ary, VALUE num)
7341 long r, n, i;
7343 n = RARRAY_LEN(ary); /* Array length */
7344 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7345 r = NUM2LONG(num); /* Permutation size from argument */
7347 if (r < 0) {
7348 /* no permutations: yield nothing */
7350 else if (r == 0) { /* exactly one permutation: the zero-length array */
7351 rb_yield(rb_ary_new2(0));
7353 else if (r == 1) { /* this is a special, easy case */
7354 for (i = 0; i < RARRAY_LEN(ary); i++) {
7355 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7358 else { /* this is the general case */
7359 volatile VALUE t0;
7360 long *p = ALLOCV_N(long, t0, r);
7361 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7362 RBASIC_CLEAR_CLASS(ary0);
7364 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7365 ALLOCV_END(t0);
7366 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7368 return ary;
7371 static void
7372 rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7374 long i = 0, index = 0;
7376 p[index] = i;
7377 for (;;) {
7378 if (++index < r-1) {
7379 p[index] = i;
7380 continue;
7382 for (; i < n; ++i) {
7383 p[index] = i;
7384 if (!yield_indexed_values(values, r, p)) {
7385 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7388 do {
7389 if (index <= 0) return;
7390 } while ((i = ++p[--index]) >= n);
7394 static VALUE
7395 rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7397 long n = RARRAY_LEN(ary);
7398 long k = NUM2LONG(RARRAY_AREF(args, 0));
7399 if (k == 0) {
7400 return LONG2FIX(1);
7402 return binomial_coefficient(k, n + k - 1);
7406 * call-seq:
7407 * repeated_combination(size) {|combination| ... } -> self
7408 * repeated_combination(size) -> new_enumerator
7410 * With a block given, calls the block with each repeated combination of length +size+
7411 * of the elements of +self+;
7412 * each combination is an array;
7413 * returns +self+. The order of the combinations is indeterminate.
7415 * If a positive integer argument +size+ is given,
7416 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7417 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7419 * Examples:
7421 * - +size+ is 1:
7423 * c = []
7424 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7425 * c # => [[0], [1], [2]]
7427 * - +size+ is 2:
7429 * c = []
7430 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7431 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7433 * If +size+ is zero, calls the block once with an empty array.
7435 * If +size+ is negative, does not call the block:
7437 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7439 * With no block given, returns a new Enumerator.
7441 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7444 static VALUE
7445 rb_ary_repeated_combination(VALUE ary, VALUE num)
7447 long n, i, len;
7449 n = NUM2LONG(num); /* Combination size from argument */
7450 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7451 len = RARRAY_LEN(ary);
7452 if (n < 0) {
7453 /* yield nothing */
7455 else if (n == 0) {
7456 rb_yield(rb_ary_new2(0));
7458 else if (n == 1) {
7459 for (i = 0; i < RARRAY_LEN(ary); i++) {
7460 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7463 else if (len == 0) {
7464 /* yield nothing */
7466 else {
7467 volatile VALUE t0;
7468 long *p = ALLOCV_N(long, t0, n);
7469 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7470 RBASIC_CLEAR_CLASS(ary0);
7472 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7473 ALLOCV_END(t0);
7474 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7476 return ary;
7480 * call-seq:
7481 * product(*other_arrays) -> new_array
7482 * product(*other_arrays) {|combination| ... } -> self
7484 * Computes all combinations of elements from all the arrays,
7485 * including both +self+ and +other_arrays+:
7487 * - The number of combinations is the product of the sizes of all the arrays,
7488 * including both +self+ and +other_arrays+.
7489 * - The order of the returned combinations is indeterminate.
7491 * With no block given, returns the combinations as an array of arrays:
7493 * p = [0, 1].product([2, 3])
7494 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7495 * p.size # => 4
7496 * p = [0, 1].product([2, 3], [4, 5])
7497 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7498 * p.size # => 8
7500 * If +self+ or any argument is empty, returns an empty array:
7502 * [].product([2, 3], [4, 5]) # => []
7503 * [0, 1].product([2, 3], []) # => []
7505 * If no argument is given, returns an array of 1-element arrays,
7506 * each containing an element of +self+:
7508 * a.product # => [[0], [1], [2]]
7510 * With a block given, calls the block with each combination; returns +self+:
7512 * p = []
7513 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7514 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7516 * If +self+ or any argument is empty, does not call the block:
7518 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7519 * # => []
7520 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7521 * # => [0, 1]
7523 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7525 * p = []
7526 * [0, 1].product {|combination| p.push(combination) }
7527 * p # => [[0], [1]]
7529 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7532 static VALUE
7533 rb_ary_product(int argc, VALUE *argv, VALUE ary)
7535 int n = argc+1; /* How many arrays we're operating on */
7536 volatile VALUE t0 = rb_ary_hidden_new(n);
7537 volatile VALUE t1 = Qundef;
7538 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7539 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7540 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7541 long i,j;
7542 long resultlen = 1;
7544 RBASIC_CLEAR_CLASS(t0);
7546 /* initialize the arrays of arrays */
7547 ARY_SET_LEN(t0, n);
7548 arrays[0] = ary;
7549 for (i = 1; i < n; i++) arrays[i] = Qnil;
7550 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7552 /* initialize the counters for the arrays */
7553 for (i = 0; i < n; i++) counters[i] = 0;
7555 /* Otherwise, allocate and fill in an array of results */
7556 if (rb_block_given_p()) {
7557 /* Make defensive copies of arrays; exit if any is empty */
7558 for (i = 0; i < n; i++) {
7559 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7560 arrays[i] = ary_make_shared_copy(arrays[i]);
7563 else {
7564 /* Compute the length of the result array; return [] if any is empty */
7565 for (i = 0; i < n; i++) {
7566 long k = RARRAY_LEN(arrays[i]);
7567 if (k == 0) {
7568 result = rb_ary_new2(0);
7569 goto done;
7571 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7572 rb_raise(rb_eRangeError, "too big to product");
7573 resultlen *= k;
7575 result = rb_ary_new2(resultlen);
7577 for (;;) {
7578 int m;
7579 /* fill in one subarray */
7580 VALUE subarray = rb_ary_new2(n);
7581 for (j = 0; j < n; j++) {
7582 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7585 /* put it on the result array */
7586 if (NIL_P(result)) {
7587 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7588 rb_yield(subarray);
7589 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7590 rb_raise(rb_eRuntimeError, "product reentered");
7592 else {
7593 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7596 else {
7597 rb_ary_push(result, subarray);
7601 * Increment the last counter. If it overflows, reset to 0
7602 * and increment the one before it.
7604 m = n-1;
7605 counters[m]++;
7606 while (counters[m] == RARRAY_LEN(arrays[m])) {
7607 counters[m] = 0;
7608 /* If the first counter overflows, we are done */
7609 if (--m < 0) goto done;
7610 counters[m]++;
7614 done:
7615 ALLOCV_END(t1);
7617 return NIL_P(result) ? ary : result;
7621 * call-seq:
7622 * take(count) -> new_array
7624 * Returns a new array containing the first +count+ element of +self+
7625 * (as available);
7626 * +count+ must be a non-negative numeric;
7627 * does not modify +self+:
7629 * a = ['a', 'b', 'c', 'd']
7630 * a.take(2) # => ["a", "b"]
7631 * a.take(2.1) # => ["a", "b"]
7632 * a.take(50) # => ["a", "b", "c", "d"]
7633 * a.take(0) # => []
7635 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7638 static VALUE
7639 rb_ary_take(VALUE obj, VALUE n)
7641 long len = NUM2LONG(n);
7642 if (len < 0) {
7643 rb_raise(rb_eArgError, "attempt to take negative size");
7645 return rb_ary_subseq(obj, 0, len);
7649 * call-seq:
7650 * take_while {|element| ... } -> new_array
7651 * take_while -> new_enumerator
7653 * With a block given, calls the block with each successive element of +self+;
7654 * stops iterating if the block returns +false+ or +nil+;
7655 * returns a new array containing those elements for which the block returned a truthy value:
7657 * a = [0, 1, 2, 3, 4, 5]
7658 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7659 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7660 * a.take_while {|element| false } # => []
7662 * With no block given, returns a new Enumerator.
7664 * Does not modify +self+.
7666 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7669 static VALUE
7670 rb_ary_take_while(VALUE ary)
7672 long i;
7674 RETURN_ENUMERATOR(ary, 0, 0);
7675 for (i = 0; i < RARRAY_LEN(ary); i++) {
7676 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7678 return rb_ary_take(ary, LONG2FIX(i));
7682 * call-seq:
7683 * drop(count) -> new_array
7685 * Returns a new array containing all but the first +count+ element of +self+,
7686 * where +count+ is a non-negative integer;
7687 * does not modify +self+.
7689 * Examples:
7691 * a = [0, 1, 2, 3, 4, 5]
7692 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7693 * a.drop(1) # => [1, 2, 3, 4, 5]
7694 * a.drop(2) # => [2, 3, 4, 5]
7695 * a.drop(9) # => []
7697 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7700 static VALUE
7701 rb_ary_drop(VALUE ary, VALUE n)
7703 VALUE result;
7704 long pos = NUM2LONG(n);
7705 if (pos < 0) {
7706 rb_raise(rb_eArgError, "attempt to drop negative size");
7709 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7710 if (NIL_P(result)) result = rb_ary_new();
7711 return result;
7715 * call-seq:
7716 * drop_while {|element| ... } -> new_array
7717 * drop_while -> new_enumerator
7719 * With a block given, calls the block with each successive element of +self+;
7720 * stops if the block returns +false+ or +nil+;
7721 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7722 * does not modify +self+:
7724 * a = [0, 1, 2, 3, 4, 5]
7725 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7727 * With no block given, returns a new Enumerator.
7729 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7732 static VALUE
7733 rb_ary_drop_while(VALUE ary)
7735 long i;
7737 RETURN_ENUMERATOR(ary, 0, 0);
7738 for (i = 0; i < RARRAY_LEN(ary); i++) {
7739 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7741 return rb_ary_drop(ary, LONG2FIX(i));
7745 * call-seq:
7746 * any? -> true or false
7747 * any?(object) -> true or false
7748 * any? {|element| ... } -> true or false
7750 * Returns whether for any element of +self+, a given criterion is satisfied.
7752 * With no block and no argument, returns whether any element of +self+ is truthy:
7754 * [nil, false, []].any? # => true # Array object is truthy.
7755 * [nil, false, {}].any? # => true # Hash object is truthy.
7756 * [nil, false, ''].any? # => true # String object is truthy.
7757 * [nil, false].any? # => false # Nil and false are not truthy.
7759 * With argument +object+ given,
7760 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7762 * [nil, false, 0].any?(0) # => true
7763 * [nil, false, 1].any?(0) # => false
7764 * [nil, false, 'food'].any?(/foo/) # => true
7765 * [nil, false, 'food'].any?(/bar/) # => false
7767 * With a block given,
7768 * calls the block with each element in +self+;
7769 * returns whether the block returns any truthy value:
7771 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7772 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7774 * With both a block and argument +object+ given,
7775 * ignores the block and uses +object+ as above.
7777 * <b>Special case</b>: returns +false+ if +self+ is empty
7778 * (regardless of any given argument or block).
7780 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7783 static VALUE
7784 rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
7786 long i, len = RARRAY_LEN(ary);
7788 rb_check_arity(argc, 0, 1);
7789 if (!len) return Qfalse;
7790 if (argc) {
7791 if (rb_block_given_p()) {
7792 rb_warn("given block not used");
7794 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7795 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
7798 else if (!rb_block_given_p()) {
7799 for (i = 0; i < len; ++i) {
7800 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
7803 else {
7804 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7805 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
7808 return Qfalse;
7812 * call-seq:
7813 * all? -> true or false
7814 * all?(object) -> true or false
7815 * all? {|element| ... } -> true or false
7817 * Returns whether for every element of +self+,
7818 * a given criterion is satisfied.
7820 * With no block and no argument,
7821 * returns whether every element of +self+ is truthy:
7823 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7824 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7825 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7827 * With argument +object+ given, returns whether <tt>object === ele</tt>
7828 * for every element +ele+ in +self+:
7830 * [0, 0, 0].all?(0) # => true
7831 * [0, 1, 2].all?(1) # => false
7832 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7833 * ['food', 'drink'].all?(/foo/) # => false
7835 * With a block given, calls the block with each element in +self+;
7836 * returns whether the block returns only truthy values:
7838 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7839 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7841 * With both a block and argument +object+ given,
7842 * ignores the block and uses +object+ as above.
7844 * <b>Special case</b>: returns +true+ if +self+ is empty
7845 * (regardless of any given argument or block).
7847 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7850 static VALUE
7851 rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
7853 long i, len = RARRAY_LEN(ary);
7855 rb_check_arity(argc, 0, 1);
7856 if (!len) return Qtrue;
7857 if (argc) {
7858 if (rb_block_given_p()) {
7859 rb_warn("given block not used");
7861 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7862 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7865 else if (!rb_block_given_p()) {
7866 for (i = 0; i < len; ++i) {
7867 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7870 else {
7871 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7872 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7875 return Qtrue;
7879 * call-seq:
7880 * none? -> true or false
7881 * none?(object) -> true or false
7882 * none? {|element| ... } -> true or false
7884 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
7886 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7887 * +false+ otherwise:
7889 * [nil, false].none? # => true
7890 * [nil, 0, false].none? # => false
7891 * [].none? # => true
7893 * With argument +object+ given, returns +false+ if for any element +element+,
7894 * <tt>object === element</tt>; +true+ otherwise:
7896 * ['food', 'drink'].none?(/bar/) # => true
7897 * ['food', 'drink'].none?(/foo/) # => false
7898 * [].none?(/foo/) # => true
7899 * [0, 1, 2].none?(3) # => true
7900 * [0, 1, 2].none?(1) # => false
7902 * With a block given, calls the block with each element in +self+;
7903 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7905 * [0, 1, 2].none? {|element| element > 3 } # => true
7906 * [0, 1, 2].none? {|element| element > 1 } # => false
7908 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7911 static VALUE
7912 rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
7914 long i, len = RARRAY_LEN(ary);
7916 rb_check_arity(argc, 0, 1);
7917 if (!len) return Qtrue;
7918 if (argc) {
7919 if (rb_block_given_p()) {
7920 rb_warn("given block not used");
7922 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7923 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7926 else if (!rb_block_given_p()) {
7927 for (i = 0; i < len; ++i) {
7928 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7931 else {
7932 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7933 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7936 return Qtrue;
7940 * call-seq:
7941 * one? -> true or false
7942 * one? {|element| ... } -> true or false
7943 * one?(object) -> true or false
7945 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7947 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7948 * +false+ otherwise:
7950 * [nil, 0].one? # => true
7951 * [0, 0].one? # => false
7952 * [nil, nil].one? # => false
7953 * [].one? # => false
7955 * With a block given, calls the block with each element in +self+;
7956 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7958 * [0, 1, 2].one? {|element| element > 0 } # => false
7959 * [0, 1, 2].one? {|element| element > 1 } # => true
7960 * [0, 1, 2].one? {|element| element > 2 } # => false
7962 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
7963 * +false+ otherwise:
7965 * [0, 1, 2].one?(0) # => true
7966 * [0, 0, 1].one?(0) # => false
7967 * [1, 1, 2].one?(0) # => false
7968 * ['food', 'drink'].one?(/bar/) # => false
7969 * ['food', 'drink'].one?(/foo/) # => true
7970 * [].one?(/foo/) # => false
7972 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7975 static VALUE
7976 rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
7978 long i, len = RARRAY_LEN(ary);
7979 VALUE result = Qfalse;
7981 rb_check_arity(argc, 0, 1);
7982 if (!len) return Qfalse;
7983 if (argc) {
7984 if (rb_block_given_p()) {
7985 rb_warn("given block not used");
7987 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7988 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
7989 if (result) return Qfalse;
7990 result = Qtrue;
7994 else if (!rb_block_given_p()) {
7995 for (i = 0; i < len; ++i) {
7996 if (RTEST(RARRAY_AREF(ary, i))) {
7997 if (result) return Qfalse;
7998 result = Qtrue;
8002 else {
8003 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8004 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
8005 if (result) return Qfalse;
8006 result = Qtrue;
8010 return result;
8014 * call-seq:
8015 * array.dig(index, *identifiers) -> object
8017 * Finds and returns the object in nested object
8018 * specified by +index+ and +identifiers+;
8019 * the nested objects may be instances of various classes.
8020 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8022 * Examples:
8024 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8025 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8026 * a.dig(1, 2) # => [:bat, :bam]
8027 * a.dig(1, 2, 0) # => :bat
8028 * a.dig(1, 2, 3) # => nil
8030 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8033 static VALUE
8034 rb_ary_dig(int argc, VALUE *argv, VALUE self)
8036 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
8037 self = rb_ary_at(self, *argv);
8038 if (!--argc) return self;
8039 ++argv;
8040 return rb_obj_dig(argc, argv, self, Qnil);
8043 static inline VALUE
8044 finish_exact_sum(long n, VALUE r, VALUE v, int z)
8046 if (n != 0)
8047 v = rb_fix_plus(LONG2FIX(n), v);
8048 if (!UNDEF_P(r)) {
8049 v = rb_rational_plus(r, v);
8051 else if (!n && z) {
8052 v = rb_fix_plus(LONG2FIX(0), v);
8054 return v;
8058 * call-seq:
8059 * sum(init = 0) -> object
8060 * sum(init = 0) {|element| ... } -> object
8062 * With no block given, returns the sum of +init+ and all elements of +self+;
8063 * for array +array+ and value +init+, equivalent to:
8065 * sum = init
8066 * array.each {|element| sum += element }
8067 * sum
8069 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
8071 * Examples:
8073 * [0, 1, 2, 3].sum # => 6
8074 * [0, 1, 2, 3].sum(100) # => 106
8075 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
8076 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
8077 * # => [2, 3, :foo, :bar, "foo", "bar"]
8079 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
8081 * # Raises TypeError: Array can't be coerced into Integer.
8082 * [[:foo, :bar], ['foo', 'bar']].sum(2)
8084 * With a block given, calls the block with each element of +self+;
8085 * the block's return value (instead of the element itself) is used as the addend:
8087 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
8088 * # => "Coerced and concatenated: zero1two"
8090 * Notes:
8092 * - Array#join and Array#flatten may be faster than Array#sum
8093 * for an array of strings or an array of arrays.
8094 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8098 static VALUE
8099 rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8101 VALUE e, v, r;
8102 long i, n;
8103 int block_given;
8105 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8107 block_given = rb_block_given_p();
8109 if (RARRAY_LEN(ary) == 0)
8110 return v;
8112 n = 0;
8113 r = Qundef;
8115 if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8116 i = 0;
8117 goto init_is_a_value;
8120 for (i = 0; i < RARRAY_LEN(ary); i++) {
8121 e = RARRAY_AREF(ary, i);
8122 if (block_given)
8123 e = rb_yield(e);
8124 if (FIXNUM_P(e)) {
8125 n += FIX2LONG(e); /* should not overflow long type */
8126 if (!FIXABLE(n)) {
8127 v = rb_big_plus(LONG2NUM(n), v);
8128 n = 0;
8131 else if (RB_BIGNUM_TYPE_P(e))
8132 v = rb_big_plus(e, v);
8133 else if (RB_TYPE_P(e, T_RATIONAL)) {
8134 if (UNDEF_P(r))
8135 r = e;
8136 else
8137 r = rb_rational_plus(r, e);
8139 else
8140 goto not_exact;
8142 v = finish_exact_sum(n, r, v, argc!=0);
8143 return v;
8145 not_exact:
8146 v = finish_exact_sum(n, r, v, i!=0);
8148 if (RB_FLOAT_TYPE_P(e)) {
8150 * Kahan-Babuska balancing compensated summation algorithm
8151 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8153 double f, c;
8154 double x, t;
8156 f = NUM2DBL(v);
8157 c = 0.0;
8158 goto has_float_value;
8159 for (; i < RARRAY_LEN(ary); i++) {
8160 e = RARRAY_AREF(ary, i);
8161 if (block_given)
8162 e = rb_yield(e);
8163 if (RB_FLOAT_TYPE_P(e))
8164 has_float_value:
8165 x = RFLOAT_VALUE(e);
8166 else if (FIXNUM_P(e))
8167 x = FIX2LONG(e);
8168 else if (RB_BIGNUM_TYPE_P(e))
8169 x = rb_big2dbl(e);
8170 else if (RB_TYPE_P(e, T_RATIONAL))
8171 x = rb_num2dbl(e);
8172 else
8173 goto not_float;
8175 if (isnan(f)) continue;
8176 if (isnan(x)) {
8177 f = x;
8178 continue;
8180 if (isinf(x)) {
8181 if (isinf(f) && signbit(x) != signbit(f))
8182 f = NAN;
8183 else
8184 f = x;
8185 continue;
8187 if (isinf(f)) continue;
8189 t = f + x;
8190 if (fabs(f) >= fabs(x))
8191 c += ((f - t) + x);
8192 else
8193 c += ((x - t) + f);
8194 f = t;
8196 f += c;
8197 return DBL2NUM(f);
8199 not_float:
8200 v = DBL2NUM(f);
8203 goto has_some_value;
8204 init_is_a_value:
8205 for (; i < RARRAY_LEN(ary); i++) {
8206 e = RARRAY_AREF(ary, i);
8207 if (block_given)
8208 e = rb_yield(e);
8209 has_some_value:
8210 v = rb_funcall(v, idPLUS, 1, e);
8212 return v;
8215 /* :nodoc: */
8216 static VALUE
8217 rb_ary_deconstruct(VALUE ary)
8219 return ary;
8223 * An \Array object is an ordered, integer-indexed collection of objects,
8224 * called _elements_;
8225 * the object represents
8226 * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
8228 * An element may be any object (even another array);
8229 * elements may be any mixture of objects of different types.
8231 * Important data structures that use arrays include:
8233 * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
8234 * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
8235 * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
8236 * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
8237 * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
8238 * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
8239 * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
8241 * There are also array-like data structures:
8243 * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
8244 * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
8245 * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
8246 * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
8247 * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
8249 * == \Array Indexes
8251 * \Array indexing starts at 0, as in C or Java.
8253 * A non-negative index is an offset from the first element:
8255 * - Index 0 indicates the first element.
8256 * - Index 1 indicates the second element.
8257 * - ...
8259 * A negative index is an offset, backwards, from the end of the array:
8261 * - Index -1 indicates the last element.
8262 * - Index -2 indicates the next-to-last element.
8263 * - ...
8266 * === In-Range and Out-of-Range Indexes
8268 * A non-negative index is <i>in range</i> if and only if it is smaller than
8269 * the size of the array. For a 3-element array:
8271 * - Indexes 0 through 2 are in range.
8272 * - Index 3 is out of range.
8274 * A negative index is <i>in range</i> if and only if its absolute value is
8275 * not larger than the size of the array. For a 3-element array:
8277 * - Indexes -1 through -3 are in range.
8278 * - Index -4 is out of range.
8280 * === Effective Index
8282 * Although the effective index into an array is always an integer,
8283 * some methods (both within class \Array and elsewhere)
8284 * accept one or more non-integer arguments that are
8285 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8287 * == Creating Arrays
8289 * You can create an \Array object explicitly with:
8291 * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
8293 * [1, 'one', :one, [2, 'two', :two]]
8295 * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8297 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8298 * %w[1 % *] # => ["1", "%", "*"]
8300 * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8302 * %i[foo bar baz] # => [:foo, :bar, :baz]
8303 * %i[1 % *] # => [:"1", :%, :*]
8305 * - \Method Kernel#Array:
8307 * Array(["a", "b"]) # => ["a", "b"]
8308 * Array(1..5) # => [1, 2, 3, 4, 5]
8309 * Array(key: :value) # => [[:key, :value]]
8310 * Array(nil) # => []
8311 * Array(1) # => [1]
8312 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8314 * - \Method Array.new:
8316 * Array.new # => []
8317 * Array.new(3) # => [nil, nil, nil]
8318 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8319 * Array.new(3, true) # => [true, true, true]
8321 * Note that the last example above populates the array
8322 * with references to the same object.
8323 * This is recommended only in cases where that object is a natively immutable object
8324 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8326 * Another way to create an array with various objects, using a block;
8327 * this usage is safe for mutable objects such as hashes, strings or
8328 * other arrays:
8330 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8332 * Here is a way to create a multi-dimensional array:
8334 * Array.new(3) {Array.new(3)}
8335 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8337 * A number of Ruby methods, both in the core and in the standard library,
8338 * provide instance method +to_a+, which converts an object to an array.
8340 * - ARGF#to_a
8341 * - Array#to_a
8342 * - Enumerable#to_a
8343 * - Hash#to_a
8344 * - MatchData#to_a
8345 * - NilClass#to_a
8346 * - OptionParser#to_a
8347 * - Range#to_a
8348 * - Set#to_a
8349 * - Struct#to_a
8350 * - Time#to_a
8351 * - Benchmark::Tms#to_a
8352 * - CSV::Table#to_a
8353 * - Enumerator::Lazy#to_a
8354 * - Gem::List#to_a
8355 * - Gem::NameTuple#to_a
8356 * - Gem::Platform#to_a
8357 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8358 * - Gem::SourceList#to_a
8359 * - OpenSSL::X509::Extension#to_a
8360 * - OpenSSL::X509::Name#to_a
8361 * - Racc::ISet#to_a
8362 * - Rinda::RingFinger#to_a
8363 * - Ripper::Lexer::Elem#to_a
8364 * - RubyVM::InstructionSequence#to_a
8365 * - YAML::DBM#to_a
8367 * == Example Usage
8369 * In addition to the methods it mixes in through the Enumerable module, the
8370 * +Array+ class has proprietary methods for accessing, searching and otherwise
8371 * manipulating arrays.
8373 * Some of the more common ones are illustrated below.
8375 * == Accessing Elements
8377 * Elements in an array can be retrieved using the Array#[] method. It can
8378 * take a single integer argument (a numeric index), a pair of arguments
8379 * (start and length) or a range. Negative indices start counting from the end,
8380 * with -1 being the last element.
8382 * arr = [1, 2, 3, 4, 5, 6]
8383 * arr[2] #=> 3
8384 * arr[100] #=> nil
8385 * arr[-3] #=> 4
8386 * arr[2, 3] #=> [3, 4, 5]
8387 * arr[1..4] #=> [2, 3, 4, 5]
8388 * arr[1..-3] #=> [2, 3, 4]
8390 * Another way to access a particular array element is by using the #at method
8392 * arr.at(0) #=> 1
8394 * The #slice method works in an identical manner to Array#[].
8396 * To raise an error for indices outside of the array bounds or else to
8397 * provide a default value when that happens, you can use #fetch.
8399 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8400 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8401 * arr.fetch(100, "oops") #=> "oops"
8403 * The special methods #first and #last will return the first and last
8404 * elements of an array, respectively.
8406 * arr.first #=> 1
8407 * arr.last #=> 6
8409 * To return the first +n+ elements of an array, use #take
8411 * arr.take(3) #=> [1, 2, 3]
8413 * #drop does the opposite of #take, by returning the elements after +n+
8414 * elements have been dropped:
8416 * arr.drop(3) #=> [4, 5, 6]
8418 * == Obtaining Information about an +Array+
8420 * Arrays keep track of their own length at all times. To query an array
8421 * about the number of elements it contains, use #length, #count or #size.
8423 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8424 * browsers.length #=> 5
8425 * browsers.count #=> 5
8427 * To check whether an array contains any elements at all
8429 * browsers.empty? #=> false
8431 * To check whether a particular item is included in the array
8433 * browsers.include?('Konqueror') #=> false
8435 * == Adding Items to Arrays
8437 * Items can be added to the end of an array by using either #push or #<<
8439 * arr = [1, 2, 3, 4]
8440 * arr.push(5) #=> [1, 2, 3, 4, 5]
8441 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8443 * #unshift will add a new item to the beginning of an array.
8445 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8447 * With #insert you can add a new element to an array at any position.
8449 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8451 * Using the #insert method, you can also insert multiple values at once:
8453 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8454 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8456 * == Removing Items from an +Array+
8458 * The method #pop removes the last element in an array and returns it:
8460 * arr = [1, 2, 3, 4, 5, 6]
8461 * arr.pop #=> 6
8462 * arr #=> [1, 2, 3, 4, 5]
8464 * To retrieve and at the same time remove the first item, use #shift:
8466 * arr.shift #=> 1
8467 * arr #=> [2, 3, 4, 5]
8469 * To delete an element at a particular index:
8471 * arr.delete_at(2) #=> 4
8472 * arr #=> [2, 3, 5]
8474 * To delete a particular element anywhere in an array, use #delete:
8476 * arr = [1, 2, 2, 3]
8477 * arr.delete(2) #=> 2
8478 * arr #=> [1,3]
8480 * A useful method if you need to remove +nil+ values from an array is
8481 * #compact:
8483 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8484 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8485 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8486 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8487 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8489 * Another common need is to remove duplicate elements from an array.
8491 * It has the non-destructive #uniq, and destructive method #uniq!
8493 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8494 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8496 * == Iterating over Arrays
8498 * Like all classes that include the Enumerable module, +Array+ has an each
8499 * method, which defines what elements should be iterated over and how. In
8500 * case of Array's #each, all elements in the +Array+ instance are yielded to
8501 * the supplied block in sequence.
8503 * Note that this operation leaves the array unchanged.
8505 * arr = [1, 2, 3, 4, 5]
8506 * arr.each {|a| print a -= 10, " "}
8507 * # prints: -9 -8 -7 -6 -5
8508 * #=> [1, 2, 3, 4, 5]
8510 * Another sometimes useful iterator is #reverse_each which will iterate over
8511 * the elements in the array in reverse order.
8513 * words = %w[first second third fourth fifth sixth]
8514 * str = ""
8515 * words.reverse_each {|word| str += "#{word} "}
8516 * p str #=> "sixth fifth fourth third second first "
8518 * The #map method can be used to create a new array based on the original
8519 * array, but with the values modified by the supplied block:
8521 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8522 * arr #=> [1, 2, 3, 4, 5]
8523 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8524 * arr #=> [1, 4, 9, 16, 25]
8527 * == Selecting Items from an +Array+
8529 * Elements can be selected from an array according to criteria defined in a
8530 * block. The selection can happen in a destructive or a non-destructive
8531 * manner. While the destructive operations will modify the array they were
8532 * called on, the non-destructive methods usually return a new array with the
8533 * selected elements, but leave the original array unchanged.
8535 * === Non-destructive Selection
8537 * arr = [1, 2, 3, 4, 5, 6]
8538 * arr.select {|a| a > 3} #=> [4, 5, 6]
8539 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8540 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8541 * arr #=> [1, 2, 3, 4, 5, 6]
8543 * === Destructive Selection
8545 * #select! and #reject! are the corresponding destructive methods to #select
8546 * and #reject
8548 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8549 * opposite result when supplied with the same block:
8551 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8552 * arr #=> [4, 5, 6]
8554 * arr = [1, 2, 3, 4, 5, 6]
8555 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8556 * arr #=> [1, 2, 3]
8558 * == What's Here
8560 * First, what's elsewhere. \Class +Array+:
8562 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8563 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8564 * which provides dozens of additional methods.
8566 * Here, class +Array+ provides methods that are useful for:
8568 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8569 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8570 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8571 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8572 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8573 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8574 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8575 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8576 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8577 * - {And more....}[rdoc-ref:Array@Other+Methods]
8579 * === Methods for Creating an +Array+
8581 * - ::[]: Returns a new array populated with given objects.
8582 * - ::new: Returns a new array.
8583 * - ::try_convert: Returns a new array created from a given object.
8585 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8587 * === Methods for Querying
8589 * - #all?: Returns whether all elements meet a given criterion.
8590 * - #any?: Returns whether any element meets a given criterion.
8591 * - #count: Returns the count of elements that meet a given criterion.
8592 * - #empty?: Returns whether there are no elements.
8593 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8594 * - #hash: Returns the integer hash code.
8595 * - #include?: Returns whether any element <tt>==</tt> a given object.
8596 * - #length (aliased as #size): Returns the count of elements.
8597 * - #none?: Returns whether no element <tt>==</tt> a given object.
8598 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8599 * - #rindex: Returns the index of the last element that meets a given criterion.
8601 * === Methods for Comparing
8603 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
8604 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
8605 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding element in a given object.
8607 * === Methods for Fetching
8609 * These methods do not modify +self+.
8611 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8612 * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
8613 * - #at: Returns the element at a given offset.
8614 * - #bsearch: Returns an element selected via a binary search as determined by a given block.
8615 * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
8616 * - #compact: Returns an array containing all non-+nil+ elements.
8617 * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
8618 * - #drop: Returns trailing elements as determined by a given index.
8619 * - #drop_while: Returns trailing elements as determined by a given block.
8620 * - #fetch: Returns the element at a given offset.
8621 * - #fetch_values: Returns elements at given offsets.
8622 * - #first: Returns one or more leading elements.
8623 * - #last: Returns one or more trailing elements.
8624 * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8625 * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
8626 * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8627 * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
8628 * - #reject: Returns an array containing elements not rejected by a given block.
8629 * - #reverse: Returns all elements in reverse order.
8630 * - #rotate: Returns all elements with some rotated from one end to the other.
8631 * - #sample: Returns one or more random elements.
8632 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8633 * - #shuffle: Returns elements in a random order.
8634 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8635 * - #take: Returns leading elements as determined by a given index.
8636 * - #take_while: Returns leading elements as determined by a given block.
8637 * - #uniq: Returns an array containing non-duplicate elements.
8638 * - #values_at: Returns the elements at given offsets.
8640 * === Methods for Assigning
8642 * These methods add, replace, or reorder elements in +self+.
8644 * - #<<: Appends an element.
8645 * - #[]=: Assigns specified elements with a given object.
8646 * - #concat: Appends all elements from given arrays.
8647 * - #fill: Replaces specified elements with specified objects.
8648 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8649 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8650 * - #insert: Inserts given objects at a given offset; does not replace elements.
8651 * - #push (aliased as #append): Appends elements.
8652 * - #reverse!: Replaces +self+ with its elements reversed.
8653 * - #rotate!: Replaces +self+ with its elements rotated.
8654 * - #shuffle!: Replaces +self+ with its elements in random order.
8655 * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
8656 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8657 * - #unshift (aliased as #prepend): Prepends leading elements.
8659 * === Methods for Deleting
8661 * Each of these methods removes elements from +self+:
8663 * - #clear: Removes all elements.
8664 * - #compact!: Removes all +nil+ elements.
8665 * - #delete: Removes elements equal to a given object.
8666 * - #delete_at: Removes the element at a given offset.
8667 * - #delete_if: Removes elements specified by a given block.
8668 * - #keep_if: Removes elements not specified by a given block.
8669 * - #pop: Removes and returns the last element.
8670 * - #reject!: Removes elements specified by a given block.
8671 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8672 * - #shift: Removes and returns the first element.
8673 * - #slice!: Removes and returns a sequence of elements.
8674 * - #uniq!: Removes duplicates.
8676 * === Methods for Combining
8678 * - #&: Returns an array containing elements found both in +self+ and a given array.
8679 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8680 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8681 * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
8682 * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
8683 * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
8684 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8685 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8686 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
8688 * === Methods for Iterating
8690 * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
8691 * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
8692 * - #each: Passes each element to a given block.
8693 * - #each_index: Passes each element index to a given block.
8694 * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
8695 * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
8696 * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
8697 * - #reverse_each: Passes each element, in reverse order, to a given block.
8699 * === Methods for Converting
8701 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8702 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8703 * - #flatten: Returns an array that is a recursive flattening of +self+.
8704 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8705 * - #join: Returns a newsString containing the elements joined by the field separator.
8706 * - #to_a: Returns +self+ or a new array containing all elements.
8707 * - #to_ary: Returns +self+.
8708 * - #to_h: Returns a new hash formed from the elements.
8709 * - #transpose: Transposes +self+, which must be an array of arrays.
8710 * - #zip: Returns a new array of arrays containing +self+ and given arrays.
8712 * === Other Methods
8714 * - #*: Returns one of the following:
8716 * - With integer argument +n+, a new array that is the concatenation
8717 * of +n+ copies of +self+.
8718 * - With string argument +field_separator+, a new string that is equivalent to
8719 * <tt>join(field_separator)</tt>.
8721 * - #pack: Packs the elements into a binary sequence.
8722 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8725 void
8726 Init_Array(void)
8728 fake_ary_flags = init_fake_ary_flags();
8730 rb_cArray = rb_define_class("Array", rb_cObject);
8731 rb_include_module(rb_cArray, rb_mEnumerable);
8733 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8734 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
8735 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8736 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8737 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8738 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8740 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
8741 rb_define_alias(rb_cArray, "to_s", "inspect");
8742 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
8743 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
8744 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
8746 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
8747 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
8748 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
8750 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
8751 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
8752 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
8753 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8754 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
8755 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
8756 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
8757 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
8758 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
8759 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
8760 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
8761 rb_define_alias(rb_cArray, "append", "push");
8762 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
8763 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
8764 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
8765 rb_define_alias(rb_cArray, "prepend", "unshift");
8766 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
8767 rb_define_method(rb_cArray, "each", rb_ary_each, 0);
8768 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
8769 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
8770 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
8771 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
8772 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
8773 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
8774 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
8775 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
8776 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
8777 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
8778 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
8779 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
8780 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
8781 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
8782 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
8783 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
8784 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
8785 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
8786 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
8787 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8788 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
8789 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8790 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
8791 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
8792 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
8793 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
8794 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
8795 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
8796 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
8797 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
8798 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
8799 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
8800 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
8801 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
8802 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
8803 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
8804 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
8805 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
8807 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
8808 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
8810 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
8811 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
8813 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
8814 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
8816 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
8817 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
8818 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
8820 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
8821 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
8822 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
8824 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
8825 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
8826 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
8827 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
8828 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
8829 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
8830 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
8831 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
8832 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
8833 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
8834 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
8835 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
8836 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
8838 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
8839 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
8840 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
8841 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
8842 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
8843 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
8844 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
8845 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
8846 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
8847 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
8848 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
8849 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
8850 rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
8852 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
8854 rb_cArray_empty_frozen = rb_ary_freeze(rb_ary_new());
8855 rb_vm_register_global_object(rb_cArray_empty_frozen);
8858 #include "array.rbinc"