318b7763ec6a13a8fc32cf75d78e384f2e447acd
[ruby.git] / array.c
blob318b7763ec6a13a8fc32cf75d78e384f2e447acd
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 * 1: RARRAY_EMBED_FLAG
46 * The array is embedded (its contents follow the header, rather than
47 * being on a separately allocated buffer).
48 * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
49 * The array is shared. The buffer this array points to is owned by
50 * another array (the shared root).
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;
267 void
268 rb_ary_verify(VALUE ary)
270 ary_verify(ary);
272 #else
273 #define ary_verify(ary) ((void)0)
274 #endif
276 VALUE *
277 rb_ary_ptr_use_start(VALUE ary)
279 #if ARRAY_DEBUG
280 FL_SET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
281 #endif
282 return (VALUE *)RARRAY_CONST_PTR(ary);
285 void
286 rb_ary_ptr_use_end(VALUE ary)
288 #if ARRAY_DEBUG
289 FL_UNSET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
290 #endif
293 void
294 rb_mem_clear(VALUE *mem, long size)
296 while (size--) {
297 *mem++ = Qnil;
301 static void
302 ary_mem_clear(VALUE ary, long beg, long size)
304 RARRAY_PTR_USE(ary, ptr, {
305 rb_mem_clear(ptr + beg, size);
309 static inline void
310 memfill(register VALUE *mem, register long size, register VALUE val)
312 while (size--) {
313 *mem++ = val;
317 static void
318 ary_memfill(VALUE ary, long beg, long size, VALUE val)
320 RARRAY_PTR_USE(ary, ptr, {
321 memfill(ptr + beg, size, val);
322 RB_OBJ_WRITTEN(ary, Qundef, val);
326 static void
327 ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
329 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary));
331 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
332 rb_gc_writebarrier_remember(buff_owner_ary);
333 RARRAY_PTR_USE(ary, ptr, {
334 MEMCPY(ptr+beg, argv, VALUE, argc);
337 else {
338 int i;
339 RARRAY_PTR_USE(ary, ptr, {
340 for (i=0; i<argc; i++) {
341 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
347 static void
348 ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
350 ary_memcpy0(ary, beg, argc, argv, ary);
353 static VALUE *
354 ary_heap_alloc_buffer(size_t capa)
356 return ALLOC_N(VALUE, capa);
359 static void
360 ary_heap_free_ptr(VALUE ary, const VALUE *ptr, long size)
362 ruby_sized_xfree((void *)ptr, size);
365 static void
366 ary_heap_free(VALUE ary)
368 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
371 static size_t
372 ary_heap_realloc(VALUE ary, size_t new_capa)
374 RUBY_ASSERT(!OBJ_FROZEN(ary));
375 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, ARY_HEAP_CAPA(ary));
376 ary_verify(ary);
378 return new_capa;
381 void
382 rb_ary_make_embedded(VALUE ary)
384 RUBY_ASSERT(rb_ary_embeddable_p(ary));
385 if (!ARY_EMBED_P(ary)) {
386 const VALUE *buf = ARY_HEAP_PTR(ary);
387 long len = ARY_HEAP_LEN(ary);
389 FL_SET_EMBED(ary);
390 ARY_SET_EMBED_LEN(ary, len);
392 MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
394 ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
398 static void
399 ary_resize_capa(VALUE ary, long capacity)
401 RUBY_ASSERT(RARRAY_LEN(ary) <= capacity);
402 RUBY_ASSERT(!OBJ_FROZEN(ary));
403 RUBY_ASSERT(!ARY_SHARED_P(ary));
405 if (capacity > ary_embed_capa(ary)) {
406 size_t new_capa = capacity;
407 if (ARY_EMBED_P(ary)) {
408 long len = ARY_EMBED_LEN(ary);
409 VALUE *ptr = ary_heap_alloc_buffer(capacity);
411 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
412 FL_UNSET_EMBED(ary);
413 ARY_SET_PTR(ary, ptr);
414 ARY_SET_HEAP_LEN(ary, len);
416 else {
417 new_capa = ary_heap_realloc(ary, capacity);
419 ARY_SET_CAPA(ary, new_capa);
421 else {
422 if (!ARY_EMBED_P(ary)) {
423 long len = ARY_HEAP_LEN(ary);
424 long old_capa = ARY_HEAP_CAPA(ary);
425 const VALUE *ptr = ARY_HEAP_PTR(ary);
427 if (len > capacity) len = capacity;
428 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
429 ary_heap_free_ptr(ary, ptr, old_capa);
431 FL_SET_EMBED(ary);
432 ARY_SET_LEN(ary, len);
436 ary_verify(ary);
439 static inline void
440 ary_shrink_capa(VALUE ary)
442 long capacity = ARY_HEAP_LEN(ary);
443 long old_capa = ARY_HEAP_CAPA(ary);
444 RUBY_ASSERT(!ARY_SHARED_P(ary));
445 RUBY_ASSERT(old_capa >= capacity);
446 if (old_capa > capacity) {
447 size_t new_capa = ary_heap_realloc(ary, capacity);
448 ARY_SET_CAPA(ary, new_capa);
451 ary_verify(ary);
454 static void
455 ary_double_capa(VALUE ary, long min)
457 long new_capa = ARY_CAPA(ary) / 2;
459 if (new_capa < ARY_DEFAULT_SIZE) {
460 new_capa = ARY_DEFAULT_SIZE;
462 if (new_capa >= ARY_MAX_SIZE - min) {
463 new_capa = (ARY_MAX_SIZE - min) / 2;
465 new_capa += min;
466 ary_resize_capa(ary, new_capa);
468 ary_verify(ary);
471 static void
472 rb_ary_decrement_share(VALUE shared_root)
474 if (!OBJ_FROZEN(shared_root)) {
475 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
476 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
480 static void
481 rb_ary_unshare(VALUE ary)
483 VALUE shared_root = ARY_SHARED_ROOT(ary);
484 rb_ary_decrement_share(shared_root);
485 FL_UNSET_SHARED(ary);
488 static void
489 rb_ary_reset(VALUE ary)
491 if (ARY_OWNS_HEAP_P(ary)) {
492 ary_heap_free(ary);
494 else if (ARY_SHARED_P(ary)) {
495 rb_ary_unshare(ary);
498 FL_SET_EMBED(ary);
499 ARY_SET_EMBED_LEN(ary, 0);
502 static VALUE
503 rb_ary_increment_share(VALUE shared_root)
505 if (!OBJ_FROZEN(shared_root)) {
506 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
507 RUBY_ASSERT(num >= 0);
508 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
510 return shared_root;
513 static void
514 rb_ary_set_shared(VALUE ary, VALUE shared_root)
516 RUBY_ASSERT(!ARY_EMBED_P(ary));
517 RUBY_ASSERT(!OBJ_FROZEN(ary));
518 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root));
520 rb_ary_increment_share(shared_root);
521 FL_SET_SHARED(ary);
522 RB_OBJ_WRITE(ary, &RARRAY(ary)->as.heap.aux.shared_root, shared_root);
524 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
527 static inline void
528 rb_ary_modify_check(VALUE ary)
530 rb_check_frozen(ary);
531 ary_verify(ary);
534 void
535 rb_ary_cancel_sharing(VALUE ary)
537 if (ARY_SHARED_P(ary)) {
538 long shared_len, len = RARRAY_LEN(ary);
539 VALUE shared_root = ARY_SHARED_ROOT(ary);
541 ary_verify(shared_root);
543 if (len <= ary_embed_capa(ary)) {
544 const VALUE *ptr = ARY_HEAP_PTR(ary);
545 FL_UNSET_SHARED(ary);
546 FL_SET_EMBED(ary);
547 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
548 rb_ary_decrement_share(shared_root);
549 ARY_SET_EMBED_LEN(ary, len);
551 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
552 long shift = RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared_root);
553 FL_UNSET_SHARED(ary);
554 ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared_root));
555 ARY_SET_CAPA(ary, shared_len);
556 RARRAY_PTR_USE(ary, ptr, {
557 MEMMOVE(ptr, ptr+shift, VALUE, len);
559 FL_SET_EMBED(shared_root);
560 rb_ary_decrement_share(shared_root);
562 else {
563 VALUE *ptr = ary_heap_alloc_buffer(len);
564 MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
565 rb_ary_unshare(ary);
566 ARY_SET_CAPA(ary, len);
567 ARY_SET_PTR(ary, ptr);
570 rb_gc_writebarrier_remember(ary);
572 ary_verify(ary);
575 void
576 rb_ary_modify(VALUE ary)
578 rb_ary_modify_check(ary);
579 rb_ary_cancel_sharing(ary);
582 static VALUE
583 ary_ensure_room_for_push(VALUE ary, long add_len)
585 long old_len = RARRAY_LEN(ary);
586 long new_len = old_len + add_len;
587 long capa;
589 if (old_len > ARY_MAX_SIZE - add_len) {
590 rb_raise(rb_eIndexError, "index %ld too big", new_len);
592 if (ARY_SHARED_P(ary)) {
593 if (new_len > ary_embed_capa(ary)) {
594 VALUE shared_root = ARY_SHARED_ROOT(ary);
595 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
596 if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
597 rb_ary_modify_check(ary);
599 ary_verify(ary);
600 ary_verify(shared_root);
601 return shared_root;
603 else {
604 /* if array is shared, then it is likely it participate in push/shift pattern */
605 rb_ary_modify(ary);
606 capa = ARY_CAPA(ary);
607 if (new_len > capa - (capa >> 6)) {
608 ary_double_capa(ary, new_len);
610 ary_verify(ary);
611 return ary;
615 ary_verify(ary);
616 rb_ary_modify(ary);
618 else {
619 rb_ary_modify_check(ary);
621 capa = ARY_CAPA(ary);
622 if (new_len > capa) {
623 ary_double_capa(ary, new_len);
626 ary_verify(ary);
627 return ary;
631 * call-seq:
632 * freeze -> self
634 * Freezes +self+ (if not already frozen); returns +self+:
636 * a = []
637 * a.frozen? # => false
638 * a.freeze
639 * a.frozen? # => true
641 * No further changes may be made to +self+;
642 * raises FrozenError if a change is attempted.
644 * Related: Kernel#frozen?.
647 VALUE
648 rb_ary_freeze(VALUE ary)
650 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
652 if (OBJ_FROZEN(ary)) return ary;
654 if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) {
655 ary_shrink_capa(ary);
658 return rb_obj_freeze(ary);
661 /* This can be used to take a snapshot of an array (with
662 e.g. rb_ary_replace) and check later whether the array has been
663 modified from the snapshot. The snapshot is cheap, though if
664 something does modify the array it will pay the cost of copying
665 it. If Array#pop or Array#shift has been called, the array will
666 be still shared with the snapshot, but the array length will
667 differ. */
668 VALUE
669 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
671 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
672 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
673 ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
674 ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
675 return Qtrue;
677 return Qfalse;
680 static VALUE
681 ary_alloc_embed(VALUE klass, long capa)
683 size_t size = ary_embed_size(capa);
684 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
685 NEWOBJ_OF(ary, struct RArray, klass,
686 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
687 size, 0);
688 /* Created array is:
689 * FL_SET_EMBED((VALUE)ary);
690 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
692 return (VALUE)ary;
695 static VALUE
696 ary_alloc_heap(VALUE klass)
698 NEWOBJ_OF(ary, struct RArray, klass,
699 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
700 sizeof(struct RArray), 0);
701 return (VALUE)ary;
704 static VALUE
705 empty_ary_alloc(VALUE klass)
707 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
708 return ary_alloc_embed(klass, 0);
711 static VALUE
712 ary_new(VALUE klass, long capa)
714 VALUE ary;
716 if (capa < 0) {
717 rb_raise(rb_eArgError, "negative array size (or size too big)");
719 if (capa > ARY_MAX_SIZE) {
720 rb_raise(rb_eArgError, "array size too big");
723 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
725 if (ary_embeddable_p(capa)) {
726 ary = ary_alloc_embed(klass, capa);
728 else {
729 ary = ary_alloc_heap(klass);
730 ARY_SET_CAPA(ary, capa);
731 RUBY_ASSERT(!ARY_EMBED_P(ary));
733 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
734 ARY_SET_HEAP_LEN(ary, 0);
737 return ary;
740 VALUE
741 rb_ary_new_capa(long capa)
743 return ary_new(rb_cArray, capa);
746 VALUE
747 rb_ary_new(void)
749 return rb_ary_new_capa(0);
752 VALUE
753 (rb_ary_new_from_args)(long n, ...)
755 va_list ar;
756 VALUE ary;
757 long i;
759 ary = rb_ary_new2(n);
761 va_start(ar, n);
762 for (i=0; i<n; i++) {
763 ARY_SET(ary, i, va_arg(ar, VALUE));
765 va_end(ar);
767 ARY_SET_LEN(ary, n);
768 return ary;
771 VALUE
772 rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
774 VALUE ary;
776 ary = ary_new(klass, n);
777 if (n > 0 && elts) {
778 ary_memcpy(ary, 0, n, elts);
779 ARY_SET_LEN(ary, n);
782 return ary;
785 VALUE
786 rb_ary_new_from_values(long n, const VALUE *elts)
788 return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
791 static VALUE
792 ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
794 size_t size = ary_embed_size(capa);
795 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
796 NEWOBJ_OF(ary, struct RArray, klass,
797 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
798 size, ec);
799 /* Created array is:
800 * FL_SET_EMBED((VALUE)ary);
801 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
803 return (VALUE)ary;
806 static VALUE
807 ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
809 NEWOBJ_OF(ary, struct RArray, klass,
810 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
811 sizeof(struct RArray), ec);
812 return (VALUE)ary;
815 static VALUE
816 ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
818 VALUE ary;
820 if (capa < 0) {
821 rb_raise(rb_eArgError, "negative array size (or size too big)");
823 if (capa > ARY_MAX_SIZE) {
824 rb_raise(rb_eArgError, "array size too big");
827 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
829 if (ary_embeddable_p(capa)) {
830 ary = ec_ary_alloc_embed(ec, klass, capa);
832 else {
833 ary = ec_ary_alloc_heap(ec, klass);
834 ARY_SET_CAPA(ary, capa);
835 RUBY_ASSERT(!ARY_EMBED_P(ary));
837 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
838 ARY_SET_HEAP_LEN(ary, 0);
841 return ary;
844 VALUE
845 rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
847 VALUE ary;
849 ary = ec_ary_new(ec, rb_cArray, n);
850 if (n > 0 && elts) {
851 ary_memcpy(ary, 0, n, elts);
852 ARY_SET_LEN(ary, n);
855 return ary;
858 VALUE
859 rb_ary_hidden_new(long capa)
861 VALUE ary = ary_new(0, capa);
862 return ary;
865 VALUE
866 rb_ary_hidden_new_fill(long capa)
868 VALUE ary = rb_ary_hidden_new(capa);
869 ary_memfill(ary, 0, capa, Qnil);
870 ARY_SET_LEN(ary, capa);
871 return ary;
874 void
875 rb_ary_free(VALUE ary)
877 if (ARY_OWNS_HEAP_P(ary)) {
878 if (USE_DEBUG_COUNTER &&
879 !ARY_SHARED_ROOT_P(ary) &&
880 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
881 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
884 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
885 ary_heap_free(ary);
887 else {
888 RB_DEBUG_COUNTER_INC(obj_ary_embed);
891 if (ARY_SHARED_P(ary)) {
892 RB_DEBUG_COUNTER_INC(obj_ary_shared);
894 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
895 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
899 static VALUE fake_ary_flags;
901 static VALUE
902 init_fake_ary_flags(void)
904 struct RArray fake_ary = {0};
905 fake_ary.basic.flags = T_ARRAY;
906 VALUE ary = (VALUE)&fake_ary;
907 rb_ary_freeze(ary);
908 return fake_ary.basic.flags;
911 VALUE
912 rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len)
914 fake_ary->basic.flags = fake_ary_flags;
915 RBASIC_CLEAR_CLASS((VALUE)fake_ary);
917 // bypass frozen checks
918 fake_ary->as.heap.ptr = list;
919 fake_ary->as.heap.len = len;
920 fake_ary->as.heap.aux.capa = len;
921 return (VALUE)fake_ary;
924 size_t
925 rb_ary_memsize(VALUE ary)
927 if (ARY_OWNS_HEAP_P(ary)) {
928 return ARY_CAPA(ary) * sizeof(VALUE);
930 else {
931 return 0;
935 static VALUE
936 ary_make_shared(VALUE ary)
938 ary_verify(ary);
940 if (ARY_SHARED_P(ary)) {
941 return ARY_SHARED_ROOT(ary);
943 else if (ARY_SHARED_ROOT_P(ary)) {
944 return ary;
946 else if (OBJ_FROZEN(ary)) {
947 return ary;
949 else {
950 long capa = ARY_CAPA(ary);
951 long len = RARRAY_LEN(ary);
953 /* Shared roots cannot be embedded because the reference count
954 * (refcnt) is stored in as.heap.aux.capa. */
955 VALUE shared = ary_alloc_heap(0);
956 FL_SET_SHARED_ROOT(shared);
958 if (ARY_EMBED_P(ary)) {
959 VALUE *ptr = ary_heap_alloc_buffer(capa);
960 ARY_SET_PTR(shared, ptr);
961 ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary));
963 FL_UNSET_EMBED(ary);
964 ARY_SET_HEAP_LEN(ary, len);
965 ARY_SET_PTR(ary, ptr);
967 else {
968 ARY_SET_PTR(shared, RARRAY_CONST_PTR(ary));
971 ARY_SET_LEN(shared, capa);
972 ary_mem_clear(shared, len, capa - len);
973 rb_ary_set_shared(ary, shared);
975 ary_verify(shared);
976 ary_verify(ary);
978 return shared;
982 static VALUE
983 ary_make_substitution(VALUE ary)
985 long len = RARRAY_LEN(ary);
987 if (ary_embeddable_p(len)) {
988 VALUE subst = rb_ary_new_capa(len);
989 RUBY_ASSERT(ARY_EMBED_P(subst));
991 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
992 ARY_SET_EMBED_LEN(subst, len);
993 return subst;
995 else {
996 return rb_ary_increment_share(ary_make_shared(ary));
1000 VALUE
1001 rb_assoc_new(VALUE car, VALUE cdr)
1003 return rb_ary_new3(2, car, cdr);
1006 VALUE
1007 rb_to_array_type(VALUE ary)
1009 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1011 #define to_ary rb_to_array_type
1013 VALUE
1014 rb_check_array_type(VALUE ary)
1016 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1019 VALUE
1020 rb_check_to_array(VALUE ary)
1022 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1025 VALUE
1026 rb_to_array(VALUE ary)
1028 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1032 * call-seq:
1033 * Array.try_convert(object) -> object, new_array, or nil
1035 * Attempts to return an array, based on the given +object+.
1037 * If +object+ is an array, returns +object+.
1039 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1040 * calls <tt>object.to_ary</tt>:
1041 * if the return value is an array or +nil+, returns that value;
1042 * if not, raises TypeError.
1044 * Otherwise returns +nil+.
1046 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1049 static VALUE
1050 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
1052 return rb_check_array_type(ary);
1055 /* :nodoc: */
1056 static VALUE
1057 rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
1059 VALUE ary;
1061 if (klass == rb_cArray) {
1062 long size = 0;
1063 if (argc > 0 && FIXNUM_P(argv[0])) {
1064 size = FIX2LONG(argv[0]);
1065 if (size < 0) size = 0;
1068 ary = ary_new(klass, size);
1070 rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
1072 else {
1073 ary = rb_class_new_instance_pass_kw(argc, argv, klass);
1076 return ary;
1080 * call-seq:
1081 * Array.new -> new_empty_array
1082 * Array.new(array) -> new_array
1083 * Array.new(size, default_value = nil) -> new_array
1084 * Array.new(size = 0) {|index| ... } -> new_array
1086 * Returns a new array.
1088 * With no block and no argument given, returns a new empty array:
1090 * Array.new # => []
1092 * With no block and array argument given, returns a new array with the same elements:
1094 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1096 * With no block and integer argument given, returns a new array containing
1097 * that many instances of the given +default_value+:
1099 * Array.new(0) # => []
1100 * Array.new(3) # => [nil, nil, nil]
1101 * Array.new(2, 3) # => [3, 3]
1103 * With a block given, returns an array of the given +size+;
1104 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1105 * the element at that +index+ in the returned array is the blocks return value:
1107 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1109 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1111 * array = Array.new(2, {})
1112 * array # => [{}, {}]
1113 * array[0][:a] = 1
1114 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1116 * If you want the elements of the array to be distinct, you should pass a block:
1118 * array = Array.new(2) { {} }
1119 * array # => [{}, {}]
1120 * array[0][:a] = 1
1121 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1123 * Raises TypeError if the first argument is not either an array
1124 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1125 * Raises ArgumentError if the first argument is a negative integer.
1127 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1130 static VALUE
1131 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1133 long len;
1134 VALUE size, val;
1136 rb_ary_modify(ary);
1137 if (argc == 0) {
1138 rb_ary_reset(ary);
1139 RUBY_ASSERT(ARY_EMBED_P(ary));
1140 RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
1141 if (rb_block_given_p()) {
1142 rb_warning("given block not used");
1144 return ary;
1146 rb_scan_args(argc, argv, "02", &size, &val);
1147 if (argc == 1 && !FIXNUM_P(size)) {
1148 val = rb_check_array_type(size);
1149 if (!NIL_P(val)) {
1150 rb_ary_replace(ary, val);
1151 return ary;
1155 len = NUM2LONG(size);
1156 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1157 if (len < 0) {
1158 rb_raise(rb_eArgError, "negative array size");
1160 if (len > ARY_MAX_SIZE) {
1161 rb_raise(rb_eArgError, "array size too big");
1163 /* recheck after argument conversion */
1164 rb_ary_modify(ary);
1165 ary_resize_capa(ary, len);
1166 if (rb_block_given_p()) {
1167 long i;
1169 if (argc == 2) {
1170 rb_warn("block supersedes default value argument");
1172 for (i=0; i<len; i++) {
1173 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
1174 ARY_SET_LEN(ary, i + 1);
1177 else {
1178 ary_memfill(ary, 0, len, val);
1179 ARY_SET_LEN(ary, len);
1181 return ary;
1185 * Returns a new array, populated with the given objects:
1187 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1188 * Array[] # => []
1189 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1191 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1194 static VALUE
1195 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1197 VALUE ary = ary_new(klass, argc);
1198 if (argc > 0 && argv) {
1199 ary_memcpy(ary, 0, argc, argv);
1200 ARY_SET_LEN(ary, argc);
1203 return ary;
1206 void
1207 rb_ary_store(VALUE ary, long idx, VALUE val)
1209 long len = RARRAY_LEN(ary);
1211 if (idx < 0) {
1212 idx += len;
1213 if (idx < 0) {
1214 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1215 idx - len, -len);
1218 else if (idx >= ARY_MAX_SIZE) {
1219 rb_raise(rb_eIndexError, "index %ld too big", idx);
1222 rb_ary_modify(ary);
1223 if (idx >= ARY_CAPA(ary)) {
1224 ary_double_capa(ary, idx);
1226 if (idx > len) {
1227 ary_mem_clear(ary, len, idx - len + 1);
1230 if (idx >= len) {
1231 ARY_SET_LEN(ary, idx + 1);
1233 ARY_SET(ary, idx, val);
1236 static VALUE
1237 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1239 RUBY_ASSERT(offset >= 0);
1240 RUBY_ASSERT(len >= 0);
1241 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1243 VALUE result = ary_alloc_heap(klass);
1244 size_t embed_capa = ary_embed_capa(result);
1245 if ((size_t)len <= embed_capa) {
1246 FL_SET_EMBED(result);
1247 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
1248 ARY_SET_EMBED_LEN(result, len);
1250 else {
1251 VALUE shared = ary_make_shared(ary);
1253 /* The ary_make_shared call may allocate, which can trigger a GC
1254 * compaction. This can cause the array to be embedded because it has
1255 * a length of 0. */
1256 FL_UNSET_EMBED(result);
1258 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
1259 ARY_SET_LEN(result, RARRAY_LEN(ary));
1260 rb_ary_set_shared(result, shared);
1262 ARY_INCREASE_PTR(result, offset);
1263 ARY_SET_LEN(result, len);
1265 ary_verify(shared);
1268 ary_verify(result);
1269 return result;
1272 static VALUE
1273 ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
1275 RUBY_ASSERT(offset >= 0);
1276 RUBY_ASSERT(len >= 0);
1277 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1278 RUBY_ASSERT(step != 0);
1280 const long orig_len = len;
1282 if (step > 0 && step >= len) {
1283 VALUE result = ary_new(klass, 1);
1284 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1285 const VALUE *values = RARRAY_CONST_PTR(ary);
1287 RB_OBJ_WRITE(result, ptr, values[offset]);
1288 ARY_SET_EMBED_LEN(result, 1);
1289 return result;
1291 else if (step < 0 && step < -len) {
1292 step = -len;
1295 long ustep = (step < 0) ? -step : step;
1296 len = roomof(len, ustep);
1298 long i;
1299 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1301 VALUE result = ary_new(klass, len);
1302 if (ARY_EMBED_P(result)) {
1303 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1304 const VALUE *values = RARRAY_CONST_PTR(ary);
1306 for (i = 0; i < len; ++i) {
1307 RB_OBJ_WRITE(result, ptr+i, values[j]);
1308 j += step;
1310 ARY_SET_EMBED_LEN(result, len);
1312 else {
1313 const VALUE *values = RARRAY_CONST_PTR(ary);
1315 RARRAY_PTR_USE(result, ptr, {
1316 for (i = 0; i < len; ++i) {
1317 RB_OBJ_WRITE(result, ptr+i, values[j]);
1318 j += step;
1321 ARY_SET_LEN(result, len);
1324 return result;
1327 static VALUE
1328 ary_make_shared_copy(VALUE ary)
1330 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
1333 enum ary_take_pos_flags
1335 ARY_TAKE_FIRST = 0,
1336 ARY_TAKE_LAST = 1
1339 static VALUE
1340 ary_take_first_or_last_n(VALUE ary, long n, enum ary_take_pos_flags last)
1342 long len = RARRAY_LEN(ary);
1343 long offset = 0;
1345 if (n > len) {
1346 n = len;
1348 else if (n < 0) {
1349 rb_raise(rb_eArgError, "negative array size");
1351 if (last) {
1352 offset = len - n;
1354 return ary_make_partial(ary, rb_cArray, offset, n);
1357 static VALUE
1358 ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1360 argc = rb_check_arity(argc, 0, 1);
1361 /* the case optional argument is omitted should be handled in
1362 * callers of this function. if another arity case is added,
1363 * this arity check needs to rewrite. */
1364 RUBY_ASSERT_ALWAYS(argc == 1);
1365 return ary_take_first_or_last_n(ary, NUM2LONG(argv[0]), last);
1369 * call-seq:
1370 * self << object -> self
1372 * Appends +object+ as the last element in +self+; returns +self+:
1374 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1376 * Appends +object+ as a single element, even if it is another array:
1378 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1380 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1383 VALUE
1384 rb_ary_push(VALUE ary, VALUE item)
1386 long idx = RARRAY_LEN((ary_verify(ary), ary));
1387 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1388 RARRAY_PTR_USE(ary, ptr, {
1389 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1391 ARY_SET_LEN(ary, idx + 1);
1392 ary_verify(ary);
1393 return ary;
1396 VALUE
1397 rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1399 long oldlen = RARRAY_LEN(ary);
1400 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1401 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1402 ARY_SET_LEN(ary, oldlen + len);
1403 return ary;
1407 * call-seq:
1408 * push(*objects) -> self
1409 * append(*objects) -> self
1411 * Appends each argument in +objects+ to +self+; returns +self+:
1413 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1414 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1416 * Appends each argument as a single element, even if it is another array:
1418 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1419 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1421 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1424 static VALUE
1425 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1427 return rb_ary_cat(ary, argv, argc);
1430 VALUE
1431 rb_ary_pop(VALUE ary)
1433 long n;
1434 rb_ary_modify_check(ary);
1435 n = RARRAY_LEN(ary);
1436 if (n == 0) return Qnil;
1437 if (ARY_OWNS_HEAP_P(ary) &&
1438 n * 3 < ARY_CAPA(ary) &&
1439 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1441 ary_resize_capa(ary, n * 2);
1443 --n;
1444 ARY_SET_LEN(ary, n);
1445 ary_verify(ary);
1446 return RARRAY_AREF(ary, n);
1450 * call-seq:
1451 * pop -> object or nil
1452 * pop(count) -> new_array
1454 * Removes and returns trailing elements of +self+.
1456 * With no argument given, removes and returns the last element, if available;
1457 * otherwise returns +nil+:
1459 * a = [:foo, 'bar', 2]
1460 * a.pop # => 2
1461 * a # => [:foo, "bar"]
1462 * [].pop # => nil
1464 * With non-negative integer argument +count+ given,
1465 * returns a new array containing the trailing +count+ elements of +self+, as available:
1467 * a = [:foo, 'bar', 2]
1468 * a.pop(2) # => ["bar", 2]
1469 * a # => [:foo]
1471 * a = [:foo, 'bar', 2]
1472 * a.pop(50) # => [:foo, "bar", 2]
1473 * a # => []
1475 * Related: Array#push;
1476 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1479 static VALUE
1480 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1482 VALUE result;
1484 if (argc == 0) {
1485 return rb_ary_pop(ary);
1488 rb_ary_modify_check(ary);
1489 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1490 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1491 ary_verify(ary);
1492 return result;
1495 VALUE
1496 rb_ary_shift(VALUE ary)
1498 VALUE top;
1499 long len = RARRAY_LEN(ary);
1501 if (len == 0) {
1502 rb_ary_modify_check(ary);
1503 return Qnil;
1506 top = RARRAY_AREF(ary, 0);
1508 rb_ary_behead(ary, 1);
1510 return top;
1514 * call-seq:
1515 * shift -> object or nil
1516 * shift(count) -> new_array or nil
1518 * Removes and returns leading elements from +self+.
1520 * With no argument, removes and returns one element, if available,
1521 * or +nil+ otherwise:
1523 * a = [0, 1, 2, 3]
1524 * a.shift # => 0
1525 * a # => [1, 2, 3]
1526 * [].shift # => nil
1528 * With non-negative numeric argument +count+ given,
1529 * removes and returns the first +count+ elements:
1531 * a = [0, 1, 2, 3]
1532 * a.shift(2) # => [0, 1]
1533 * a # => [2, 3]
1534 * a.shift(1.1) # => [2]
1535 * a # => [3]
1536 * a.shift(0) # => []
1537 * a # => [3]
1539 * If +count+ is large,
1540 * removes and returns all elements:
1542 * a = [0, 1, 2, 3]
1543 * a.shift(50) # => [0, 1, 2, 3]
1544 * a # => []
1546 * If +self+ is empty, returns a new empty array.
1548 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1551 static VALUE
1552 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1554 VALUE result;
1555 long n;
1557 if (argc == 0) {
1558 return rb_ary_shift(ary);
1561 rb_ary_modify_check(ary);
1562 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1563 n = RARRAY_LEN(result);
1564 rb_ary_behead(ary,n);
1566 return result;
1569 VALUE
1570 rb_ary_behead(VALUE ary, long n)
1572 if (n <= 0) {
1573 return ary;
1576 rb_ary_modify_check(ary);
1578 if (!ARY_SHARED_P(ary)) {
1579 if (ARY_EMBED_P(ary) || RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
1580 RARRAY_PTR_USE(ary, ptr, {
1581 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary) - n);
1582 }); /* WB: no new reference */
1583 ARY_INCREASE_LEN(ary, -n);
1584 ary_verify(ary);
1585 return ary;
1588 ary_mem_clear(ary, 0, n);
1589 ary_make_shared(ary);
1591 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1592 ary_mem_clear(ary, 0, n);
1595 ARY_INCREASE_PTR(ary, n);
1596 ARY_INCREASE_LEN(ary, -n);
1597 ary_verify(ary);
1599 return ary;
1602 static VALUE
1603 make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
1605 if (head - sharedp < argc) {
1606 long room = capa - len - argc;
1608 room -= room >> 4;
1609 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1610 head = sharedp + argc + room;
1612 ARY_SET_PTR(ary, head - argc);
1613 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1615 ary_verify(ary);
1616 return ARY_SHARED_ROOT(ary);
1619 static VALUE
1620 ary_modify_for_unshift(VALUE ary, int argc)
1622 long len = RARRAY_LEN(ary);
1623 long new_len = len + argc;
1624 long capa;
1625 const VALUE *head, *sharedp;
1627 rb_ary_modify(ary);
1628 capa = ARY_CAPA(ary);
1629 if (capa - (capa >> 6) <= new_len) {
1630 ary_double_capa(ary, new_len);
1633 /* use shared array for big "queues" */
1634 if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
1635 ary_verify(ary);
1637 /* make a room for unshifted items */
1638 capa = ARY_CAPA(ary);
1639 ary_make_shared(ary);
1641 head = sharedp = RARRAY_CONST_PTR(ary);
1642 return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
1644 else {
1645 /* sliding items */
1646 RARRAY_PTR_USE(ary, ptr, {
1647 MEMMOVE(ptr + argc, ptr, VALUE, len);
1650 ary_verify(ary);
1651 return ary;
1655 static VALUE
1656 ary_ensure_room_for_unshift(VALUE ary, int argc)
1658 long len = RARRAY_LEN(ary);
1659 long new_len = len + argc;
1661 if (len > ARY_MAX_SIZE - argc) {
1662 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1664 else if (! ARY_SHARED_P(ary)) {
1665 return ary_modify_for_unshift(ary, argc);
1667 else {
1668 VALUE shared_root = ARY_SHARED_ROOT(ary);
1669 long capa = RARRAY_LEN(shared_root);
1671 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1672 return ary_modify_for_unshift(ary, argc);
1674 else if (new_len > capa) {
1675 return ary_modify_for_unshift(ary, argc);
1677 else {
1678 const VALUE * head = RARRAY_CONST_PTR(ary);
1679 void *sharedp = (void *)RARRAY_CONST_PTR(shared_root);
1681 rb_ary_modify_check(ary);
1682 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1688 * call-seq:
1689 * unshift(*objects) -> self
1690 * prepend(*objects) -> self
1692 * Prepends the given +objects+ to +self+:
1694 * a = [:foo, 'bar', 2]
1695 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1697 * Related: Array#shift;
1698 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1701 VALUE
1702 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1704 long len = RARRAY_LEN(ary);
1705 VALUE target_ary;
1707 if (argc == 0) {
1708 rb_ary_modify_check(ary);
1709 return ary;
1712 target_ary = ary_ensure_room_for_unshift(ary, argc);
1713 ary_memcpy0(ary, 0, argc, argv, target_ary);
1714 ARY_SET_LEN(ary, len + argc);
1715 return ary;
1718 VALUE
1719 rb_ary_unshift(VALUE ary, VALUE item)
1721 return rb_ary_unshift_m(1, &item, ary);
1724 /* faster version - use this if you don't need to treat negative offset */
1725 static inline VALUE
1726 rb_ary_elt(VALUE ary, long offset)
1728 long len = RARRAY_LEN(ary);
1729 if (len == 0) return Qnil;
1730 if (offset < 0 || len <= offset) {
1731 return Qnil;
1733 return RARRAY_AREF(ary, offset);
1736 VALUE
1737 rb_ary_entry(VALUE ary, long offset)
1739 return rb_ary_entry_internal(ary, offset);
1742 VALUE
1743 rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
1745 VALUE klass;
1746 long alen = RARRAY_LEN(ary);
1748 if (beg > alen) return Qnil;
1749 if (beg < 0 || len < 0) return Qnil;
1751 if (alen < len || alen < beg + len) {
1752 len = alen - beg;
1754 klass = rb_cArray;
1755 if (len == 0) return ary_new(klass, 0);
1756 if (step == 0)
1757 rb_raise(rb_eArgError, "slice step cannot be zero");
1758 if (step == 1)
1759 return ary_make_partial(ary, klass, beg, len);
1760 else
1761 return ary_make_partial_step(ary, klass, beg, len, step);
1764 VALUE
1765 rb_ary_subseq(VALUE ary, long beg, long len)
1767 return rb_ary_subseq_step(ary, beg, len, 1);
1770 static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1773 * call-seq:
1774 * self[index] -> object or nil
1775 * self[start, length] -> object or nil
1776 * self[range] -> object or nil
1777 * self[aseq] -> object or nil
1778 * slice(index) -> object or nil
1779 * slice(start, length) -> object or nil
1780 * slice(range) -> object or nil
1781 * slice(aseq) -> object or nil
1783 * Returns elements from +self+; does not modify +self+.
1785 * In brief:
1787 * a = [:foo, 'bar', 2]
1789 * # Single argument index: returns one element.
1790 * a[0] # => :foo # Zero-based index.
1791 * a[-1] # => 2 # Negative index counts backwards from end.
1793 * # Arguments start and length: returns an array.
1794 * a[1, 2] # => ["bar", 2]
1795 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1797 * # Single argument range: returns an array.
1798 * a[0..1] # => [:foo, "bar"]
1799 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1800 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1802 * When a single integer argument +index+ is given, returns the element at offset +index+:
1804 * a = [:foo, 'bar', 2]
1805 * a[0] # => :foo
1806 * a[2] # => 2
1807 * a # => [:foo, "bar", 2]
1809 * If +index+ is negative, counts backwards from the end of +self+:
1811 * a = [:foo, 'bar', 2]
1812 * a[-1] # => 2
1813 * a[-2] # => "bar"
1815 * If +index+ is out of range, returns +nil+.
1817 * When two Integer arguments +start+ and +length+ are given,
1818 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1820 * a = [:foo, 'bar', 2]
1821 * a[0, 2] # => [:foo, "bar"]
1822 * a[1, 2] # => ["bar", 2]
1824 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1825 * returns all elements from offset +start+ to the end:
1827 * a = [:foo, 'bar', 2]
1828 * a[0, 4] # => [:foo, "bar", 2]
1829 * a[1, 3] # => ["bar", 2]
1830 * a[2, 2] # => [2]
1832 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1833 * returns a new empty +Array+.
1835 * If +length+ is negative, returns +nil+.
1837 * When a single Range argument +range+ is given,
1838 * treats <tt>range.min</tt> as +start+ above
1839 * and <tt>range.size</tt> as +length+ above:
1841 * a = [:foo, 'bar', 2]
1842 * a[0..1] # => [:foo, "bar"]
1843 * a[1..2] # => ["bar", 2]
1845 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1847 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1849 * a = [:foo, 'bar', 2]
1850 * a[0..-1] # => [:foo, "bar", 2]
1851 * a[0..-2] # => [:foo, "bar"]
1852 * a[0..-3] # => [:foo]
1854 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1856 * a = [:foo, 'bar', 2]
1857 * a[-1..2] # => [2]
1858 * a[-2..2] # => ["bar", 2]
1859 * a[-3..2] # => [:foo, "bar", 2]
1861 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1863 * a = [:foo, 'bar', 2]
1864 * a[4..1] # => nil
1865 * a[4..0] # => nil
1866 * a[4..-1] # => nil
1868 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1869 * returns an +Array+ of elements corresponding to the indexes produced by
1870 * the sequence.
1872 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1873 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1875 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1876 * is larger than array size, throws RangeError.
1878 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1879 * a[(1..11).step(2)]
1880 * # RangeError (((1..11).step(2)) out of range)
1881 * a[(7..).step(2)]
1882 * # RangeError (((7..).step(2)) out of range)
1884 * If given a single argument, and its type is not one of the listed, tries to
1885 * convert it to Integer, and raises if it is impossible:
1887 * a = [:foo, 'bar', 2]
1888 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1889 * a[:foo]
1891 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1894 VALUE
1895 rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
1897 rb_check_arity(argc, 1, 2);
1898 if (argc == 2) {
1899 return rb_ary_aref2(ary, argv[0], argv[1]);
1901 return rb_ary_aref1(ary, argv[0]);
1904 static VALUE
1905 rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1907 long beg = NUM2LONG(b);
1908 long len = NUM2LONG(e);
1909 if (beg < 0) {
1910 beg += RARRAY_LEN(ary);
1912 return rb_ary_subseq(ary, beg, len);
1915 VALUE
1916 rb_ary_aref1(VALUE ary, VALUE arg)
1918 long beg, len, step;
1920 /* special case - speeding up */
1921 if (FIXNUM_P(arg)) {
1922 return rb_ary_entry(ary, FIX2LONG(arg));
1924 /* check if idx is Range or ArithmeticSequence */
1925 switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
1926 case Qfalse:
1927 break;
1928 case Qnil:
1929 return Qnil;
1930 default:
1931 return rb_ary_subseq_step(ary, beg, len, step);
1934 return rb_ary_entry(ary, NUM2LONG(arg));
1938 * call-seq:
1939 * at(index) -> object or nil
1941 * Returns the element of +self+ specified by the given +index+
1942 * or +nil+ if there is no such element;
1943 * +index+ must be an
1944 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1946 * For non-negative +index+, returns the element of +self+ at offset +index+:
1948 * a = [:foo, 'bar', 2]
1949 * a.at(0) # => :foo
1950 * a.at(2) # => 2
1951 * a.at(2.0) # => 2
1953 * For negative +index+, counts backwards from the end of +self+:
1955 * a.at(-2) # => "bar"
1957 * Related: Array#[];
1958 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1961 VALUE
1962 rb_ary_at(VALUE ary, VALUE pos)
1964 return rb_ary_entry(ary, NUM2LONG(pos));
1967 #if 0
1968 static VALUE
1969 rb_ary_first(int argc, VALUE *argv, VALUE ary)
1971 if (argc == 0) {
1972 if (RARRAY_LEN(ary) == 0) return Qnil;
1973 return RARRAY_AREF(ary, 0);
1975 else {
1976 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1979 #endif
1981 static VALUE
1982 ary_first(VALUE self)
1984 return (RARRAY_LEN(self) == 0) ? Qnil : RARRAY_AREF(self, 0);
1987 static VALUE
1988 ary_last(VALUE self)
1990 long len = RARRAY_LEN(self);
1991 return (len == 0) ? Qnil : RARRAY_AREF(self, len-1);
1994 VALUE
1995 rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
1997 if (argc == 0) {
1998 return ary_last(ary);
2000 else {
2001 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
2006 * call-seq:
2007 * fetch(index) -> element
2008 * fetch(index, default_value) -> element or default_value
2009 * fetch(index) {|index| ... } -> element or block_return_value
2011 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2012 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2014 * With the single argument +index+ and no block,
2015 * returns the element at offset +index+:
2017 * a = [:foo, 'bar', 2]
2018 * a.fetch(1) # => "bar"
2019 * a.fetch(1.1) # => "bar"
2021 * If +index+ is negative, counts from the end of the array:
2023 * a = [:foo, 'bar', 2]
2024 * a.fetch(-1) # => 2
2025 * a.fetch(-2) # => "bar"
2027 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2028 * returns +default_value+ if +index+ is out-of-range:
2030 * a = [:foo, 'bar', 2]
2031 * a.fetch(1, nil) # => "bar"
2032 * a.fetch(3, :foo) # => :foo
2034 * With argument +index+ and a block,
2035 * returns the element at offset +index+ if index is in range
2036 * (and the block is not called); otherwise calls the block with index and returns its return value:
2038 * a = [:foo, 'bar', 2]
2039 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2040 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2042 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2045 static VALUE
2046 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
2048 VALUE pos, ifnone;
2049 long block_given;
2050 long idx;
2052 rb_scan_args(argc, argv, "11", &pos, &ifnone);
2053 block_given = rb_block_given_p();
2054 if (block_given && argc == 2) {
2055 rb_warn("block supersedes default value argument");
2057 idx = NUM2LONG(pos);
2059 if (idx < 0) {
2060 idx += RARRAY_LEN(ary);
2062 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
2063 if (block_given) return rb_yield(pos);
2064 if (argc == 1) {
2065 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
2066 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
2068 return ifnone;
2070 return RARRAY_AREF(ary, idx);
2074 * call-seq:
2075 * find_index(object) -> integer or nil
2076 * find_index {|element| ... } -> integer or nil
2077 * find_index -> new_enumerator
2078 * index(object) -> integer or nil
2079 * index {|element| ... } -> integer or nil
2080 * index -> new_enumerator
2082 * Returns the zero-based integer index of a specified element, or +nil+.
2084 * With only argument +object+ given,
2085 * returns the index of the first element +element+
2086 * for which <tt>object == element</tt>:
2088 * a = [:foo, 'bar', 2, 'bar']
2089 * a.index('bar') # => 1
2091 * Returns +nil+ if no such element found.
2093 * With only a block given,
2094 * calls the block with each successive element;
2095 * returns the index of the first element for which the block returns a truthy value:
2097 * a = [:foo, 'bar', 2, 'bar']
2098 * a.index {|element| element == 'bar' } # => 1
2100 * Returns +nil+ if the block never returns a truthy value.
2102 * With neither an argument nor a block given, returns a new Enumerator.
2104 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2107 static VALUE
2108 rb_ary_index(int argc, VALUE *argv, VALUE ary)
2110 VALUE val;
2111 long i;
2113 if (argc == 0) {
2114 RETURN_ENUMERATOR(ary, 0, 0);
2115 for (i=0; i<RARRAY_LEN(ary); i++) {
2116 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2117 return LONG2NUM(i);
2120 return Qnil;
2122 rb_check_arity(argc, 0, 1);
2123 val = argv[0];
2124 if (rb_block_given_p())
2125 rb_warn("given block not used");
2126 for (i=0; i<RARRAY_LEN(ary); i++) {
2127 VALUE e = RARRAY_AREF(ary, i);
2128 if (rb_equal(e, val)) {
2129 return LONG2NUM(i);
2132 return Qnil;
2136 * call-seq:
2137 * rindex(object) -> integer or nil
2138 * rindex {|element| ... } -> integer or nil
2139 * rindex -> new_enumerator
2141 * Returns the index of the last element for which <tt>object == element</tt>.
2143 * With argument +object+ given, returns the index of the last such element found:
2145 * a = [:foo, 'bar', 2, 'bar']
2146 * a.rindex('bar') # => 3
2148 * Returns +nil+ if no such object found.
2150 * With a block given, calls the block with each successive element;
2151 * returns the index of the last element for which the block returns a truthy value:
2153 * a = [:foo, 'bar', 2, 'bar']
2154 * a.rindex {|element| element == 'bar' } # => 3
2156 * Returns +nil+ if the block never returns a truthy value.
2158 * When neither an argument nor a block is given, returns a new Enumerator.
2160 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2163 static VALUE
2164 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
2166 VALUE val;
2167 long i = RARRAY_LEN(ary), len;
2169 if (argc == 0) {
2170 RETURN_ENUMERATOR(ary, 0, 0);
2171 while (i--) {
2172 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
2173 return LONG2NUM(i);
2174 if (i > (len = RARRAY_LEN(ary))) {
2175 i = len;
2178 return Qnil;
2180 rb_check_arity(argc, 0, 1);
2181 val = argv[0];
2182 if (rb_block_given_p())
2183 rb_warn("given block not used");
2184 while (i--) {
2185 VALUE e = RARRAY_AREF(ary, i);
2186 if (rb_equal(e, val)) {
2187 return LONG2NUM(i);
2189 if (i > RARRAY_LEN(ary)) {
2190 break;
2193 return Qnil;
2196 VALUE
2197 rb_ary_to_ary(VALUE obj)
2199 VALUE tmp = rb_check_array_type(obj);
2201 if (!NIL_P(tmp)) return tmp;
2202 return rb_ary_new3(1, obj);
2205 static void
2206 rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
2208 long olen;
2209 long rofs;
2211 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2212 olen = RARRAY_LEN(ary);
2213 if (beg < 0) {
2214 beg += olen;
2215 if (beg < 0) {
2216 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2217 beg - olen, -olen);
2220 if (olen < len || olen < beg + len) {
2221 len = olen - beg;
2225 const VALUE *optr = RARRAY_CONST_PTR(ary);
2226 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2229 if (beg >= olen) {
2230 VALUE target_ary;
2231 if (beg > ARY_MAX_SIZE - rlen) {
2232 rb_raise(rb_eIndexError, "index %ld too big", beg);
2234 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2235 len = beg + rlen;
2236 ary_mem_clear(ary, olen, beg - olen);
2237 if (rlen > 0) {
2238 if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
2239 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2241 ARY_SET_LEN(ary, len);
2243 else {
2244 long alen;
2246 if (olen - len > ARY_MAX_SIZE - rlen) {
2247 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2249 rb_ary_modify(ary);
2250 alen = olen + rlen - len;
2251 if (alen >= ARY_CAPA(ary)) {
2252 ary_double_capa(ary, alen);
2255 if (len != rlen) {
2256 RARRAY_PTR_USE(ary, ptr,
2257 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2258 VALUE, olen - (beg + len)));
2259 ARY_SET_LEN(ary, alen);
2261 if (rlen > 0) {
2262 if (rofs == -1) {
2263 rb_gc_writebarrier_remember(ary);
2265 else {
2266 /* In this case, we're copying from a region in this array, so
2267 * we don't need to fire the write barrier. */
2268 rptr = RARRAY_CONST_PTR(ary) + rofs;
2271 /* do not use RARRAY_PTR() because it can causes GC.
2272 * ary can contain T_NONE object because it is not cleared.
2274 RARRAY_PTR_USE(ary, ptr,
2275 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2280 void
2281 rb_ary_set_len(VALUE ary, long len)
2283 long capa;
2285 rb_ary_modify_check(ary);
2286 if (ARY_SHARED_P(ary)) {
2287 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2289 if (len > (capa = (long)ARY_CAPA(ary))) {
2290 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2292 ARY_SET_LEN(ary, len);
2295 VALUE
2296 rb_ary_resize(VALUE ary, long len)
2298 long olen;
2300 rb_ary_modify(ary);
2301 olen = RARRAY_LEN(ary);
2302 if (len == olen) return ary;
2303 if (len > ARY_MAX_SIZE) {
2304 rb_raise(rb_eIndexError, "index %ld too big", len);
2306 if (len > olen) {
2307 if (len >= ARY_CAPA(ary)) {
2308 ary_double_capa(ary, len);
2310 ary_mem_clear(ary, olen, len - olen);
2311 ARY_SET_LEN(ary, len);
2313 else if (ARY_EMBED_P(ary)) {
2314 ARY_SET_EMBED_LEN(ary, len);
2316 else if (len <= ary_embed_capa(ary)) {
2317 const VALUE *ptr = ARY_HEAP_PTR(ary);
2318 long ptr_capa = ARY_HEAP_SIZE(ary);
2319 bool is_malloc_ptr = !ARY_SHARED_P(ary);
2321 FL_SET_EMBED(ary);
2323 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
2324 ARY_SET_EMBED_LEN(ary, len);
2326 if (is_malloc_ptr) ruby_sized_xfree((void *)ptr, ptr_capa);
2328 else {
2329 if (olen > len + ARY_DEFAULT_SIZE) {
2330 size_t new_capa = ary_heap_realloc(ary, len);
2331 ARY_SET_CAPA(ary, new_capa);
2333 ARY_SET_HEAP_LEN(ary, len);
2335 ary_verify(ary);
2336 return ary;
2339 static VALUE
2340 ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2342 rb_ary_store(ary, key, val);
2343 return val;
2346 static VALUE
2347 ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2349 VALUE rpl = rb_ary_to_ary(val);
2350 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl));
2351 RB_GC_GUARD(rpl);
2352 return val;
2356 * call-seq:
2357 * self[index] = object -> object
2358 * self[start, length] = object -> object
2359 * self[range] = object -> object
2361 * Assigns elements in +self+, based on the given +object+; returns +object+.
2363 * In brief:
2365 * a_orig = [:foo, 'bar', 2]
2367 * # With argument index.
2368 * a = a_orig.dup
2369 * a[0] = 'foo' # => "foo"
2370 * a # => ["foo", "bar", 2]
2371 * a = a_orig.dup
2372 * a[7] = 'foo' # => "foo"
2373 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2375 * # With arguments start and length.
2376 * a = a_orig.dup
2377 * a[0, 2] = 'foo' # => "foo"
2378 * a # => ["foo", 2]
2379 * a = a_orig.dup
2380 * a[6, 50] = 'foo' # => "foo"
2381 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2383 * # With argument range.
2384 * a = a_orig.dup
2385 * a[0..1] = 'foo' # => "foo"
2386 * a # => ["foo", 2]
2387 * a = a_orig.dup
2388 * a[6..50] = 'foo' # => "foo"
2389 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2391 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2393 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2395 * a = [:foo, 'bar', 2]
2396 * a[0] = 'foo' # => "foo"
2397 * a # => ["foo", "bar", 2]
2399 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2401 * a = [:foo, 'bar', 2]
2402 * a[7] = 'foo' # => "foo"
2403 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2405 * If +index+ is negative, counts backwards from the end of the array:
2407 * a = [:foo, 'bar', 2]
2408 * a[-1] = 'two' # => "two"
2409 * a # => [:foo, "bar", "two"]
2411 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2412 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2413 * and assigns +object+ at offset +start+:
2415 * a = [:foo, 'bar', 2]
2416 * a[0, 2] = 'foo' # => "foo"
2417 * a # => ["foo", 2]
2419 * If +start+ is negative, counts backwards from the end of the array:
2421 * a = [:foo, 'bar', 2]
2422 * a[-2, 2] = 'foo' # => "foo"
2423 * a # => [:foo, "foo"]
2425 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2426 * extends the array with +nil+, assigns +object+ at offset +start+,
2427 * and ignores +length+:
2429 * a = [:foo, 'bar', 2]
2430 * a[6, 50] = 'foo' # => "foo"
2431 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2433 * If +length+ is zero, shifts elements at and following offset +start+
2434 * and assigns +object+ at offset +start+:
2436 * a = [:foo, 'bar', 2]
2437 * a[1, 0] = 'foo' # => "foo"
2438 * a # => [:foo, "foo", "bar", 2]
2440 * If +length+ is too large for the existing array, does not extend the array:
2442 * a = [:foo, 'bar', 2]
2443 * a[1, 5] = 'foo' # => "foo"
2444 * a # => [:foo, "foo"]
2446 * When Range argument +range+ is given and +object+ is not an +Array+,
2447 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2448 * and assigns +object+ at offset +start+:
2450 * a = [:foo, 'bar', 2]
2451 * a[0..1] = 'foo' # => "foo"
2452 * a # => ["foo", 2]
2454 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2456 * a = [:foo, 'bar', 2]
2457 * a[-2..2] = 'foo' # => "foo"
2458 * a # => [:foo, "foo"]
2460 * If the array length is less than <tt>range.begin</tt>,
2461 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2462 * and ignores +length+:
2464 * a = [:foo, 'bar', 2]
2465 * a[6..50] = 'foo' # => "foo"
2466 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2468 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2469 * and assigns +object+ at offset +start+:
2471 * a = [:foo, 'bar', 2]
2472 * a[1..0] = 'foo' # => "foo"
2473 * a # => [:foo, "foo", "bar", 2]
2475 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2476 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2478 * a = [:foo, 'bar', 2]
2479 * a[1..-1] = 'foo' # => "foo"
2480 * a # => [:foo, "foo"]
2481 * a = [:foo, 'bar', 2]
2482 * a[1..-2] = 'foo' # => "foo"
2483 * a # => [:foo, "foo", 2]
2484 * a = [:foo, 'bar', 2]
2485 * a[1..-3] = 'foo' # => "foo"
2486 * a # => [:foo, "foo", "bar", 2]
2487 * a = [:foo, 'bar', 2]
2489 * If <tt>range.end</tt> is too large for the existing array,
2490 * replaces array elements, but does not extend the array with +nil+ values:
2492 * a = [:foo, 'bar', 2]
2493 * a[1..5] = 'foo' # => "foo"
2494 * a # => [:foo, "foo"]
2496 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2499 static VALUE
2500 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2502 long offset, beg, len;
2504 rb_check_arity(argc, 2, 3);
2505 rb_ary_modify_check(ary);
2506 if (argc == 3) {
2507 beg = NUM2LONG(argv[0]);
2508 len = NUM2LONG(argv[1]);
2509 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2511 if (FIXNUM_P(argv[0])) {
2512 offset = FIX2LONG(argv[0]);
2513 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2515 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2516 /* check if idx is Range */
2517 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2520 offset = NUM2LONG(argv[0]);
2521 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2525 * call-seq:
2526 * insert(index, *objects) -> self
2528 * Inserts the given +objects+ as elements of +self+;
2529 * returns +self+.
2531 * When +index+ is non-negative, inserts +objects+
2532 * _before_ the element at offset +index+:
2534 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2535 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2537 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2539 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2540 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2542 * When +index+ is negative, inserts +objects+
2543 * _after_ the element at offset <tt>index + self.size</tt>:
2545 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2546 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2548 * With no +objects+ given, does nothing:
2550 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2551 * a.insert(1) # => ["a", "b", "c"]
2552 * a.insert(50) # => ["a", "b", "c"]
2553 * a.insert(-50) # => ["a", "b", "c"]
2555 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2557 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2560 static VALUE
2561 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2563 long pos;
2565 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
2566 rb_ary_modify_check(ary);
2567 pos = NUM2LONG(argv[0]);
2568 if (argc == 1) return ary;
2569 if (pos == -1) {
2570 pos = RARRAY_LEN(ary);
2572 else if (pos < 0) {
2573 long minpos = -RARRAY_LEN(ary) - 1;
2574 if (pos < minpos) {
2575 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2576 pos, minpos);
2578 pos++;
2580 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2581 return ary;
2584 static VALUE
2585 rb_ary_length(VALUE ary);
2587 static VALUE
2588 ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2590 return rb_ary_length(ary);
2593 // Primitive to avoid a race condition in Array#each.
2594 // Return `true` and write `value` and `index` if the element exists.
2595 static VALUE
2596 ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
2598 long i = NUM2LONG(*index);
2599 if (i >= RARRAY_LEN(self)) {
2600 return Qfalse;
2602 *value = RARRAY_AREF(self, i);
2603 *index = LONG2NUM(i + 1);
2604 return Qtrue;
2607 VALUE
2608 rb_ary_each(VALUE ary)
2610 long i;
2611 ary_verify(ary);
2612 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2613 for (i=0; i<RARRAY_LEN(ary); i++) {
2614 rb_yield(RARRAY_AREF(ary, i));
2616 return ary;
2620 * call-seq:
2621 * each_index {|index| ... } -> self
2622 * each_index -> new_enumerator
2624 * With a block given, iterates over the elements of +self+,
2625 * passing each <i>array index</i> to the block;
2626 * returns +self+:
2628 * a = [:foo, 'bar', 2]
2629 * a.each_index {|index| puts "#{index} #{a[index]}" }
2631 * Output:
2633 * 0 foo
2634 * 1 bar
2635 * 2 2
2637 * Allows the array to be modified during iteration:
2639 * a = [:foo, 'bar', 2]
2640 * a.each_index {|index| puts index; a.clear if index > 0 }
2641 * a # => []
2643 * Output:
2648 * With no block given, returns a new Enumerator.
2650 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2653 static VALUE
2654 rb_ary_each_index(VALUE ary)
2656 long i;
2657 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2659 for (i=0; i<RARRAY_LEN(ary); i++) {
2660 rb_yield(LONG2NUM(i));
2662 return ary;
2666 * call-seq:
2667 * reverse_each {|element| ... } -> self
2668 * reverse_each -> Enumerator
2670 * When a block given, iterates backwards over the elements of +self+,
2671 * passing, in reverse order, each element to the block;
2672 * returns +self+:
2674 * a = []
2675 * [0, 1, 2].reverse_each {|element| a.push(element) }
2676 * a # => [2, 1, 0]
2678 * Allows the array to be modified during iteration:
2680 * a = ['a', 'b', 'c']
2681 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2682 * a # => []
2684 * When no block given, returns a new Enumerator.
2686 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2689 static VALUE
2690 rb_ary_reverse_each(VALUE ary)
2692 long len;
2694 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2695 len = RARRAY_LEN(ary);
2696 while (len--) {
2697 long nlen;
2698 rb_yield(RARRAY_AREF(ary, len));
2699 nlen = RARRAY_LEN(ary);
2700 if (nlen < len) {
2701 len = nlen;
2704 return ary;
2708 * call-seq:
2709 * length -> integer
2710 * size -> integer
2712 * Returns the count of elements in +self+:
2714 * [0, 1, 2].length # => 3
2715 * [].length # => 0
2717 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2720 static VALUE
2721 rb_ary_length(VALUE ary)
2723 long len = RARRAY_LEN(ary);
2724 return LONG2NUM(len);
2728 * call-seq:
2729 * array.empty? -> true or false
2731 * Returns +true+ if the count of elements in +self+ is zero,
2732 * +false+ otherwise.
2734 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2737 static VALUE
2738 rb_ary_empty_p(VALUE ary)
2740 return RBOOL(RARRAY_LEN(ary) == 0);
2743 VALUE
2744 rb_ary_dup(VALUE ary)
2746 long len = RARRAY_LEN(ary);
2747 VALUE dup = rb_ary_new2(len);
2748 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2749 ARY_SET_LEN(dup, len);
2751 ary_verify(ary);
2752 ary_verify(dup);
2753 return dup;
2756 VALUE
2757 rb_ary_resurrect(VALUE ary)
2759 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2762 extern VALUE rb_output_fs;
2764 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2766 static VALUE
2767 recursive_join(VALUE obj, VALUE argp, int recur)
2769 VALUE *arg = (VALUE *)argp;
2770 VALUE ary = arg[0];
2771 VALUE sep = arg[1];
2772 VALUE result = arg[2];
2773 int *first = (int *)arg[3];
2775 if (recur) {
2776 rb_raise(rb_eArgError, "recursive array join");
2778 else {
2779 ary_join_1(obj, ary, sep, 0, result, first);
2781 return Qnil;
2784 static long
2785 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2787 long i;
2788 VALUE val;
2790 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2791 for (i=0; i<max; i++) {
2792 val = RARRAY_AREF(ary, i);
2793 if (!RB_TYPE_P(val, T_STRING)) break;
2794 if (i > 0 && !NIL_P(sep))
2795 rb_str_buf_append(result, sep);
2796 rb_str_buf_append(result, val);
2798 return i;
2801 static void
2802 ary_join_1_str(VALUE dst, VALUE src, int *first)
2804 rb_str_buf_append(dst, src);
2805 if (*first) {
2806 rb_enc_copy(dst, src);
2807 *first = FALSE;
2811 static void
2812 ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
2814 if (val == ary) {
2815 rb_raise(rb_eArgError, "recursive array join");
2817 else {
2818 VALUE args[4];
2820 *first = FALSE;
2821 args[0] = val;
2822 args[1] = sep;
2823 args[2] = result;
2824 args[3] = (VALUE)first;
2825 rb_exec_recursive(recursive_join, obj, (VALUE)args);
2829 static void
2830 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
2832 VALUE val, tmp;
2834 for (; i<RARRAY_LEN(ary); i++) {
2835 if (i > 0 && !NIL_P(sep))
2836 rb_str_buf_append(result, sep);
2838 val = RARRAY_AREF(ary, i);
2839 if (RB_TYPE_P(val, T_STRING)) {
2840 ary_join_1_str(result, val, first);
2842 else if (RB_TYPE_P(val, T_ARRAY)) {
2843 ary_join_1_ary(val, ary, sep, result, val, first);
2845 else if (!NIL_P(tmp = rb_check_string_type(val))) {
2846 ary_join_1_str(result, tmp, first);
2848 else if (!NIL_P(tmp = rb_check_array_type(val))) {
2849 ary_join_1_ary(val, ary, sep, result, tmp, first);
2851 else {
2852 ary_join_1_str(result, rb_obj_as_string(val), first);
2857 VALUE
2858 rb_ary_join(VALUE ary, VALUE sep)
2860 long len = 1, i;
2861 VALUE val, tmp, result;
2863 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
2865 if (!NIL_P(sep)) {
2866 StringValue(sep);
2867 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
2869 for (i=0; i<RARRAY_LEN(ary); i++) {
2870 val = RARRAY_AREF(ary, i);
2871 tmp = rb_check_string_type(val);
2873 if (NIL_P(tmp) || tmp != val) {
2874 int first;
2875 long n = RARRAY_LEN(ary);
2876 if (i > n) i = n;
2877 result = rb_str_buf_new(len + (n-i)*10);
2878 rb_enc_associate(result, rb_usascii_encoding());
2879 i = ary_join_0(ary, sep, i, result);
2880 first = i == 0;
2881 ary_join_1(ary, ary, sep, i, result, &first);
2882 return result;
2885 len += RSTRING_LEN(tmp);
2888 result = rb_str_new(0, len);
2889 rb_str_set_len(result, 0);
2891 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
2893 return result;
2897 * call-seq:
2898 * array.join(separator = $,) -> new_string
2900 * Returns the new string formed by joining the converted elements of +self+;
2901 * for each element +element+:
2903 * - Converts recursively using <tt>element.join(separator)</tt>
2904 * if +element+ is a <tt>kind_of?(Array)</tt>.
2905 * - Otherwise, converts using <tt>element.to_s</tt>.
2907 * With no argument given, joins using the output field separator, <tt>$,</tt>:
2909 * a = [:foo, 'bar', 2]
2910 * $, # => nil
2911 * a.join # => "foobar2"
2913 * With string argument +separator+ given, joins using that separator:
2915 * a = [:foo, 'bar', 2]
2916 * a.join("\n") # => "foo\nbar\n2"
2918 * Joins recursively for nested arrays:
2920 * a = [:foo, [:bar, [:baz, :bat]]]
2921 * a.join # => "foobarbazbat"
2923 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2925 static VALUE
2926 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
2928 VALUE sep;
2930 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
2931 sep = rb_output_fs;
2932 if (!NIL_P(sep)) {
2933 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
2937 return rb_ary_join(ary, sep);
2940 static VALUE
2941 inspect_ary(VALUE ary, VALUE dummy, int recur)
2943 long i;
2944 VALUE s, str;
2946 if (recur) return rb_usascii_str_new_cstr("[...]");
2947 str = rb_str_buf_new2("[");
2948 for (i=0; i<RARRAY_LEN(ary); i++) {
2949 s = rb_inspect(RARRAY_AREF(ary, i));
2950 if (i > 0) rb_str_buf_cat2(str, ", ");
2951 else rb_enc_copy(str, s);
2952 rb_str_buf_append(str, s);
2954 rb_str_buf_cat2(str, "]");
2955 return str;
2959 * call-seq:
2960 * inspect -> new_string
2961 * to_s -> new_string
2963 * Returns the new string formed by calling method <tt>#inspect</tt>
2964 * on each array element:
2966 * a = [:foo, 'bar', 2]
2967 * a.inspect # => "[:foo, \"bar\", 2]"
2969 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2972 static VALUE
2973 rb_ary_inspect(VALUE ary)
2975 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
2976 return rb_exec_recursive(inspect_ary, ary, 0);
2979 VALUE
2980 rb_ary_to_s(VALUE ary)
2982 return rb_ary_inspect(ary);
2986 * call-seq:
2987 * to_a -> self or new_array
2989 * When +self+ is an instance of +Array+, returns +self+.
2991 * Otherwise, returns a new array containing the elements of +self+:
2993 * class MyArray < Array; end
2994 * my_a = MyArray.new(['foo', 'bar', 'two'])
2995 * a = my_a.to_a
2996 * a # => ["foo", "bar", "two"]
2997 * a.class # => Array # Not MyArray.
2999 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3002 static VALUE
3003 rb_ary_to_a(VALUE ary)
3005 if (rb_obj_class(ary) != rb_cArray) {
3006 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
3007 rb_ary_replace(dup, ary);
3008 return dup;
3010 return ary;
3014 * call-seq:
3015 * to_h -> new_hash
3016 * to_h {|element| ... } -> new_hash
3018 * Returns a new hash formed from +self+.
3020 * With no block given, each element of +self+ must be a 2-element sub-array;
3021 * forms each sub-array into a key-value pair in the new hash:
3023 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3024 * a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3025 * [].to_h # => {}
3027 * With a block given, the block must return a 2-element array;
3028 * calls the block with each element of +self+;
3029 * forms each returned array into a key-value pair in the returned hash:
3031 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3032 * a.to_h {|element| [element, element.class] }
3033 * # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
3035 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3038 static VALUE
3039 rb_ary_to_h(VALUE ary)
3041 long i;
3042 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
3043 int block_given = rb_block_given_p();
3045 for (i=0; i<RARRAY_LEN(ary); i++) {
3046 const VALUE e = rb_ary_elt(ary, i);
3047 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3048 const VALUE key_value_pair = rb_check_array_type(elt);
3049 if (NIL_P(key_value_pair)) {
3050 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
3051 rb_obj_class(elt), i);
3053 if (RARRAY_LEN(key_value_pair) != 2) {
3054 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
3055 i, RARRAY_LEN(key_value_pair));
3057 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3059 return hash;
3063 * call-seq:
3064 * array.to_ary -> self
3066 * Returns +self+.
3069 static VALUE
3070 rb_ary_to_ary_m(VALUE ary)
3072 return ary;
3075 static void
3076 ary_reverse(VALUE *p1, VALUE *p2)
3078 while (p1 < p2) {
3079 VALUE tmp = *p1;
3080 *p1++ = *p2;
3081 *p2-- = tmp;
3085 VALUE
3086 rb_ary_reverse(VALUE ary)
3088 VALUE *p2;
3089 long len = RARRAY_LEN(ary);
3091 rb_ary_modify(ary);
3092 if (len > 1) {
3093 RARRAY_PTR_USE(ary, p1, {
3094 p2 = p1 + len - 1; /* points last item */
3095 ary_reverse(p1, p2);
3096 }); /* WB: no new reference */
3098 return ary;
3102 * call-seq:
3103 * reverse! -> self
3105 * Reverses the order of the elements of +self+;
3106 * returns +self+:
3108 * a = [0, 1, 2]
3109 * a.reverse! # => [2, 1, 0]
3110 * a # => [2, 1, 0]
3112 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3115 static VALUE
3116 rb_ary_reverse_bang(VALUE ary)
3118 return rb_ary_reverse(ary);
3122 * call-seq:
3123 * reverse -> new_array
3125 * Returns a new array containing the elements of +self+ in reverse order:
3127 * [0, 1, 2].reverse # => [2, 1, 0]
3129 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3132 static VALUE
3133 rb_ary_reverse_m(VALUE ary)
3135 long len = RARRAY_LEN(ary);
3136 VALUE dup = rb_ary_new2(len);
3138 if (len > 0) {
3139 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3140 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3141 do *p2-- = *p1++; while (--len > 0);
3143 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3144 return dup;
3147 static inline long
3148 rotate_count(long cnt, long len)
3150 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3153 static void
3154 ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3156 if (cnt == 1) {
3157 VALUE tmp = *ptr;
3158 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3159 *(ptr + len - 1) = tmp;
3161 else if (cnt == len - 1) {
3162 VALUE tmp = *(ptr + len - 1);
3163 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3164 *ptr = tmp;
3166 else {
3167 --len;
3168 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3169 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3170 if (len > 0) ary_reverse(ptr, ptr + len);
3174 VALUE
3175 rb_ary_rotate(VALUE ary, long cnt)
3177 rb_ary_modify(ary);
3179 if (cnt != 0) {
3180 long len = RARRAY_LEN(ary);
3181 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3182 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3183 return ary;
3186 return Qnil;
3190 * call-seq:
3191 * rotate!(count = 1) -> self
3193 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3195 * With non-negative numeric +count+,
3196 * rotates +count+ elements from the beginning to the end:
3198 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3199 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3201 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3203 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3205 * If +count+ is zero, rotates no elements:
3207 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3209 * With a negative numeric +count+, rotates in the opposite direction,
3210 * from end to beginning:
3212 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3214 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3216 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3218 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3221 static VALUE
3222 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3224 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3225 rb_ary_rotate(ary, n);
3226 return ary;
3230 * call-seq:
3231 * rotate(count = 1) -> new_array
3233 * Returns a new array formed from +self+ with elements
3234 * rotated from one end to the other.
3236 * With non-negative numeric +count+,
3237 * rotates elements from the beginning to the end:
3239 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3240 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3242 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3244 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3246 * With a +count+ of zero, rotates no elements:
3248 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3250 * With negative numeric +count+, rotates in the opposite direction,
3251 * from the end to the beginning:
3253 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3255 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3257 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3259 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3262 static VALUE
3263 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3265 VALUE rotated;
3266 const VALUE *ptr;
3267 long len;
3268 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3270 len = RARRAY_LEN(ary);
3271 rotated = rb_ary_new2(len);
3272 if (len > 0) {
3273 cnt = rotate_count(cnt, len);
3274 ptr = RARRAY_CONST_PTR(ary);
3275 len -= cnt;
3276 ary_memcpy(rotated, 0, len, ptr + cnt);
3277 ary_memcpy(rotated, len, cnt, ptr);
3279 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3280 return rotated;
3283 struct ary_sort_data {
3284 VALUE ary;
3285 VALUE receiver;
3288 static VALUE
3289 sort_reentered(VALUE ary)
3291 if (RBASIC(ary)->klass) {
3292 rb_raise(rb_eRuntimeError, "sort reentered");
3294 return Qnil;
3297 static void
3298 sort_returned(struct ary_sort_data *data)
3300 if (rb_obj_frozen_p(data->receiver)) {
3301 rb_raise(rb_eFrozenError, "array frozen during sort");
3303 sort_reentered(data->ary);
3306 static int
3307 sort_1(const void *ap, const void *bp, void *dummy)
3309 struct ary_sort_data *data = dummy;
3310 VALUE retval = sort_reentered(data->ary);
3311 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3312 VALUE args[2];
3313 int n;
3315 args[0] = a;
3316 args[1] = b;
3317 retval = rb_yield_values2(2, args);
3318 n = rb_cmpint(retval, a, b);
3319 sort_returned(data);
3320 return n;
3323 static int
3324 sort_2(const void *ap, const void *bp, void *dummy)
3326 struct ary_sort_data *data = dummy;
3327 VALUE retval = sort_reentered(data->ary);
3328 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3329 int n;
3331 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3332 if ((long)a > (long)b) return 1;
3333 if ((long)a < (long)b) return -1;
3334 return 0;
3336 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3337 return rb_str_cmp(a, b);
3339 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3340 return rb_float_cmp(a, b);
3343 retval = rb_funcallv(a, id_cmp, 1, &b);
3344 n = rb_cmpint(retval, a, b);
3345 sort_returned(data);
3347 return n;
3351 * call-seq:
3352 * sort! -> self
3353 * sort! {|a, b| ... } -> self
3355 * Like Array#sort, but returns +self+ with its elements sorted in place.
3357 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3360 VALUE
3361 rb_ary_sort_bang(VALUE ary)
3363 rb_ary_modify(ary);
3364 RUBY_ASSERT(!ARY_SHARED_P(ary));
3365 if (RARRAY_LEN(ary) > 1) {
3366 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3367 struct ary_sort_data data;
3368 long len = RARRAY_LEN(ary);
3369 RBASIC_CLEAR_CLASS(tmp);
3370 data.ary = tmp;
3371 data.receiver = ary;
3372 RARRAY_PTR_USE(tmp, ptr, {
3373 ruby_qsort(ptr, len, sizeof(VALUE),
3374 rb_block_given_p()?sort_1:sort_2, &data);
3375 }); /* WB: no new reference */
3376 rb_ary_modify(ary);
3377 if (ARY_EMBED_P(tmp)) {
3378 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3379 rb_ary_unshare(ary);
3380 FL_SET_EMBED(ary);
3382 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3383 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3385 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3386 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3388 else {
3389 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3390 FL_UNSET_SHARED(ary);
3391 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3393 else {
3394 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3395 if (ARY_EMBED_P(ary)) {
3396 FL_UNSET_EMBED(ary);
3398 else if (ARY_SHARED_P(ary)) {
3399 /* ary might be destructively operated in the given block */
3400 rb_ary_unshare(ary);
3402 else {
3403 ary_heap_free(ary);
3405 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3406 ARY_SET_HEAP_LEN(ary, len);
3407 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3409 /* tmp was lost ownership for the ptr */
3410 FL_UNSET(tmp, FL_FREEZE);
3411 FL_SET_EMBED(tmp);
3412 ARY_SET_EMBED_LEN(tmp, 0);
3413 FL_SET(tmp, FL_FREEZE);
3415 /* tmp will be GC'ed. */
3416 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3418 ary_verify(ary);
3419 return ary;
3423 * call-seq:
3424 * sort -> new_array
3425 * sort {|a, b| ... } -> new_array
3427 * Returns a new array containing the elements of +self+, sorted.
3429 * With no block given, compares elements using operator <tt>#<=></tt>
3430 * (see Object#<=>):
3432 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3434 * With a block given, calls the block with each combination of pairs of elements from +self+;
3435 * for each pair +a+ and +b+, the block should return a numeric:
3437 * - Negative when +b+ is to follow +a+.
3438 * - Zero when +a+ and +b+ are equivalent.
3439 * - Positive when +a+ is to follow +b+.
3441 * Example:
3443 * a = [3, 2, 0, 1]
3444 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3445 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3447 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3448 * and may be unstable.
3450 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3453 VALUE
3454 rb_ary_sort(VALUE ary)
3456 ary = rb_ary_dup(ary);
3457 rb_ary_sort_bang(ary);
3458 return ary;
3461 static VALUE rb_ary_bsearch_index(VALUE ary);
3464 * call-seq:
3465 * bsearch {|element| ... } -> found_element or nil
3466 * bsearch -> new_enumerator
3468 * Returns the element from +self+ found by a binary search,
3469 * or +nil+ if the search found no suitable element.
3471 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3473 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3476 static VALUE
3477 rb_ary_bsearch(VALUE ary)
3479 VALUE index_result = rb_ary_bsearch_index(ary);
3481 if (FIXNUM_P(index_result)) {
3482 return rb_ary_entry(ary, FIX2LONG(index_result));
3484 return index_result;
3488 * call-seq:
3489 * bsearch_index {|element| ... } -> integer or nil
3490 * bsearch_index -> new_enumerator
3492 * Returns the integer index of the element from +self+ found by a binary search,
3493 * or +nil+ if the search found no suitable element.
3495 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3497 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3500 static VALUE
3501 rb_ary_bsearch_index(VALUE ary)
3503 long low = 0, high = RARRAY_LEN(ary), mid;
3504 int smaller = 0, satisfied = 0;
3505 VALUE v, val;
3507 RETURN_ENUMERATOR(ary, 0, 0);
3508 while (low < high) {
3509 mid = low + ((high - low) / 2);
3510 val = rb_ary_entry(ary, mid);
3511 v = rb_yield(val);
3512 if (FIXNUM_P(v)) {
3513 if (v == INT2FIX(0)) return INT2FIX(mid);
3514 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3516 else if (v == Qtrue) {
3517 satisfied = 1;
3518 smaller = 1;
3520 else if (!RTEST(v)) {
3521 smaller = 0;
3523 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3524 const VALUE zero = INT2FIX(0);
3525 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3526 case 0: return INT2FIX(mid);
3527 case 1: smaller = 0; break;
3528 case -1: smaller = 1;
3531 else {
3532 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3533 " (must be numeric, true, false or nil)",
3534 rb_obj_class(v));
3536 if (smaller) {
3537 high = mid;
3539 else {
3540 low = mid + 1;
3543 if (!satisfied) return Qnil;
3544 return INT2FIX(low);
3548 static VALUE
3549 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3551 return rb_yield(i);
3555 * call-seq:
3556 * sort_by! {|element| ... } -> self
3557 * sort_by! -> new_enumerator
3559 * With a block given, sorts the elements of +self+ in place;
3560 * returns self.
3562 * Calls the block with each successive element;
3563 * sorts elements based on the values returned from the block:
3565 * a = ['aaaa', 'bbb', 'cc', 'd']
3566 * a.sort_by! {|element| element.size }
3567 * a # => ["d", "cc", "bbb", "aaaa"]
3569 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3571 * With no block given, returns a new Enumerator.
3573 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3576 static VALUE
3577 rb_ary_sort_by_bang(VALUE ary)
3579 VALUE sorted;
3581 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3582 rb_ary_modify(ary);
3583 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3584 rb_ary_replace(ary, sorted);
3585 return ary;
3590 * call-seq:
3591 * collect {|element| ... } -> new_array
3592 * collect -> new_enumerator
3593 * map {|element| ... } -> new_array
3594 * map -> new_enumerator
3596 * With a block given, calls the block with each element of +self+;
3597 * returns a new array whose elements are the return values from the block:
3599 * a = [:foo, 'bar', 2]
3600 * a1 = a.map {|element| element.class }
3601 * a1 # => [Symbol, String, Integer]
3603 * With no block given, returns a new Enumerator.
3605 * Related: #collect!;
3606 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3609 static VALUE
3610 rb_ary_collect(VALUE ary)
3612 long i;
3613 VALUE collect;
3615 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3616 collect = rb_ary_new2(RARRAY_LEN(ary));
3617 for (i = 0; i < RARRAY_LEN(ary); i++) {
3618 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3620 return collect;
3625 * call-seq:
3626 * collect! {|element| ... } -> new_array
3627 * collect! -> new_enumerator
3628 * map! {|element| ... } -> new_array
3629 * map! -> new_enumerator
3631 * With a block given, calls the block with each element of +self+
3632 * and replaces the element with the block's return value;
3633 * returns +self+:
3635 * a = [:foo, 'bar', 2]
3636 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3638 * With no block given, returns a new Enumerator.
3640 * Related: #collect;
3641 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3644 static VALUE
3645 rb_ary_collect_bang(VALUE ary)
3647 long i;
3649 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3650 rb_ary_modify(ary);
3651 for (i = 0; i < RARRAY_LEN(ary); i++) {
3652 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3654 return ary;
3657 VALUE
3658 rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3660 VALUE result = rb_ary_new2(argc);
3661 long beg, len, i, j;
3663 for (i=0; i<argc; i++) {
3664 if (FIXNUM_P(argv[i])) {
3665 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3666 continue;
3668 /* check if idx is Range */
3669 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3670 long end = olen < beg+len ? olen : beg+len;
3671 for (j = beg; j < end; j++) {
3672 rb_ary_push(result, (*func)(obj, j));
3674 if (beg + len > j)
3675 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3676 continue;
3678 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3680 return result;
3683 static VALUE
3684 append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3686 long beg, len;
3687 if (FIXNUM_P(idx)) {
3688 beg = FIX2LONG(idx);
3690 /* check if idx is Range */
3691 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3692 if (len > 0) {
3693 const VALUE *const src = RARRAY_CONST_PTR(ary);
3694 const long end = beg + len;
3695 const long prevlen = RARRAY_LEN(result);
3696 if (beg < olen) {
3697 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3699 if (end > olen) {
3700 rb_ary_store(result, prevlen + len - 1, Qnil);
3703 return result;
3705 else {
3706 beg = NUM2LONG(idx);
3708 return rb_ary_push(result, rb_ary_entry(ary, beg));
3712 * call-seq:
3713 * array.values_at(*indexes) -> new_array
3715 * Returns a new +Array+ whose elements are the elements
3716 * of +self+ at the given Integer or Range +indexes+.
3718 * For each positive +index+, returns the element at offset +index+:
3720 * a = [:foo, 'bar', 2]
3721 * a.values_at(0, 2) # => [:foo, 2]
3722 * a.values_at(0..1) # => [:foo, "bar"]
3724 * The given +indexes+ may be in any order, and may repeat:
3726 * a = [:foo, 'bar', 2]
3727 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3728 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3730 * Assigns +nil+ for an +index+ that is too large:
3732 * a = [:foo, 'bar', 2]
3733 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3735 * Returns a new empty +Array+ if no arguments given.
3737 * For each negative +index+, counts backward from the end of the array:
3739 * a = [:foo, 'bar', 2]
3740 * a.values_at(-1, -3) # => [2, :foo]
3742 * Assigns +nil+ for an +index+ that is too small:
3744 * a = [:foo, 'bar', 2]
3745 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3747 * The given +indexes+ may have a mixture of signs:
3749 * a = [:foo, 'bar', 2]
3750 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3754 static VALUE
3755 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
3757 long i, olen = RARRAY_LEN(ary);
3758 VALUE result = rb_ary_new_capa(argc);
3759 for (i = 0; i < argc; ++i) {
3760 append_values_at_single(result, ary, olen, argv[i]);
3762 RB_GC_GUARD(ary);
3763 return result;
3768 * call-seq:
3769 * select {|element| ... } -> new_array
3770 * select -> new_enumerator
3771 * filter {|element| ... } -> new_array
3772 * filter -> new_enumerator
3774 * With a block given, calls the block with each element of +self+;
3775 * returns a new array containing those elements of +self+
3776 * for which the block returns a truthy value:
3778 * a = [:foo, 'bar', 2, :bam]
3779 * a.select {|element| element.to_s.start_with?('b') }
3780 * # => ["bar", :bam]
3782 * With no block given, returns a new Enumerator.
3784 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3787 static VALUE
3788 rb_ary_select(VALUE ary)
3790 VALUE result;
3791 long i;
3793 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3794 result = rb_ary_new2(RARRAY_LEN(ary));
3795 for (i = 0; i < RARRAY_LEN(ary); i++) {
3796 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
3797 rb_ary_push(result, rb_ary_elt(ary, i));
3800 return result;
3803 struct select_bang_arg {
3804 VALUE ary;
3805 long len[2];
3808 static VALUE
3809 select_bang_i(VALUE a)
3811 volatile struct select_bang_arg *arg = (void *)a;
3812 VALUE ary = arg->ary;
3813 long i1, i2;
3815 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
3816 VALUE v = RARRAY_AREF(ary, i1);
3817 if (!RTEST(rb_yield(v))) continue;
3818 if (i1 != i2) {
3819 rb_ary_store(ary, i2, v);
3821 arg->len[1] = ++i2;
3823 return (i1 == i2) ? Qnil : ary;
3826 static VALUE
3827 select_bang_ensure(VALUE a)
3829 volatile struct select_bang_arg *arg = (void *)a;
3830 VALUE ary = arg->ary;
3831 long len = RARRAY_LEN(ary);
3832 long i1 = arg->len[0], i2 = arg->len[1];
3834 if (i2 < len && i2 < i1) {
3835 long tail = 0;
3836 rb_ary_modify(ary);
3837 if (i1 < len) {
3838 tail = len - i1;
3839 RARRAY_PTR_USE(ary, ptr, {
3840 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
3843 ARY_SET_LEN(ary, i2 + tail);
3845 return ary;
3849 * call-seq:
3850 * select! {|element| ... } -> self or nil
3851 * select! -> new_enumerator
3852 * filter! {|element| ... } -> self or nil
3853 * filter! -> new_enumerator
3855 * With a block given, calls the block with each element of +self+;
3856 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3858 * Returns +self+ if any elements were removed:
3860 * a = [:foo, 'bar', 2, :bam]
3861 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3863 * Returns +nil+ if no elements were removed.
3865 * With no block given, returns a new Enumerator.
3867 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3870 static VALUE
3871 rb_ary_select_bang(VALUE ary)
3873 struct select_bang_arg args;
3875 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3876 rb_ary_modify(ary);
3878 args.ary = ary;
3879 args.len[0] = args.len[1] = 0;
3880 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
3884 * call-seq:
3885 * keep_if {|element| ... } -> self
3886 * keep_if -> new_enumerator
3888 * With a block given, calls the block with each element of +self+;
3889 * removes the element from +self+ if the block does not return a truthy value:
3891 * a = [:foo, 'bar', 2, :bam]
3892 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3894 * With no block given, returns a new Enumerator.
3896 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3899 static VALUE
3900 rb_ary_keep_if(VALUE ary)
3902 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3903 rb_ary_select_bang(ary);
3904 return ary;
3907 static void
3908 ary_resize_smaller(VALUE ary, long len)
3910 rb_ary_modify(ary);
3911 if (RARRAY_LEN(ary) > len) {
3912 ARY_SET_LEN(ary, len);
3913 if (len * 2 < ARY_CAPA(ary) &&
3914 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
3915 ary_resize_capa(ary, len * 2);
3921 * call-seq:
3922 * delete(object) -> last_removed_object
3923 * delete(object) {|element| ... } -> last_removed_object or block_return
3925 * Removes zero or more elements from +self+.
3927 * With no block given,
3928 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
3929 * returns the last removed element:
3931 * a = [0, 1, 2, 2.0]
3932 * a.delete(2) # => 2.0
3933 * a # => [0, 1]
3935 * Returns +nil+ if no elements removed:
3937 * a.delete(2) # => nil
3939 * With a block given,
3940 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
3942 * If any such elements are found, ignores the block
3943 * and returns the last removed element:
3945 * a = [0, 1, 2, 2.0]
3946 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
3947 * a # => [0, 1]
3949 * If no such element is found, returns the block's return value:
3951 * a.delete(2) {|element| "Element #{element} not found." }
3952 * # => "Element 2 not found."
3954 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3957 VALUE
3958 rb_ary_delete(VALUE ary, VALUE item)
3960 VALUE v = item;
3961 long i1, i2;
3963 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
3964 VALUE e = RARRAY_AREF(ary, i1);
3966 if (rb_equal(e, item)) {
3967 v = e;
3968 continue;
3970 if (i1 != i2) {
3971 rb_ary_store(ary, i2, e);
3973 i2++;
3975 if (RARRAY_LEN(ary) == i2) {
3976 if (rb_block_given_p()) {
3977 return rb_yield(item);
3979 return Qnil;
3982 ary_resize_smaller(ary, i2);
3984 ary_verify(ary);
3985 return v;
3988 void
3989 rb_ary_delete_same(VALUE ary, VALUE item)
3991 long i1, i2;
3993 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
3994 VALUE e = RARRAY_AREF(ary, i1);
3996 if (e == item) {
3997 continue;
3999 if (i1 != i2) {
4000 rb_ary_store(ary, i2, e);
4002 i2++;
4004 if (RARRAY_LEN(ary) == i2) {
4005 return;
4008 ary_resize_smaller(ary, i2);
4011 VALUE
4012 rb_ary_delete_at(VALUE ary, long pos)
4014 long len = RARRAY_LEN(ary);
4015 VALUE del;
4017 if (pos >= len) return Qnil;
4018 if (pos < 0) {
4019 pos += len;
4020 if (pos < 0) return Qnil;
4023 rb_ary_modify(ary);
4024 del = RARRAY_AREF(ary, pos);
4025 RARRAY_PTR_USE(ary, ptr, {
4026 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4028 ARY_INCREASE_LEN(ary, -1);
4029 ary_verify(ary);
4030 return del;
4034 * call-seq:
4035 * delete_at(index) -> removed_object or nil
4037 * Removes the element of +self+ at the given +index+, which must be an
4038 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4040 * When +index+ is non-negative, deletes the element at offset +index+:
4042 * a = [:foo, 'bar', 2]
4043 * a.delete_at(1) # => "bar"
4044 * a # => [:foo, 2]
4046 * When +index+ is negative, counts backward from the end of the array:
4048 * a = [:foo, 'bar', 2]
4049 * a.delete_at(-2) # => "bar"
4050 * a # => [:foo, 2]
4052 * When +index+ is out of range, returns +nil+.
4054 * a = [:foo, 'bar', 2]
4055 * a.delete_at(3) # => nil
4056 * a.delete_at(-4) # => nil
4058 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4061 static VALUE
4062 rb_ary_delete_at_m(VALUE ary, VALUE pos)
4064 return rb_ary_delete_at(ary, NUM2LONG(pos));
4067 static VALUE
4068 ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
4070 const long orig_len = RARRAY_LEN(ary);
4072 if (len < 0) {
4073 return Qnil;
4075 else if (pos < -orig_len) {
4076 return Qnil;
4078 else if (pos < 0) {
4079 pos += orig_len;
4081 else if (orig_len < pos) {
4082 return Qnil;
4084 if (orig_len < pos + len) {
4085 len = orig_len - pos;
4087 if (len == 0) {
4088 return rb_ary_new2(0);
4090 else {
4091 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4092 rb_ary_splice(ary, pos, len, 0, 0);
4093 return arg2;
4098 * call-seq:
4099 * slice!(index) -> object or nil
4100 * slice!(start, length) -> new_array or nil
4101 * slice!(range) -> new_array or nil
4103 * Removes and returns elements from +self+.
4105 * With numeric argument +index+ given,
4106 * removes and returns the element at offset +index+:
4108 * a = ['a', 'b', 'c', 'd']
4109 * a.slice!(2) # => "c"
4110 * a # => ["a", "b", "d"]
4111 * a.slice!(2.1) # => "d"
4112 * a # => ["a", "b"]
4114 * If +index+ is negative, counts backwards from the end of +self+:
4116 * a = ['a', 'b', 'c', 'd']
4117 * a.slice!(-2) # => "c"
4118 * a # => ["a", "b", "d"]
4120 * If +index+ is out of range, returns +nil+.
4122 * With numeric arguments +start+ and +length+ given,
4123 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4124 * returns the removed objects in a new array:
4126 * a = ['a', 'b', 'c', 'd']
4127 * a.slice!(1, 2) # => ["b", "c"]
4128 * a # => ["a", "d"]
4129 * a.slice!(0.1, 1.1) # => ["a"]
4130 * a # => ["d"]
4132 * If +start+ is negative, counts backwards from the end of +self+:
4134 * a = ['a', 'b', 'c', 'd']
4135 * a.slice!(-2, 1) # => ["c"]
4136 * a # => ["a", "b", "d"]
4138 * If +start+ is out-of-range, returns +nil+:
4140 * a = ['a', 'b', 'c', 'd']
4141 * a.slice!(5, 1) # => nil
4142 * a.slice!(-5, 1) # => nil
4144 * If <tt>start + length</tt> exceeds the array size,
4145 * removes and returns all elements from offset +start+ to the end:
4147 * a = ['a', 'b', 'c', 'd']
4148 * a.slice!(2, 50) # => ["c", "d"]
4149 * a # => ["a", "b"]
4151 * If <tt>start == a.size</tt> and +length+ is non-negative,
4152 * returns a new empty array.
4154 * If +length+ is negative, returns +nil+.
4156 * With Range argument +range+ given,
4157 * treats <tt>range.min</tt> as +start+ (as above)
4158 * and <tt>range.size</tt> as +length+ (as above):
4160 * a = ['a', 'b', 'c', 'd']
4161 * a.slice!(1..2) # => ["b", "c"]
4162 * a # => ["a", "d"]
4164 * If <tt>range.start == a.size</tt>, returns a new empty array:
4166 * a = ['a', 'b', 'c', 'd']
4167 * a.slice!(4..5) # => []
4169 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4171 * a = ['a', 'b', 'c', 'd']
4172 a.slice!(5..6) # => nil
4174 * If <tt>range.start</tt> is negative,
4175 * calculates the start index by counting backwards from the end of +self+:
4177 * a = ['a', 'b', 'c', 'd']
4178 * a.slice!(-2..2) # => ["c"]
4180 * If <tt>range.end</tt> is negative,
4181 * calculates the end index by counting backwards from the end of +self+:
4183 * a = ['a', 'b', 'c', 'd']
4184 * a.slice!(0..-2) # => ["a", "b", "c"]
4186 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4189 static VALUE
4190 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4192 VALUE arg1;
4193 long pos, len;
4195 rb_ary_modify_check(ary);
4196 rb_check_arity(argc, 1, 2);
4197 arg1 = argv[0];
4199 if (argc == 2) {
4200 pos = NUM2LONG(argv[0]);
4201 len = NUM2LONG(argv[1]);
4202 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4205 if (!FIXNUM_P(arg1)) {
4206 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4207 case Qtrue:
4208 /* valid range */
4209 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4210 case Qnil:
4211 /* invalid range */
4212 return Qnil;
4213 default:
4214 /* not a range */
4215 break;
4219 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4222 static VALUE
4223 ary_reject(VALUE orig, VALUE result)
4225 long i;
4227 for (i = 0; i < RARRAY_LEN(orig); i++) {
4228 VALUE v = RARRAY_AREF(orig, i);
4230 if (!RTEST(rb_yield(v))) {
4231 rb_ary_push(result, v);
4234 return result;
4237 static VALUE
4238 reject_bang_i(VALUE a)
4240 volatile struct select_bang_arg *arg = (void *)a;
4241 VALUE ary = arg->ary;
4242 long i1, i2;
4244 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4245 VALUE v = RARRAY_AREF(ary, i1);
4246 if (RTEST(rb_yield(v))) continue;
4247 if (i1 != i2) {
4248 rb_ary_store(ary, i2, v);
4250 arg->len[1] = ++i2;
4252 return (i1 == i2) ? Qnil : ary;
4255 static VALUE
4256 ary_reject_bang(VALUE ary)
4258 struct select_bang_arg args;
4259 rb_ary_modify_check(ary);
4260 args.ary = ary;
4261 args.len[0] = args.len[1] = 0;
4262 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4266 * call-seq:
4267 * reject! {|element| ... } -> self or nil
4268 * reject! -> new_enumerator
4270 * With a block given, calls the block with each element of +self+;
4271 * removes each element for which the block returns a truthy value.
4273 * Returns +self+ if any elements removed:
4275 * a = [:foo, 'bar', 2, 'bat']
4276 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4278 * Returns +nil+ if no elements removed.
4280 * With no block given, returns a new Enumerator.
4282 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4285 static VALUE
4286 rb_ary_reject_bang(VALUE ary)
4288 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4289 rb_ary_modify(ary);
4290 return ary_reject_bang(ary);
4294 * call-seq:
4295 * reject {|element| ... } -> new_array
4296 * reject -> new_enumerator
4298 * With a block given, returns a new array whose elements are all those from +self+
4299 * for which the block returns +false+ or +nil+:
4301 * a = [:foo, 'bar', 2, 'bat']
4302 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4303 * a1 # => [:foo, 2]
4305 * With no block given, returns a new Enumerator.
4307 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4310 static VALUE
4311 rb_ary_reject(VALUE ary)
4313 VALUE rejected_ary;
4315 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4316 rejected_ary = rb_ary_new();
4317 ary_reject(ary, rejected_ary);
4318 return rejected_ary;
4322 * call-seq:
4323 * delete_if {|element| ... } -> self
4324 * delete_if -> new_numerator
4326 * With a block given, calls the block with each element of +self+;
4327 * removes the element if the block returns a truthy value;
4328 * returns +self+:
4330 * a = [:foo, 'bar', 2, 'bat']
4331 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4333 * With no block given, returns a new Enumerator.
4335 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4338 static VALUE
4339 rb_ary_delete_if(VALUE ary)
4341 ary_verify(ary);
4342 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4343 ary_reject_bang(ary);
4344 return ary;
4347 static VALUE
4348 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4350 VALUE *args = (VALUE *)cbarg;
4351 if (argc > 1) val = rb_ary_new4(argc, argv);
4352 rb_ary_push(args[0], val);
4353 if (--args[1] == 0) rb_iter_break();
4354 return Qnil;
4357 static VALUE
4358 take_items(VALUE obj, long n)
4360 VALUE result = rb_check_array_type(obj);
4361 VALUE args[2];
4363 if (n == 0) return result;
4364 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4365 result = rb_ary_new2(n);
4366 args[0] = result; args[1] = (VALUE)n;
4367 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4368 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4369 rb_obj_class(obj));
4370 return result;
4375 * call-seq:
4376 * array.zip(*other_arrays) -> new_array
4377 * array.zip(*other_arrays) {|other_array| ... } -> nil
4379 * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
4380 * whose elements are Arrays.
4382 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4383 * and contains:
4385 * - The _nth_ element of +self+.
4386 * - The _nth_ element of each of the +other_arrays+.
4388 * If all +other_arrays+ and +self+ are the same size:
4390 * a = [:a0, :a1, :a2, :a3]
4391 * b = [:b0, :b1, :b2, :b3]
4392 * c = [:c0, :c1, :c2, :c3]
4393 * d = a.zip(b, c)
4394 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4396 * If any array in +other_arrays+ is smaller than +self+,
4397 * fills to <tt>self.size</tt> with +nil+:
4399 * a = [:a0, :a1, :a2, :a3]
4400 * b = [:b0, :b1, :b2]
4401 * c = [:c0, :c1]
4402 * d = a.zip(b, c)
4403 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4405 * If any array in +other_arrays+ is larger than +self+,
4406 * its trailing elements are ignored:
4408 * a = [:a0, :a1, :a2, :a3]
4409 * b = [:b0, :b1, :b2, :b3, :b4]
4410 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4411 * d = a.zip(b, c)
4412 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4414 * If an argument is not an array, it extracts the values by calling #each:
4416 * a = [:a0, :a1, :a2, :a2]
4417 * b = 1..4
4418 * c = a.zip(b)
4419 * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
4421 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
4423 * a = [:a0, :a1, :a2, :a3]
4424 * b = [:b0, :b1, :b2, :b3]
4425 * c = [:c0, :c1, :c2, :c3]
4426 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4428 * Output:
4430 * [:a0, :b0, :c0]
4431 * [:a1, :b1, :c1]
4432 * [:a2, :b2, :c2]
4433 * [:a3, :b3, :c3]
4437 static VALUE
4438 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4440 int i, j;
4441 long len = RARRAY_LEN(ary);
4442 VALUE result = Qnil;
4444 for (i=0; i<argc; i++) {
4445 argv[i] = take_items(argv[i], len);
4448 if (rb_block_given_p()) {
4449 int arity = rb_block_arity();
4451 if (arity > 1) {
4452 VALUE work, *tmp;
4454 tmp = ALLOCV_N(VALUE, work, argc+1);
4456 for (i=0; i<RARRAY_LEN(ary); i++) {
4457 tmp[0] = RARRAY_AREF(ary, i);
4458 for (j=0; j<argc; j++) {
4459 tmp[j+1] = rb_ary_elt(argv[j], i);
4461 rb_yield_values2(argc+1, tmp);
4464 if (work) ALLOCV_END(work);
4466 else {
4467 for (i=0; i<RARRAY_LEN(ary); i++) {
4468 VALUE tmp = rb_ary_new2(argc+1);
4470 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4471 for (j=0; j<argc; j++) {
4472 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4474 rb_yield(tmp);
4478 else {
4479 result = rb_ary_new_capa(len);
4481 for (i=0; i<len; i++) {
4482 VALUE tmp = rb_ary_new_capa(argc+1);
4484 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4485 for (j=0; j<argc; j++) {
4486 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4488 rb_ary_push(result, tmp);
4492 return result;
4496 * call-seq:
4497 * transpose -> new_array
4499 * Returns a new array that is +self+
4500 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4502 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4503 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4505 * The elements of +self+ must all be the same size.
4507 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4510 static VALUE
4511 rb_ary_transpose(VALUE ary)
4513 long elen = -1, alen, i, j;
4514 VALUE tmp, result = 0;
4516 alen = RARRAY_LEN(ary);
4517 if (alen == 0) return rb_ary_dup(ary);
4518 for (i=0; i<alen; i++) {
4519 tmp = to_ary(rb_ary_elt(ary, i));
4520 if (elen < 0) { /* first element */
4521 elen = RARRAY_LEN(tmp);
4522 result = rb_ary_new2(elen);
4523 for (j=0; j<elen; j++) {
4524 rb_ary_store(result, j, rb_ary_new2(alen));
4527 else if (elen != RARRAY_LEN(tmp)) {
4528 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4529 RARRAY_LEN(tmp), elen);
4531 for (j=0; j<elen; j++) {
4532 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4535 return result;
4539 * call-seq:
4540 * initialize_copy(other_array) -> self
4541 * replace(other_array) -> self
4543 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4544 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4545 * returns +self+:
4547 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4548 * a.replace(['d', 'e']) # => ["d", "e"]
4550 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4553 VALUE
4554 rb_ary_replace(VALUE copy, VALUE orig)
4556 rb_ary_modify_check(copy);
4557 orig = to_ary(orig);
4558 if (copy == orig) return copy;
4560 rb_ary_reset(copy);
4562 /* orig has enough space to embed the contents of orig. */
4563 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4564 RUBY_ASSERT(ARY_EMBED_P(copy));
4565 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4566 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4568 /* orig is embedded but copy does not have enough space to embed the
4569 * contents of orig. */
4570 else if (ARY_EMBED_P(orig)) {
4571 long len = ARY_EMBED_LEN(orig);
4572 VALUE *ptr = ary_heap_alloc_buffer(len);
4574 FL_UNSET_EMBED(copy);
4575 ARY_SET_PTR(copy, ptr);
4576 ARY_SET_LEN(copy, len);
4577 ARY_SET_CAPA(copy, len);
4579 // No allocation and exception expected that could leave `copy` in a
4580 // bad state from the edits above.
4581 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
4583 /* Otherwise, orig is on heap and copy does not have enough space to embed
4584 * the contents of orig. */
4585 else {
4586 VALUE shared_root = ary_make_shared(orig);
4587 FL_UNSET_EMBED(copy);
4588 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4589 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4590 rb_ary_set_shared(copy, shared_root);
4592 ary_verify(copy);
4593 return copy;
4597 * call-seq:
4598 * clear -> self
4600 * Removes all elements from +self+; returns +self+:
4602 * a = [:foo, 'bar', 2]
4603 * a.clear # => []
4605 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4608 VALUE
4609 rb_ary_clear(VALUE ary)
4611 rb_ary_modify_check(ary);
4612 if (ARY_SHARED_P(ary)) {
4613 rb_ary_unshare(ary);
4614 FL_SET_EMBED(ary);
4615 ARY_SET_EMBED_LEN(ary, 0);
4617 else {
4618 ARY_SET_LEN(ary, 0);
4619 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4620 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4623 ary_verify(ary);
4624 return ary;
4628 * call-seq:
4629 * fill(object, start = nil, count = nil) -> new_array
4630 * fill(object, range) -> new_array
4631 * fill(start = nil, count = nil) {|element| ... } -> new_array
4632 * fill(range) {|element| ... } -> new_array
4634 * Replaces selected elements in +self+;
4635 * may add elements to +self+;
4636 * always returns +self+ (never a new array).
4638 * In brief:
4640 * # Non-negative start.
4641 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4642 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4644 * # Extends with specified values if necessary.
4645 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4646 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4648 * # Fills with nils if necessary.
4649 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4650 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4652 * # For negative start, counts backwards from the end.
4653 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4654 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4656 * # Range.
4657 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4658 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4660 * When arguments +start+ and +count+ are given,
4661 * they select the elements of +self+ to be replaced;
4662 * each must be an
4663 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
4664 * (or +nil+):
4666 * - +start+ specifies the zero-based offset of the first element to be replaced;
4667 * +nil+ means zero.
4668 * - +count+ is the number of consecutive elements to be replaced;
4669 * +nil+ means "all the rest."
4671 * With argument +object+ given,
4672 * that one object is used for all replacements:
4674 * o = Object.new # => #<Object:0x0000014e7bff7600>
4675 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4676 * a.fill(o, 1, 2)
4677 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
4679 * With a block given, the block is called once for each element to be replaced;
4680 * the value passed to the block is the _index_ of the element to be replaced
4681 * (not the element itself);
4682 * the block's return value replaces the element:
4684 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4685 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
4687 * For arguments +start+ and +count+:
4689 * - If +start+ is non-negative,
4690 * replaces +count+ elements beginning at offset +start+:
4692 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
4693 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4694 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
4696 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4697 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4698 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
4700 * Extends +self+ if necessary:
4702 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4703 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
4705 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4706 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
4708 * Fills with +nil+ if necessary:
4710 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
4711 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4713 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
4714 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4716 * Does nothing if +count+ is non-positive:
4718 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
4719 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
4720 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
4722 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4723 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4724 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4726 * - If +start+ is negative, counts backwards from the end of +self+:
4728 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
4729 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4731 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
4732 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4734 * Extends +self+ if necessary:
4736 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
4737 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
4739 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
4740 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
4742 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
4744 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
4745 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
4747 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4748 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4750 * Does nothing if +count+ is non-positive:
4752 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
4753 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
4755 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4756 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4758 * When argument +range+ is given,
4759 * it must be a Range object whose members are numeric;
4760 * its +begin+ and +end+ values determine the elements of +self+
4761 * to be replaced:
4763 * - If both +begin+ and +end+ are positive, they specify the first and last elements
4764 * to be replaced:
4766 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4767 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4769 * If +end+ is smaller than +begin+, replaces no elements:
4771 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
4772 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
4774 * - If either is negative (or both are negative), counts backwards from the end of +self+:
4776 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
4777 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
4778 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
4780 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4781 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4782 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4784 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
4786 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
4787 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
4789 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4790 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4792 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
4793 * replaces elements to the end of +self+:
4795 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
4796 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
4798 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
4799 * replaces elements from the beginning of +self+:
4801 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
4802 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
4804 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4807 static VALUE
4808 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
4810 VALUE item = Qundef, arg1, arg2;
4811 long beg = 0, end = 0, len = 0;
4813 if (rb_block_given_p()) {
4814 rb_scan_args(argc, argv, "02", &arg1, &arg2);
4815 argc += 1; /* hackish */
4817 else {
4818 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
4820 switch (argc) {
4821 case 1:
4822 beg = 0;
4823 len = RARRAY_LEN(ary);
4824 break;
4825 case 2:
4826 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
4827 break;
4829 /* fall through */
4830 case 3:
4831 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
4832 if (beg < 0) {
4833 beg = RARRAY_LEN(ary) + beg;
4834 if (beg < 0) beg = 0;
4836 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
4837 break;
4839 rb_ary_modify(ary);
4840 if (len < 0) {
4841 return ary;
4843 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
4844 rb_raise(rb_eArgError, "argument too big");
4846 end = beg + len;
4847 if (RARRAY_LEN(ary) < end) {
4848 if (end >= ARY_CAPA(ary)) {
4849 ary_resize_capa(ary, end);
4851 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
4852 ARY_SET_LEN(ary, end);
4855 if (UNDEF_P(item)) {
4856 VALUE v;
4857 long i;
4859 for (i=beg; i<end; i++) {
4860 v = rb_yield(LONG2NUM(i));
4861 if (i>=RARRAY_LEN(ary)) break;
4862 ARY_SET(ary, i, v);
4865 else {
4866 ary_memfill(ary, beg, len, item);
4868 return ary;
4872 * call-seq:
4873 * self + other_array -> new_array
4875 * Returns a new array containing all elements of +self+
4876 * followed by all elements of +other_array+:
4878 * a = [0, 1] + [2, 3]
4879 * a # => [0, 1, 2, 3]
4881 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
4884 VALUE
4885 rb_ary_plus(VALUE x, VALUE y)
4887 VALUE z;
4888 long len, xlen, ylen;
4890 y = to_ary(y);
4891 xlen = RARRAY_LEN(x);
4892 ylen = RARRAY_LEN(y);
4893 len = xlen + ylen;
4894 z = rb_ary_new2(len);
4896 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
4897 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
4898 ARY_SET_LEN(z, len);
4899 return z;
4902 static VALUE
4903 ary_append(VALUE x, VALUE y)
4905 long n = RARRAY_LEN(y);
4906 if (n > 0) {
4907 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
4909 RB_GC_GUARD(y);
4910 return x;
4914 * call-seq:
4915 * concat(*other_arrays) -> self
4917 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
4919 * a = [0, 1]
4920 * a.concat(['two', 'three'], [:four, :five], a)
4921 * # => [0, 1, "two", "three", :four, :five, 0, 1]
4923 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4926 static VALUE
4927 rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
4929 rb_ary_modify_check(ary);
4931 if (argc == 1) {
4932 rb_ary_concat(ary, argv[0]);
4934 else if (argc > 1) {
4935 int i;
4936 VALUE args = rb_ary_hidden_new(argc);
4937 for (i = 0; i < argc; i++) {
4938 rb_ary_concat(args, argv[i]);
4940 ary_append(ary, args);
4943 ary_verify(ary);
4944 return ary;
4947 VALUE
4948 rb_ary_concat(VALUE x, VALUE y)
4950 return ary_append(x, to_ary(y));
4954 * call-seq:
4955 * self * n -> new_array
4956 * self * string_separator -> new_string
4958 * When non-negative integer argument +n+ is given,
4959 * returns a new array built by concatenating +n+ copies of +self+:
4961 * a = ['x', 'y']
4962 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
4964 * When string argument +string_separator+ is given,
4965 * equivalent to <tt>self.join(string_separator)</tt>:
4967 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
4971 static VALUE
4972 rb_ary_times(VALUE ary, VALUE times)
4974 VALUE ary2, tmp;
4975 const VALUE *ptr;
4976 long t, len;
4978 tmp = rb_check_string_type(times);
4979 if (!NIL_P(tmp)) {
4980 return rb_ary_join(ary, tmp);
4983 len = NUM2LONG(times);
4984 if (len == 0) {
4985 ary2 = ary_new(rb_cArray, 0);
4986 goto out;
4988 if (len < 0) {
4989 rb_raise(rb_eArgError, "negative argument");
4991 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
4992 rb_raise(rb_eArgError, "argument too big");
4994 len *= RARRAY_LEN(ary);
4996 ary2 = ary_new(rb_cArray, len);
4997 ARY_SET_LEN(ary2, len);
4999 ptr = RARRAY_CONST_PTR(ary);
5000 t = RARRAY_LEN(ary);
5001 if (0 < t) {
5002 ary_memcpy(ary2, 0, t, ptr);
5003 while (t <= len/2) {
5004 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5005 t *= 2;
5007 if (t < len) {
5008 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5011 out:
5012 return ary2;
5016 * call-seq:
5017 * assoc(object) -> found_array or nil
5019 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5020 * and <tt>ele[0] == object</tt>:
5022 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5023 * a.assoc(4) # => [4, 5, 6]
5025 * Returns +nil+ if no such element is found.
5027 * Related: Array#rassoc;
5028 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5031 VALUE
5032 rb_ary_assoc(VALUE ary, VALUE key)
5034 long i;
5035 VALUE v;
5037 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5038 v = rb_check_array_type(RARRAY_AREF(ary, i));
5039 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5040 rb_equal(RARRAY_AREF(v, 0), key))
5041 return v;
5043 return Qnil;
5047 * call-seq:
5048 * rassoc(object) -> found_array or nil
5050 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5051 * and <tt>ele[1] == object</tt>:
5053 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5054 * a.rassoc(4) # => [2, 4]
5055 * a.rassoc(5) # => [4, 5, 6]
5057 * Returns +nil+ if no such element is found.
5059 * Related: Array#assoc;
5060 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5063 VALUE
5064 rb_ary_rassoc(VALUE ary, VALUE value)
5066 long i;
5067 VALUE v;
5069 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5070 v = rb_check_array_type(RARRAY_AREF(ary, i));
5071 if (RB_TYPE_P(v, T_ARRAY) &&
5072 RARRAY_LEN(v) > 1 &&
5073 rb_equal(RARRAY_AREF(v, 1), value))
5074 return v;
5076 return Qnil;
5079 static VALUE
5080 recursive_equal(VALUE ary1, VALUE ary2, int recur)
5082 long i, len1;
5083 const VALUE *p1, *p2;
5085 if (recur) return Qtrue; /* Subtle! */
5087 /* rb_equal() can evacuate ptrs */
5088 p1 = RARRAY_CONST_PTR(ary1);
5089 p2 = RARRAY_CONST_PTR(ary2);
5090 len1 = RARRAY_LEN(ary1);
5092 for (i = 0; i < len1; i++) {
5093 if (*p1 != *p2) {
5094 if (rb_equal(*p1, *p2)) {
5095 len1 = RARRAY_LEN(ary1);
5096 if (len1 != RARRAY_LEN(ary2))
5097 return Qfalse;
5098 if (len1 < i)
5099 return Qtrue;
5100 p1 = RARRAY_CONST_PTR(ary1) + i;
5101 p2 = RARRAY_CONST_PTR(ary2) + i;
5103 else {
5104 return Qfalse;
5107 p1++;
5108 p2++;
5110 return Qtrue;
5114 * call-seq:
5115 * self == other_array -> true or false
5117 * Returns whether both:
5119 * - +self+ and +other_array+ are the same size.
5120 * - Their corresponding elements are the same;
5121 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5122 * <tt>self[i] == other_array[i]</tt>.
5124 * Examples:
5126 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5127 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5128 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5129 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5131 * This method is different from method Array#eql?,
5132 * which compares elements using <tt>Object#eql?</tt>.
5134 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5137 static VALUE
5138 rb_ary_equal(VALUE ary1, VALUE ary2)
5140 if (ary1 == ary2) return Qtrue;
5141 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5142 if (!rb_respond_to(ary2, idTo_ary)) {
5143 return Qfalse;
5145 return rb_equal(ary2, ary1);
5147 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5148 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5149 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5152 static VALUE
5153 recursive_eql(VALUE ary1, VALUE ary2, int recur)
5155 long i;
5157 if (recur) return Qtrue; /* Subtle! */
5158 for (i=0; i<RARRAY_LEN(ary1); i++) {
5159 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5160 return Qfalse;
5162 return Qtrue;
5166 * call-seq:
5167 * eql?(other_array) -> true or false
5169 * Returns +true+ if +self+ and +other_array+ are the same size,
5170 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5172 * a0 = [:foo, 'bar', 2]
5173 * a1 = [:foo, 'bar', 2]
5174 * a1.eql?(a0) # => true
5176 * Otherwise, returns +false+.
5178 * This method is different from method Array#==,
5179 * which compares using method <tt>Object#==</tt>.
5181 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5184 static VALUE
5185 rb_ary_eql(VALUE ary1, VALUE ary2)
5187 if (ary1 == ary2) return Qtrue;
5188 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5189 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5190 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5191 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5194 VALUE
5195 rb_ary_hash_values(long len, const VALUE *elements)
5197 long i;
5198 st_index_t h;
5199 VALUE n;
5201 h = rb_hash_start(len);
5202 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5203 for (i=0; i<len; i++) {
5204 n = rb_hash(elements[i]);
5205 h = rb_hash_uint(h, NUM2LONG(n));
5207 h = rb_hash_end(h);
5208 return ST2FIX(h);
5212 * call-seq:
5213 * hash -> integer
5215 * Returns the integer hash value for +self+.
5217 * Two arrays with the same content will have the same hash value
5218 * (and will compare using eql?):
5220 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5221 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5222 * ['a', 'b'].hash == ['a'].hash # => false
5226 static VALUE
5227 rb_ary_hash(VALUE ary)
5229 return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
5233 * call-seq:
5234 * include?(object) -> true or false
5236 * Returns whether for some element +element+ in +self+,
5237 * <tt>object == element</tt>:
5239 * [0, 1, 2].include?(2) # => true
5240 * [0, 1, 2].include?(2.0) # => true
5241 * [0, 1, 2].include?(2.1) # => false
5243 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5246 VALUE
5247 rb_ary_includes(VALUE ary, VALUE item)
5249 long i;
5250 VALUE e;
5252 for (i=0; i<RARRAY_LEN(ary); i++) {
5253 e = RARRAY_AREF(ary, i);
5254 if (rb_equal(e, item)) {
5255 return Qtrue;
5258 return Qfalse;
5261 static VALUE
5262 rb_ary_includes_by_eql(VALUE ary, VALUE item)
5264 long i;
5265 VALUE e;
5267 for (i=0; i<RARRAY_LEN(ary); i++) {
5268 e = RARRAY_AREF(ary, i);
5269 if (rb_eql(item, e)) {
5270 return Qtrue;
5273 return Qfalse;
5276 static VALUE
5277 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5279 long i, len;
5281 if (recur) return Qundef; /* Subtle! */
5282 len = RARRAY_LEN(ary1);
5283 if (len > RARRAY_LEN(ary2)) {
5284 len = RARRAY_LEN(ary2);
5286 for (i=0; i<len; i++) {
5287 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5288 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5289 if (v != INT2FIX(0)) {
5290 return v;
5293 return Qundef;
5297 * call-seq:
5298 * self <=> other_array -> -1, 0, or 1
5300 * Returns -1, 0, or 1 as +self+ is determined
5301 * to be less than, equal to, or greater than +other_array+.
5303 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5305 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5306 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5308 * [0, 1, 2] <=> [0, 0, 2] # => 1
5310 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5312 * [0, 1, 2] <=> [0, 2, 2] # => -1
5314 * - Continues if <tt>result[i]</tt> is 0.
5316 * When every +result+ is 0,
5317 * returns <tt>self.size <=> other_array.size</tt>
5318 * (see Integer#<=>):
5320 * [0, 1, 2] <=> [0, 1] # => 1
5321 * [0, 1, 2] <=> [0, 1, 2] # => 0
5322 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5324 * Note that when +other_array+ is larger than +self+,
5325 * its trailing elements do not affect the result:
5327 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5328 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5329 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5331 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5334 VALUE
5335 rb_ary_cmp(VALUE ary1, VALUE ary2)
5337 long len;
5338 VALUE v;
5340 ary2 = rb_check_array_type(ary2);
5341 if (NIL_P(ary2)) return Qnil;
5342 if (ary1 == ary2) return INT2FIX(0);
5343 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5344 if (!UNDEF_P(v)) return v;
5345 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5346 if (len == 0) return INT2FIX(0);
5347 if (len > 0) return INT2FIX(1);
5348 return INT2FIX(-1);
5351 static VALUE
5352 ary_add_hash(VALUE hash, VALUE ary)
5354 long i;
5356 for (i=0; i<RARRAY_LEN(ary); i++) {
5357 VALUE elt = RARRAY_AREF(ary, i);
5358 rb_hash_add_new_element(hash, elt, elt);
5360 return hash;
5363 static inline VALUE
5364 ary_tmp_hash_new(VALUE ary)
5366 long size = RARRAY_LEN(ary);
5367 VALUE hash = rb_hash_new_with_size(size);
5369 RBASIC_CLEAR_CLASS(hash);
5370 return hash;
5373 static VALUE
5374 ary_make_hash(VALUE ary)
5376 VALUE hash = ary_tmp_hash_new(ary);
5377 return ary_add_hash(hash, ary);
5380 static VALUE
5381 ary_add_hash_by(VALUE hash, VALUE ary)
5383 long i;
5385 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5386 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5387 rb_hash_add_new_element(hash, k, v);
5389 return hash;
5392 static VALUE
5393 ary_make_hash_by(VALUE ary)
5395 VALUE hash = ary_tmp_hash_new(ary);
5396 return ary_add_hash_by(hash, ary);
5400 * call-seq:
5401 * self - other_array -> new_array
5403 * Returns a new array containing only those elements of +self+
5404 * that are not found in +other_array+;
5405 * the order from +self+ is preserved:
5407 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5408 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5409 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5411 * Element are compared using method <tt>#eql?</tt>
5412 * (as defined in each element of +self+).
5414 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5417 VALUE
5418 rb_ary_diff(VALUE ary1, VALUE ary2)
5420 VALUE ary3;
5421 VALUE hash;
5422 long i;
5424 ary2 = to_ary(ary2);
5425 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5426 ary3 = rb_ary_new();
5428 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5429 for (i=0; i<RARRAY_LEN(ary1); i++) {
5430 VALUE elt = rb_ary_elt(ary1, i);
5431 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5432 rb_ary_push(ary3, elt);
5434 return ary3;
5437 hash = ary_make_hash(ary2);
5438 for (i=0; i<RARRAY_LEN(ary1); i++) {
5439 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5440 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5443 return ary3;
5447 * call-seq:
5448 * difference(*other_arrays = []) -> new_array
5450 * Returns a new array containing only those elements from +self+
5451 * that are not found in any of the given +other_arrays+;
5452 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5454 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5455 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5456 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5457 * [0, 1, 2].difference # => [0, 1, 2]
5459 * Returns a copy of +self+ if no arguments are given.
5461 * Related: Array#-;
5462 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5465 static VALUE
5466 rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5468 VALUE ary_diff;
5469 long i, length;
5470 volatile VALUE t0;
5471 bool *is_hash = ALLOCV_N(bool, t0, argc);
5472 ary_diff = rb_ary_new();
5473 length = RARRAY_LEN(ary);
5475 for (i = 0; i < argc; i++) {
5476 argv[i] = to_ary(argv[i]);
5477 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5478 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5481 for (i = 0; i < RARRAY_LEN(ary); i++) {
5482 int j;
5483 VALUE elt = rb_ary_elt(ary, i);
5484 for (j = 0; j < argc; j++) {
5485 if (is_hash[j]) {
5486 if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
5487 break;
5489 else {
5490 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5493 if (j == argc) rb_ary_push(ary_diff, elt);
5496 ALLOCV_END(t0);
5498 return ary_diff;
5503 * call-seq:
5504 * self & other_array -> new_array
5506 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5507 * that is, containing those elements found in both +self+ and +other_array+:
5509 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5511 * Omits duplicates:
5513 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5515 * Preserves order from +self+:
5517 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5519 * Identifies common elements using method <tt>#eql?</tt>
5520 * (as defined in each element of +self+).
5522 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5526 static VALUE
5527 rb_ary_and(VALUE ary1, VALUE ary2)
5529 VALUE hash, ary3, v;
5530 st_data_t vv;
5531 long i;
5533 ary2 = to_ary(ary2);
5534 ary3 = rb_ary_new();
5535 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5537 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5538 for (i=0; i<RARRAY_LEN(ary1); i++) {
5539 v = RARRAY_AREF(ary1, i);
5540 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5541 if (rb_ary_includes_by_eql(ary3, v)) continue;
5542 rb_ary_push(ary3, v);
5544 return ary3;
5547 hash = ary_make_hash(ary2);
5549 for (i=0; i<RARRAY_LEN(ary1); i++) {
5550 v = RARRAY_AREF(ary1, i);
5551 vv = (st_data_t)v;
5552 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5553 rb_ary_push(ary3, v);
5557 return ary3;
5561 * call-seq:
5562 * intersection(*other_arrays) -> new_array
5564 * Returns a new array containing each element in +self+ that is +#eql?+
5565 * to at least one element in each of the given +other_arrays+;
5566 * duplicates are omitted:
5568 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5570 * Each element must correctly implement method <tt>#hash</tt>.
5572 * Order from +self+ is preserved:
5574 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5576 * Returns a copy of +self+ if no arguments are given.
5578 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5581 static VALUE
5582 rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5584 VALUE result = rb_ary_dup(ary);
5585 int i;
5587 for (i = 0; i < argc; i++) {
5588 result = rb_ary_and(result, argv[i]);
5591 return result;
5594 static int
5595 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5597 if (existing) return ST_STOP;
5598 *key = *value = (VALUE)arg;
5599 return ST_CONTINUE;
5602 static void
5603 rb_ary_union(VALUE ary_union, VALUE ary)
5605 long i;
5606 for (i = 0; i < RARRAY_LEN(ary); i++) {
5607 VALUE elt = rb_ary_elt(ary, i);
5608 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5609 rb_ary_push(ary_union, elt);
5613 static void
5614 rb_ary_union_hash(VALUE hash, VALUE ary2)
5616 long i;
5617 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5618 VALUE elt = RARRAY_AREF(ary2, i);
5619 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5620 RB_OBJ_WRITTEN(hash, Qundef, elt);
5626 * call-seq:
5627 * array | other_array -> new_array
5629 * Returns the union of +array+ and +Array+ +other_array+;
5630 * duplicates are removed; order is preserved;
5631 * items are compared using <tt>eql?</tt>:
5633 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5634 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5635 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5637 * Related: Array#union.
5640 static VALUE
5641 rb_ary_or(VALUE ary1, VALUE ary2)
5643 VALUE hash;
5645 ary2 = to_ary(ary2);
5646 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5647 VALUE ary3 = rb_ary_new();
5648 rb_ary_union(ary3, ary1);
5649 rb_ary_union(ary3, ary2);
5650 return ary3;
5653 hash = ary_make_hash(ary1);
5654 rb_ary_union_hash(hash, ary2);
5656 return rb_hash_values(hash);
5660 * call-seq:
5661 * union(*other_arrays) -> new_array
5663 * Returns a new array that is the union of the elements of +self+
5664 * and all given arrays +other_arrays+;
5665 * items are compared using <tt>eql?</tt>:
5667 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5669 * Removes duplicates (preserving the first found):
5671 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5673 * Preserves order (preserving the position of the first found):
5675 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
5677 * With no arguments given, returns a copy of +self+.
5679 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5682 static VALUE
5683 rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
5685 int i;
5686 long sum;
5687 VALUE hash;
5689 sum = RARRAY_LEN(ary);
5690 for (i = 0; i < argc; i++) {
5691 argv[i] = to_ary(argv[i]);
5692 sum += RARRAY_LEN(argv[i]);
5695 if (sum <= SMALL_ARRAY_LEN) {
5696 VALUE ary_union = rb_ary_new();
5698 rb_ary_union(ary_union, ary);
5699 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5701 return ary_union;
5704 hash = ary_make_hash(ary);
5705 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5707 return rb_hash_values(hash);
5711 * call-seq:
5712 * intersect?(other_array) -> true or false
5714 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5716 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5717 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5719 * Each element must correctly implement method <tt>#hash</tt>.
5721 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5724 static VALUE
5725 rb_ary_intersect_p(VALUE ary1, VALUE ary2)
5727 VALUE hash, v, result, shorter, longer;
5728 st_data_t vv;
5729 long i;
5731 ary2 = to_ary(ary2);
5732 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
5734 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5735 for (i=0; i<RARRAY_LEN(ary1); i++) {
5736 v = RARRAY_AREF(ary1, i);
5737 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
5739 return Qfalse;
5742 shorter = ary1;
5743 longer = ary2;
5744 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
5745 longer = ary1;
5746 shorter = ary2;
5749 hash = ary_make_hash(shorter);
5750 result = Qfalse;
5752 for (i=0; i<RARRAY_LEN(longer); i++) {
5753 v = RARRAY_AREF(longer, i);
5754 vv = (st_data_t)v;
5755 if (rb_hash_stlike_lookup(hash, vv, 0)) {
5756 result = Qtrue;
5757 break;
5761 return result;
5764 static VALUE
5765 ary_max_generic(VALUE ary, long i, VALUE vmax)
5767 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5769 VALUE v;
5770 for (; i < RARRAY_LEN(ary); ++i) {
5771 v = RARRAY_AREF(ary, i);
5773 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
5774 vmax = v;
5778 return vmax;
5781 static VALUE
5782 ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
5784 const long n = RARRAY_LEN(ary);
5785 RUBY_ASSERT(i > 0 && i < n);
5786 RUBY_ASSERT(FIXNUM_P(vmax));
5788 VALUE v;
5789 for (; i < n; ++i) {
5790 v = RARRAY_AREF(ary, i);
5792 if (FIXNUM_P(v)) {
5793 if ((long)vmax < (long)v) {
5794 vmax = v;
5797 else {
5798 return ary_max_generic(ary, i, vmax);
5802 return vmax;
5805 static VALUE
5806 ary_max_opt_float(VALUE ary, long i, VALUE vmax)
5808 const long n = RARRAY_LEN(ary);
5809 RUBY_ASSERT(i > 0 && i < n);
5810 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax));
5812 VALUE v;
5813 for (; i < n; ++i) {
5814 v = RARRAY_AREF(ary, i);
5816 if (RB_FLOAT_TYPE_P(v)) {
5817 if (rb_float_cmp(vmax, v) < 0) {
5818 vmax = v;
5821 else {
5822 return ary_max_generic(ary, i, vmax);
5826 return vmax;
5829 static VALUE
5830 ary_max_opt_string(VALUE ary, long i, VALUE vmax)
5832 const long n = RARRAY_LEN(ary);
5833 RUBY_ASSERT(i > 0 && i < n);
5834 RUBY_ASSERT(STRING_P(vmax));
5836 VALUE v;
5837 for (; i < n; ++i) {
5838 v = RARRAY_AREF(ary, i);
5840 if (STRING_P(v)) {
5841 if (rb_str_cmp(vmax, v) < 0) {
5842 vmax = v;
5845 else {
5846 return ary_max_generic(ary, i, vmax);
5850 return vmax;
5854 * call-seq:
5855 * max -> element
5856 * max(n) -> new_array
5857 * max {|a, b| ... } -> element
5858 * max(n) {|a, b| ... } -> new_array
5860 * Returns one of the following:
5862 * - The maximum-valued element from +self+.
5863 * - A new array of maximum-valued elements from +self+.
5865 * Does not modify +self+.
5867 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
5868 * with a numeric.
5870 * With no argument and no block, returns the element in +self+
5871 * having the maximum value per method <tt>#<=></tt>:
5873 * [1, 0, 3, 2].max # => 3
5875 * With non-negative numeric argument +n+ and no block,
5876 * returns a new array with at most +n+ elements,
5877 * in descending order, per method <tt>#<=></tt>:
5879 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
5880 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
5881 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
5882 * [1, 0, 3, 2].max(0) # => []
5884 * With a block given, the block must return a numeric.
5886 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
5887 * returns the element having the maximum value per the block:
5889 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
5890 * # => "000"
5892 * With non-negative numeric argument +n+ and a block,
5893 * returns a new array with at most +n+ elements,
5894 * in descending order, per the block:
5896 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
5897 * # => ["000", "00"]
5899 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5901 static VALUE
5902 rb_ary_max(int argc, VALUE *argv, VALUE ary)
5904 VALUE result = Qundef, v;
5905 VALUE num;
5906 long i;
5908 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
5909 return rb_nmin_run(ary, num, 0, 1, 1);
5911 const long n = RARRAY_LEN(ary);
5912 if (rb_block_given_p()) {
5913 for (i = 0; i < RARRAY_LEN(ary); i++) {
5914 v = RARRAY_AREF(ary, i);
5915 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
5916 result = v;
5920 else if (n > 0) {
5921 result = RARRAY_AREF(ary, 0);
5922 if (n > 1) {
5923 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
5924 return ary_max_opt_fixnum(ary, 1, result);
5926 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
5927 return ary_max_opt_string(ary, 1, result);
5929 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
5930 return ary_max_opt_float(ary, 1, result);
5932 else {
5933 return ary_max_generic(ary, 1, result);
5937 if (UNDEF_P(result)) return Qnil;
5938 return result;
5941 static VALUE
5942 ary_min_generic(VALUE ary, long i, VALUE vmin)
5944 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5946 VALUE v;
5947 for (; i < RARRAY_LEN(ary); ++i) {
5948 v = RARRAY_AREF(ary, i);
5950 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
5951 vmin = v;
5955 return vmin;
5958 static VALUE
5959 ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
5961 const long n = RARRAY_LEN(ary);
5962 RUBY_ASSERT(i > 0 && i < n);
5963 RUBY_ASSERT(FIXNUM_P(vmin));
5965 VALUE a;
5966 for (; i < n; ++i) {
5967 a = RARRAY_AREF(ary, i);
5969 if (FIXNUM_P(a)) {
5970 if ((long)vmin > (long)a) {
5971 vmin = a;
5974 else {
5975 return ary_min_generic(ary, i, vmin);
5979 return vmin;
5982 static VALUE
5983 ary_min_opt_float(VALUE ary, long i, VALUE vmin)
5985 const long n = RARRAY_LEN(ary);
5986 RUBY_ASSERT(i > 0 && i < n);
5987 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin));
5989 VALUE a;
5990 for (; i < n; ++i) {
5991 a = RARRAY_AREF(ary, i);
5993 if (RB_FLOAT_TYPE_P(a)) {
5994 if (rb_float_cmp(vmin, a) > 0) {
5995 vmin = a;
5998 else {
5999 return ary_min_generic(ary, i, vmin);
6003 return vmin;
6006 static VALUE
6007 ary_min_opt_string(VALUE ary, long i, VALUE vmin)
6009 const long n = RARRAY_LEN(ary);
6010 RUBY_ASSERT(i > 0 && i < n);
6011 RUBY_ASSERT(STRING_P(vmin));
6013 VALUE a;
6014 for (; i < n; ++i) {
6015 a = RARRAY_AREF(ary, i);
6017 if (STRING_P(a)) {
6018 if (rb_str_cmp(vmin, a) > 0) {
6019 vmin = a;
6022 else {
6023 return ary_min_generic(ary, i, vmin);
6027 return vmin;
6031 * call-seq:
6032 * min -> element
6033 * min(n) -> new_array
6034 * min {|a, b| ... } -> element
6035 * min(n) {|a, b| ... } -> new_array
6037 * Returns one of the following:
6039 * - The minimum-valued element from +self+.
6040 * - A new array of minimum-valued elements from +self+.
6042 * Does not modify +self+.
6044 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6045 * with a numeric.
6047 * With no argument and no block, returns the element in +self+
6048 * having the minimum value per method <tt>#<=></tt>:
6050 * [1, 0, 3, 2].min # => 0
6052 * With non-negative numeric argument +n+ and no block,
6053 * returns a new array with at most +n+ elements,
6054 * in ascending order, per method <tt>#<=></tt>:
6056 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6057 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6058 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6059 * [1, 0, 3, 2].min(0) # => []
6061 * With a block given, the block must return a numeric.
6063 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6064 * returns the element having the minimum value per the block:
6066 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6067 * # => ""
6069 * With non-negative numeric argument +n+ and a block,
6070 * returns a new array with at most +n+ elements,
6071 * in ascending order, per the block:
6073 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6074 * # => ["", "0"]
6076 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6078 static VALUE
6079 rb_ary_min(int argc, VALUE *argv, VALUE ary)
6081 VALUE result = Qundef, v;
6082 VALUE num;
6083 long i;
6085 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6086 return rb_nmin_run(ary, num, 0, 0, 1);
6088 const long n = RARRAY_LEN(ary);
6089 if (rb_block_given_p()) {
6090 for (i = 0; i < RARRAY_LEN(ary); i++) {
6091 v = RARRAY_AREF(ary, i);
6092 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6093 result = v;
6097 else if (n > 0) {
6098 result = RARRAY_AREF(ary, 0);
6099 if (n > 1) {
6100 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6101 return ary_min_opt_fixnum(ary, 1, result);
6103 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6104 return ary_min_opt_string(ary, 1, result);
6106 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6107 return ary_min_opt_float(ary, 1, result);
6109 else {
6110 return ary_min_generic(ary, 1, result);
6114 if (UNDEF_P(result)) return Qnil;
6115 return result;
6119 * call-seq:
6120 * minmax -> array
6121 * minmax {|a, b| ... } -> array
6123 * Returns a 2-element array containing the minimum-valued and maximum-valued
6124 * elements from +self+;
6125 * does not modify +self+.
6127 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6129 * [1, 0, 3, 2].minmax # => [0, 3]
6131 * With a block given, the block must return a numeric;
6132 * the block is called <tt>self.size - 1</tt> times to compare elements;
6133 * returns the elements having the minimum and maximum values per the block:
6135 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6136 * # => ["", "000"]
6138 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6140 static VALUE
6141 rb_ary_minmax(VALUE ary)
6143 if (rb_block_given_p()) {
6144 return rb_call_super(0, NULL);
6146 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6149 static int
6150 push_value(st_data_t key, st_data_t val, st_data_t ary)
6152 rb_ary_push((VALUE)ary, (VALUE)val);
6153 return ST_CONTINUE;
6157 * call-seq:
6158 * array.uniq! -> self or nil
6159 * array.uniq! {|element| ... } -> self or nil
6161 * Removes duplicate elements from +self+, the first occurrence always being retained;
6162 * returns +self+ if any elements removed, +nil+ otherwise.
6164 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6165 * to compare.
6167 * Returns +self+ if any elements removed:
6169 * a = [0, 0, 1, 1, 2, 2]
6170 * a.uniq! # => [0, 1, 2]
6172 * Returns +nil+ if no elements removed.
6174 * With a block given, calls the block for each element;
6175 * identifies (using method <tt>eql?</tt>) and removes
6176 * elements for which the block returns duplicate values.
6178 * Returns +self+ if any elements removed:
6180 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6181 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
6183 * Returns +nil+ if no elements removed.
6185 static VALUE
6186 rb_ary_uniq_bang(VALUE ary)
6188 VALUE hash;
6189 long hash_size;
6191 rb_ary_modify_check(ary);
6192 if (RARRAY_LEN(ary) <= 1)
6193 return Qnil;
6194 if (rb_block_given_p())
6195 hash = ary_make_hash_by(ary);
6196 else
6197 hash = ary_make_hash(ary);
6199 hash_size = RHASH_SIZE(hash);
6200 if (RARRAY_LEN(ary) == hash_size) {
6201 return Qnil;
6203 rb_ary_modify_check(ary);
6204 ARY_SET_LEN(ary, 0);
6205 if (ARY_SHARED_P(ary)) {
6206 rb_ary_unshare(ary);
6207 FL_SET_EMBED(ary);
6209 ary_resize_capa(ary, hash_size);
6210 rb_hash_foreach(hash, push_value, ary);
6212 return ary;
6216 * call-seq:
6217 * array.uniq -> new_array
6218 * array.uniq {|element| ... } -> new_array
6220 * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
6221 * the first occurrence always being retained.
6223 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
6224 * to compare:
6226 * a = [0, 0, 1, 1, 2, 2]
6227 * a.uniq # => [0, 1, 2]
6229 * With a block given, calls the block for each element;
6230 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
6231 * that is, those elements for which the block returns the same value:
6233 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6234 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6238 static VALUE
6239 rb_ary_uniq(VALUE ary)
6241 VALUE hash, uniq;
6243 if (RARRAY_LEN(ary) <= 1) {
6244 hash = 0;
6245 uniq = rb_ary_dup(ary);
6247 else if (rb_block_given_p()) {
6248 hash = ary_make_hash_by(ary);
6249 uniq = rb_hash_values(hash);
6251 else {
6252 hash = ary_make_hash(ary);
6253 uniq = rb_hash_values(hash);
6256 return uniq;
6260 * call-seq:
6261 * compact! -> self or nil
6263 * Removes all +nil+ elements from +self+;
6264 * Returns +self+ if any elements are removed, +nil+ otherwise:
6266 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6267 * a.compact! # => [0, false, "", [], {}]
6268 * a # => [0, false, "", [], {}]
6269 * a.compact! # => nil
6271 * Related: Array#compact;
6272 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6275 static VALUE
6276 rb_ary_compact_bang(VALUE ary)
6278 VALUE *p, *t, *end;
6279 long n;
6281 rb_ary_modify(ary);
6282 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6283 end = p + RARRAY_LEN(ary);
6285 while (t < end) {
6286 if (NIL_P(*t)) t++;
6287 else *p++ = *t++;
6289 n = p - RARRAY_CONST_PTR(ary);
6290 if (RARRAY_LEN(ary) == n) {
6291 return Qnil;
6293 ary_resize_smaller(ary, n);
6295 return ary;
6299 * call-seq:
6300 * compact -> new_array
6302 * Returns a new array containing only the non-+nil+ elements from +self+;
6303 * element order is preserved:
6305 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6306 * a.compact # => [0, false, "", [], {}]
6308 * Related: Array#compact!;
6309 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6312 static VALUE
6313 rb_ary_compact(VALUE ary)
6315 ary = rb_ary_dup(ary);
6316 rb_ary_compact_bang(ary);
6317 return ary;
6321 * call-seq:
6322 * count -> integer
6323 * count(object) -> integer
6324 * count {|element| ... } -> integer
6326 * Returns a count of specified elements.
6328 * With no argument and no block, returns the count of all elements:
6330 * [0, :one, 'two', 3, 3.0].count # => 5
6332 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6334 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6336 * With no argument and a block given, calls the block with each element;
6337 * returns the count of elements for which the block returns a truthy value:
6339 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6341 * With argument +object+ and a block given, issues a warning, ignores the block,
6342 * and returns the count of elements <tt>==</tt> to +object+.
6344 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6347 static VALUE
6348 rb_ary_count(int argc, VALUE *argv, VALUE ary)
6350 long i, n = 0;
6352 if (rb_check_arity(argc, 0, 1) == 0) {
6353 VALUE v;
6355 if (!rb_block_given_p())
6356 return LONG2NUM(RARRAY_LEN(ary));
6358 for (i = 0; i < RARRAY_LEN(ary); i++) {
6359 v = RARRAY_AREF(ary, i);
6360 if (RTEST(rb_yield(v))) n++;
6363 else {
6364 VALUE obj = argv[0];
6366 if (rb_block_given_p()) {
6367 rb_warn("given block not used");
6369 for (i = 0; i < RARRAY_LEN(ary); i++) {
6370 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6374 return LONG2NUM(n);
6377 static VALUE
6378 flatten(VALUE ary, int level)
6380 long i;
6381 VALUE stack, result, tmp = 0, elt;
6382 VALUE memo = Qfalse;
6384 for (i = 0; i < RARRAY_LEN(ary); i++) {
6385 elt = RARRAY_AREF(ary, i);
6386 tmp = rb_check_array_type(elt);
6387 if (!NIL_P(tmp)) {
6388 break;
6391 if (i == RARRAY_LEN(ary)) {
6392 return ary;
6395 result = ary_new(0, RARRAY_LEN(ary));
6396 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6397 ARY_SET_LEN(result, i);
6399 stack = ary_new(0, ARY_DEFAULT_SIZE);
6400 rb_ary_push(stack, ary);
6401 rb_ary_push(stack, LONG2NUM(i + 1));
6403 if (level < 0) {
6404 memo = rb_obj_hide(rb_ident_hash_new());
6405 rb_hash_aset(memo, ary, Qtrue);
6406 rb_hash_aset(memo, tmp, Qtrue);
6409 ary = tmp;
6410 i = 0;
6412 while (1) {
6413 while (i < RARRAY_LEN(ary)) {
6414 elt = RARRAY_AREF(ary, i++);
6415 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6416 rb_ary_push(result, elt);
6417 continue;
6419 tmp = rb_check_array_type(elt);
6420 if (RBASIC(result)->klass) {
6421 if (RTEST(memo)) {
6422 rb_hash_clear(memo);
6424 rb_raise(rb_eRuntimeError, "flatten reentered");
6426 if (NIL_P(tmp)) {
6427 rb_ary_push(result, elt);
6429 else {
6430 if (memo) {
6431 if (rb_hash_aref(memo, tmp) == Qtrue) {
6432 rb_hash_clear(memo);
6433 rb_raise(rb_eArgError, "tried to flatten recursive array");
6435 rb_hash_aset(memo, tmp, Qtrue);
6437 rb_ary_push(stack, ary);
6438 rb_ary_push(stack, LONG2NUM(i));
6439 ary = tmp;
6440 i = 0;
6443 if (RARRAY_LEN(stack) == 0) {
6444 break;
6446 if (memo) {
6447 rb_hash_delete(memo, ary);
6449 tmp = rb_ary_pop(stack);
6450 i = NUM2LONG(tmp);
6451 ary = rb_ary_pop(stack);
6454 if (memo) {
6455 rb_hash_clear(memo);
6458 RBASIC_SET_CLASS(result, rb_cArray);
6459 return result;
6463 * call-seq:
6464 * flatten!(depth = nil) -> self or nil
6466 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6467 * +depth+ must be an
6468 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6469 * or +nil+.
6470 * At each level of recursion:
6472 * - Each element that is an array is "flattened"
6473 * (that is, replaced by its individual array elements).
6474 * - Each element that is not an array is unchanged
6475 * (even if the element is an object that has instance method +flatten+).
6477 * Returns +nil+ if no elements were flattened.
6479 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6481 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6482 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6483 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6484 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6485 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6486 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6488 * With +nil+ or negative argument +depth+, flattens all levels:
6490 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6491 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6493 * Related: Array#flatten;
6494 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6497 static VALUE
6498 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6500 int mod = 0, level = -1;
6501 VALUE result, lv;
6503 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6504 rb_ary_modify_check(ary);
6505 if (!NIL_P(lv)) level = NUM2INT(lv);
6506 if (level == 0) return Qnil;
6508 result = flatten(ary, level);
6509 if (result == ary) {
6510 return Qnil;
6512 if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6513 rb_ary_replace(ary, result);
6514 if (mod) ARY_SET_EMBED_LEN(result, 0);
6516 return ary;
6520 * call-seq:
6521 * flatten(depth = nil) -> new_array
6523 * Returns a new array that is a recursive flattening of +self+
6524 * to +depth+ levels of recursion;
6525 * +depth+ must be an
6526 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6527 * or +nil+.
6528 * At each level of recursion:
6530 * - Each element that is an array is "flattened"
6531 * (that is, replaced by its individual array elements).
6532 * - Each element that is not an array is unchanged
6533 * (even if the element is an object that has instance method +flatten+).
6535 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6537 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6538 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6539 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6540 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6541 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6542 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6543 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6545 * With +nil+ or negative +depth+, flattens all levels.
6547 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6548 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6550 * Related: Array#flatten!;
6551 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6554 static VALUE
6555 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6557 int level = -1;
6558 VALUE result;
6560 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6561 level = NUM2INT(argv[0]);
6562 if (level == 0) return ary_make_shared_copy(ary);
6565 result = flatten(ary, level);
6566 if (result == ary) {
6567 result = ary_make_shared_copy(ary);
6570 return result;
6573 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6575 static VALUE
6576 rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6578 long i, len;
6580 rb_ary_modify(ary);
6581 i = len = RARRAY_LEN(ary);
6582 RARRAY_PTR_USE(ary, ptr, {
6583 while (i) {
6584 long j = RAND_UPTO(i);
6585 VALUE tmp;
6586 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6587 rb_raise(rb_eRuntimeError, "modified during shuffle");
6589 tmp = ptr[--i];
6590 ptr[i] = ptr[j];
6591 ptr[j] = tmp;
6593 }); /* WB: no new reference */
6594 return ary;
6597 static VALUE
6598 rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6600 ary = rb_ary_dup(ary);
6601 rb_ary_shuffle_bang(ec, ary, randgen);
6602 return ary;
6605 static const rb_data_type_t ary_sample_memo_type = {
6606 .wrap_struct_name = "ary_sample_memo",
6607 .function = {
6608 .dfree = (RUBY_DATA_FUNC)st_free_table,
6610 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
6613 static VALUE
6614 ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6616 VALUE result;
6617 long n, len, i, j, k, idx[10];
6618 long rnds[numberof(idx)];
6619 long memo_threshold;
6621 len = RARRAY_LEN(ary);
6622 if (!to_array) {
6623 if (len < 2)
6624 i = 0;
6625 else
6626 i = RAND_UPTO(len);
6628 return rb_ary_elt(ary, i);
6630 n = NUM2LONG(nv);
6631 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
6632 if (n > len) n = len;
6633 if (n <= numberof(idx)) {
6634 for (i = 0; i < n; ++i) {
6635 rnds[i] = RAND_UPTO(len - i);
6638 k = len;
6639 len = RARRAY_LEN(ary);
6640 if (len < k && n <= numberof(idx)) {
6641 for (i = 0; i < n; ++i) {
6642 if (rnds[i] >= len) return rb_ary_new_capa(0);
6645 if (n > len) n = len;
6646 switch (n) {
6647 case 0:
6648 return rb_ary_new_capa(0);
6649 case 1:
6650 i = rnds[0];
6651 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
6652 case 2:
6653 i = rnds[0];
6654 j = rnds[1];
6655 if (j >= i) j++;
6656 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
6657 case 3:
6658 i = rnds[0];
6659 j = rnds[1];
6660 k = rnds[2];
6662 long l = j, g = i;
6663 if (j >= i) l = i, g = ++j;
6664 if (k >= l && (++k >= g)) ++k;
6666 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
6668 memo_threshold =
6669 len < 2560 ? len / 128 :
6670 len < 5120 ? len / 64 :
6671 len < 10240 ? len / 32 :
6672 len / 16;
6673 if (n <= numberof(idx)) {
6674 long sorted[numberof(idx)];
6675 sorted[0] = idx[0] = rnds[0];
6676 for (i=1; i<n; i++) {
6677 k = rnds[i];
6678 for (j = 0; j < i; ++j) {
6679 if (k < sorted[j]) break;
6680 ++k;
6682 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
6683 sorted[j] = idx[i] = k;
6685 result = rb_ary_new_capa(n);
6686 RARRAY_PTR_USE(result, ptr_result, {
6687 for (i=0; i<n; i++) {
6688 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
6692 else if (n <= memo_threshold / 2) {
6693 long max_idx = 0;
6694 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
6695 st_table *memo = st_init_numtable_with_size(n);
6696 RTYPEDDATA_DATA(vmemo) = memo;
6697 result = rb_ary_new_capa(n);
6698 RARRAY_PTR_USE(result, ptr_result, {
6699 for (i=0; i<n; i++) {
6700 long r = RAND_UPTO(len-i) + i;
6701 ptr_result[i] = r;
6702 if (r > max_idx) max_idx = r;
6704 len = RARRAY_LEN(ary);
6705 if (len <= max_idx) n = 0;
6706 else if (n > len) n = len;
6707 RARRAY_PTR_USE(ary, ptr_ary, {
6708 for (i=0; i<n; i++) {
6709 long j2 = j = ptr_result[i];
6710 long i2 = i;
6711 st_data_t value;
6712 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
6713 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
6714 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6715 ptr_result[i] = ptr_ary[j2];
6719 RTYPEDDATA_DATA(vmemo) = 0;
6720 st_free_table(memo);
6721 RB_GC_GUARD(vmemo);
6723 else {
6724 result = rb_ary_dup(ary);
6725 RBASIC_CLEAR_CLASS(result);
6726 RB_GC_GUARD(ary);
6727 RARRAY_PTR_USE(result, ptr_result, {
6728 for (i=0; i<n; i++) {
6729 j = RAND_UPTO(len-i) + i;
6730 nv = ptr_result[j];
6731 ptr_result[j] = ptr_result[i];
6732 ptr_result[i] = nv;
6735 RBASIC_SET_CLASS_RAW(result, rb_cArray);
6737 ARY_SET_LEN(result, n);
6739 return result;
6742 static VALUE
6743 ary_sample0(rb_execution_context_t *ec, VALUE ary)
6745 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
6748 static VALUE
6749 rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
6751 long mul;
6752 VALUE n = Qnil;
6753 if (args && (RARRAY_LEN(args) > 0)) {
6754 n = RARRAY_AREF(args, 0);
6756 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
6757 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
6758 mul = NUM2LONG(n);
6759 if (mul <= 0) return INT2FIX(0);
6760 n = LONG2FIX(mul);
6761 return rb_fix_mul_fix(rb_ary_length(self), n);
6765 * call-seq:
6766 * cycle(count = nil) {|element| ... } -> nil
6767 * cycle(count = nil) -> new_enumerator
6769 * With a block given, may call the block, depending on the value of argument +count+;
6770 * +count+ must be an
6771 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6772 * or +nil+.
6774 * When +count+ is positive,
6775 * calls the block with each element, then does so repeatedly,
6776 * until it has done so +count+ times; returns +nil+:
6778 * output = []
6779 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6780 * output # => [0, 1, 0, 1]
6782 * When +count+ is zero or negative, does not call the block:
6784 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6785 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6787 * When +count+ is +nil+, cycles forever:
6789 * # Prints 0 and 1 forever.
6790 * [0, 1].cycle {|element| puts element }
6791 * [0, 1].cycle(nil) {|element| puts element }
6793 * With no block given, returns a new Enumerator.
6795 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6797 static VALUE
6798 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
6800 long n, i;
6802 rb_check_arity(argc, 0, 1);
6804 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
6805 if (argc == 0 || NIL_P(argv[0])) {
6806 n = -1;
6808 else {
6809 n = NUM2LONG(argv[0]);
6810 if (n <= 0) return Qnil;
6813 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
6814 for (i=0; i<RARRAY_LEN(ary); i++) {
6815 rb_yield(RARRAY_AREF(ary, i));
6818 return Qnil;
6822 * Build a ruby array of the corresponding values and yield it to the
6823 * associated block.
6824 * Return the class of +values+ for reentry check.
6826 static int
6827 yield_indexed_values(const VALUE values, const long r, const long *const p)
6829 const VALUE result = rb_ary_new2(r);
6830 long i;
6832 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
6833 ARY_SET_LEN(result, r);
6834 rb_yield(result);
6835 return !RBASIC(values)->klass;
6839 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6841 * When we have a complete permutation of array indices, copy the values
6842 * at those indices into a new array and yield that array.
6844 * n: the size of the set
6845 * r: the number of elements in each permutation
6846 * p: the array (of size r) that we're filling in
6847 * used: an array of booleans: whether a given index is already used
6848 * values: the Ruby array that holds the actual values to permute
6850 static void
6851 permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
6853 long i = 0, index = 0;
6855 for (;;) {
6856 const char *const unused = memchr(&used[i], 0, n-i);
6857 if (!unused) {
6858 if (!index) break;
6859 i = p[--index]; /* pop index */
6860 used[i++] = 0; /* index unused */
6862 else {
6863 i = unused - used;
6864 p[index] = i;
6865 used[i] = 1; /* mark index used */
6866 ++index;
6867 if (index < r-1) { /* if not done yet */
6868 p[index] = i = 0;
6869 continue;
6871 for (i = 0; i < n; ++i) {
6872 if (used[i]) continue;
6873 p[index] = i;
6874 if (!yield_indexed_values(values, r, p)) {
6875 rb_raise(rb_eRuntimeError, "permute reentered");
6878 i = p[--index]; /* pop index */
6879 used[i] = 0; /* index unused */
6880 p[index] = ++i;
6886 * Returns the product of from, from-1, ..., from - how_many + 1.
6887 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6889 static VALUE
6890 descending_factorial(long from, long how_many)
6892 VALUE cnt;
6893 if (how_many > 0) {
6894 cnt = LONG2FIX(from);
6895 while (--how_many > 0) {
6896 long v = --from;
6897 cnt = rb_int_mul(cnt, LONG2FIX(v));
6900 else {
6901 cnt = LONG2FIX(how_many == 0);
6903 return cnt;
6906 static VALUE
6907 binomial_coefficient(long comb, long size)
6909 VALUE r;
6910 long i;
6911 if (comb > size-comb) {
6912 comb = size-comb;
6914 if (comb < 0) {
6915 return LONG2FIX(0);
6917 else if (comb == 0) {
6918 return LONG2FIX(1);
6920 r = LONG2FIX(size);
6921 for (i = 1; i < comb; ++i) {
6922 r = rb_int_mul(r, LONG2FIX(size - i));
6923 r = rb_int_idiv(r, LONG2FIX(i + 1));
6925 return r;
6928 static VALUE
6929 rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
6931 long n = RARRAY_LEN(ary);
6932 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
6934 return descending_factorial(n, k);
6938 * call-seq:
6939 * permutation(n = self.size) {|permutation| ... } -> self
6940 * permutation(n = self.size) -> new_enumerator
6942 * Iterates over permutations of the elements of +self+;
6943 * the order of permutations is indeterminate.
6945 * With a block and an in-range positive integer argument +n+ (<tt>0 < n <= self.size</tt>) given,
6946 * calls the block with each +n+-tuple permutations of +self+;
6947 * returns +self+:
6949 * a = [0, 1, 2]
6950 * perms = []
6951 * a.permutation(1) {|perm| perms.push(perm) }
6952 * perms # => [[0], [1], [2]]
6954 * perms = []
6955 * a.permutation(2) {|perm| perms.push(perm) }
6956 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
6958 * perms = []
6959 * a.permutation(3) {|perm| perms.push(perm) }
6960 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
6962 * When +n+ is zero, calls the block once with a new empty array:
6964 * perms = []
6965 * a.permutation(0) {|perm| perms.push(perm) }
6966 * perms # => [[]]
6968 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
6969 * does not call the block:
6971 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
6972 * a.permutation(4) {|permutation| fail 'Cannot happen' }
6974 * With no block given, returns a new Enumerator.
6976 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6979 static VALUE
6980 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
6982 long r, n, i;
6984 n = RARRAY_LEN(ary); /* Array length */
6985 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
6986 r = n;
6987 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
6988 r = NUM2LONG(argv[0]); /* Permutation size from argument */
6990 if (r < 0 || n < r) {
6991 /* no permutations: yield nothing */
6993 else if (r == 0) { /* exactly one permutation: the zero-length array */
6994 rb_yield(rb_ary_new2(0));
6996 else if (r == 1) { /* this is a special, easy case */
6997 for (i = 0; i < RARRAY_LEN(ary); i++) {
6998 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7001 else { /* this is the general case */
7002 volatile VALUE t0;
7003 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
7004 char *used = (char*)(p + r);
7005 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7006 RBASIC_CLEAR_CLASS(ary0);
7008 MEMZERO(used, char, n); /* initialize array */
7010 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7011 ALLOCV_END(t0);
7012 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7014 return ary;
7017 static void
7018 combinate0(const long len, const long n, long *const stack, const VALUE values)
7020 long lev = 0;
7022 MEMZERO(stack+1, long, n);
7023 stack[0] = -1;
7024 for (;;) {
7025 for (lev++; lev < n; lev++) {
7026 stack[lev+1] = stack[lev]+1;
7028 if (!yield_indexed_values(values, n, stack+1)) {
7029 rb_raise(rb_eRuntimeError, "combination reentered");
7031 do {
7032 if (lev == 0) return;
7033 stack[lev--]++;
7034 } while (stack[lev+1]+n == len+lev+1);
7038 static VALUE
7039 rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7041 long n = RARRAY_LEN(ary);
7042 long k = NUM2LONG(RARRAY_AREF(args, 0));
7044 return binomial_coefficient(k, n);
7048 * call-seq:
7049 * combination(n) {|element| ... } -> self
7050 * combination(n) -> new_enumerator
7052 * When a block and a positive
7053 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7054 * argument +n+ (<tt>0 < n <= self.size</tt>)
7055 * are given, calls the block with all +n+-tuple combinations of +self+;
7056 * returns +self+:
7058 * a = %w[a b c] # => ["a", "b", "c"]
7059 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7061 * Output:
7063 * ["a", "b"]
7064 * ["a", "c"]
7065 * ["b", "c"]
7067 * The order of the yielded combinations is not guaranteed.
7069 * When +n+ is zero, calls the block once with a new empty array:
7071 * a.combination(0) {|combination| p combination }
7072 * [].combination(0) {|combination| p combination }
7074 * Output:
7076 * []
7077 * []
7079 * When +n+ is negative or larger than +self.size+ and +self+ is non-empty,
7080 * does not call the block:
7082 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7083 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7085 * With no block given, returns a new Enumerator.
7087 * Related: Array#permutation;
7088 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7091 static VALUE
7092 rb_ary_combination(VALUE ary, VALUE num)
7094 long i, n, len;
7096 n = NUM2LONG(num);
7097 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7098 len = RARRAY_LEN(ary);
7099 if (n < 0 || len < n) {
7100 /* yield nothing */
7102 else if (n == 0) {
7103 rb_yield(rb_ary_new2(0));
7105 else if (n == 1) {
7106 for (i = 0; i < RARRAY_LEN(ary); i++) {
7107 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7110 else {
7111 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7112 volatile VALUE t0;
7113 long *stack = ALLOCV_N(long, t0, n+1);
7115 RBASIC_CLEAR_CLASS(ary0);
7116 combinate0(len, n, stack, ary0);
7117 ALLOCV_END(t0);
7118 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7120 return ary;
7124 * Compute repeated permutations of +r+ elements of the set
7125 * <code>[0..n-1]</code>.
7127 * When we have a complete repeated permutation of array indices, copy the
7128 * values at those indices into a new array and yield that array.
7130 * n: the size of the set
7131 * r: the number of elements in each permutation
7132 * p: the array (of size r) that we're filling in
7133 * values: the Ruby array that holds the actual values to permute
7135 static void
7136 rpermute0(const long n, const long r, long *const p, const VALUE values)
7138 long i = 0, index = 0;
7140 p[index] = i;
7141 for (;;) {
7142 if (++index < r-1) {
7143 p[index] = i = 0;
7144 continue;
7146 for (i = 0; i < n; ++i) {
7147 p[index] = i;
7148 if (!yield_indexed_values(values, r, p)) {
7149 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7152 do {
7153 if (index <= 0) return;
7154 } while ((i = ++p[--index]) >= n);
7158 static VALUE
7159 rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7161 long n = RARRAY_LEN(ary);
7162 long k = NUM2LONG(RARRAY_AREF(args, 0));
7164 if (k < 0) {
7165 return LONG2FIX(0);
7167 if (n <= 0) {
7168 return LONG2FIX(!k);
7170 return rb_int_positive_pow(n, (unsigned long)k);
7174 * call-seq:
7175 * repeated_permutation(size) {|permutation| ... } -> self
7176 * repeated_permutation(size) -> new_enumerator
7178 * With a block given, calls the block with each repeated permutation of length +size+
7179 * of the elements of +self+;
7180 * each permutation is an array;
7181 * returns +self+. The order of the permutations is indeterminate.
7183 * If a positive integer argument +size+ is given,
7184 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7185 * The number of permutations is <tt>self.size**size</tt>.
7187 * Examples:
7189 * - +size+ is 1:
7191 * p = []
7192 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7193 * p # => [[0], [1], [2]]
7195 * - +size+ is 2:
7197 * p = []
7198 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7199 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7201 * If +size+ is zero, calls the block once with an empty array.
7203 * If +size+ is negative, does not call the block:
7205 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7207 * With no block given, returns a new Enumerator.
7209 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7211 static VALUE
7212 rb_ary_repeated_permutation(VALUE ary, VALUE num)
7214 long r, n, i;
7216 n = RARRAY_LEN(ary); /* Array length */
7217 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7218 r = NUM2LONG(num); /* Permutation size from argument */
7220 if (r < 0) {
7221 /* no permutations: yield nothing */
7223 else if (r == 0) { /* exactly one permutation: the zero-length array */
7224 rb_yield(rb_ary_new2(0));
7226 else if (r == 1) { /* this is a special, easy case */
7227 for (i = 0; i < RARRAY_LEN(ary); i++) {
7228 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7231 else { /* this is the general case */
7232 volatile VALUE t0;
7233 long *p = ALLOCV_N(long, t0, r);
7234 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7235 RBASIC_CLEAR_CLASS(ary0);
7237 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7238 ALLOCV_END(t0);
7239 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7241 return ary;
7244 static void
7245 rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7247 long i = 0, index = 0;
7249 p[index] = i;
7250 for (;;) {
7251 if (++index < r-1) {
7252 p[index] = i;
7253 continue;
7255 for (; i < n; ++i) {
7256 p[index] = i;
7257 if (!yield_indexed_values(values, r, p)) {
7258 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7261 do {
7262 if (index <= 0) return;
7263 } while ((i = ++p[--index]) >= n);
7267 static VALUE
7268 rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7270 long n = RARRAY_LEN(ary);
7271 long k = NUM2LONG(RARRAY_AREF(args, 0));
7272 if (k == 0) {
7273 return LONG2FIX(1);
7275 return binomial_coefficient(k, n + k - 1);
7279 * call-seq:
7280 * repeated_combination(size) {|combination| ... } -> self
7281 * repeated_combination(size) -> new_enumerator
7283 * With a block given, calls the block with each repeated combination of length +size+
7284 * of the elements of +self+;
7285 * each combination is an array;
7286 * returns +self+. The order of the combinations is indeterminate.
7288 * If a positive integer argument +size+ is given,
7289 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7290 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7292 * Examples:
7294 * - +size+ is 1:
7296 * c = []
7297 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7298 * c # => [[0], [1], [2]]
7300 * - +size+ is 2:
7302 * c = []
7303 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7304 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7306 * If +size+ is zero, calls the block once with an empty array.
7308 * If +size+ is negative, does not call the block:
7310 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7312 * With no block given, returns a new Enumerator.
7314 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7317 static VALUE
7318 rb_ary_repeated_combination(VALUE ary, VALUE num)
7320 long n, i, len;
7322 n = NUM2LONG(num); /* Combination size from argument */
7323 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7324 len = RARRAY_LEN(ary);
7325 if (n < 0) {
7326 /* yield nothing */
7328 else if (n == 0) {
7329 rb_yield(rb_ary_new2(0));
7331 else if (n == 1) {
7332 for (i = 0; i < RARRAY_LEN(ary); i++) {
7333 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7336 else if (len == 0) {
7337 /* yield nothing */
7339 else {
7340 volatile VALUE t0;
7341 long *p = ALLOCV_N(long, t0, n);
7342 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7343 RBASIC_CLEAR_CLASS(ary0);
7345 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7346 ALLOCV_END(t0);
7347 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7349 return ary;
7353 * call-seq:
7354 * product(*other_arrays) -> new_array
7355 * product(*other_arrays) {|combination| ... } -> self
7357 * Computes all combinations of elements from all the arrays,
7358 * including both +self+ and +other_arrays+:
7360 * - The number of combinations is the product of the sizes of all the arrays,
7361 * including both +self+ and +other_arrays+.
7362 * - The order of the returned combinations is indeterminate.
7364 * With no block given, returns the combinations as an array of arrays:
7366 * p = [0, 1].product([2, 3])
7367 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7368 * p.size # => 4
7369 * p = [0, 1].product([2, 3], [4, 5])
7370 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7371 * p.size # => 8
7373 * If +self+ or any argument is empty, returns an empty array:
7375 * [].product([2, 3], [4, 5]) # => []
7376 * [0, 1].product([2, 3], []) # => []
7378 * If no argument is given, returns an array of 1-element arrays,
7379 * each containing an element of +self+:
7381 * a.product # => [[0], [1], [2]]
7383 * With a block given, calls the block with each combination; returns +self+:
7385 * p = []
7386 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7387 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7389 * If +self+ or any argument is empty, does not call the block:
7391 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7392 * # => []
7393 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7394 * # => [0, 1]
7396 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7398 * p = []
7399 * [0, 1].product {|combination| p.push(combination) }
7400 * p # => [[0], [1]]
7402 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7405 static VALUE
7406 rb_ary_product(int argc, VALUE *argv, VALUE ary)
7408 int n = argc+1; /* How many arrays we're operating on */
7409 volatile VALUE t0 = rb_ary_hidden_new(n);
7410 volatile VALUE t1 = Qundef;
7411 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7412 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7413 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7414 long i,j;
7415 long resultlen = 1;
7417 RBASIC_CLEAR_CLASS(t0);
7419 /* initialize the arrays of arrays */
7420 ARY_SET_LEN(t0, n);
7421 arrays[0] = ary;
7422 for (i = 1; i < n; i++) arrays[i] = Qnil;
7423 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7425 /* initialize the counters for the arrays */
7426 for (i = 0; i < n; i++) counters[i] = 0;
7428 /* Otherwise, allocate and fill in an array of results */
7429 if (rb_block_given_p()) {
7430 /* Make defensive copies of arrays; exit if any is empty */
7431 for (i = 0; i < n; i++) {
7432 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7433 arrays[i] = ary_make_shared_copy(arrays[i]);
7436 else {
7437 /* Compute the length of the result array; return [] if any is empty */
7438 for (i = 0; i < n; i++) {
7439 long k = RARRAY_LEN(arrays[i]);
7440 if (k == 0) {
7441 result = rb_ary_new2(0);
7442 goto done;
7444 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7445 rb_raise(rb_eRangeError, "too big to product");
7446 resultlen *= k;
7448 result = rb_ary_new2(resultlen);
7450 for (;;) {
7451 int m;
7452 /* fill in one subarray */
7453 VALUE subarray = rb_ary_new2(n);
7454 for (j = 0; j < n; j++) {
7455 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7458 /* put it on the result array */
7459 if (NIL_P(result)) {
7460 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7461 rb_yield(subarray);
7462 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7463 rb_raise(rb_eRuntimeError, "product reentered");
7465 else {
7466 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7469 else {
7470 rb_ary_push(result, subarray);
7474 * Increment the last counter. If it overflows, reset to 0
7475 * and increment the one before it.
7477 m = n-1;
7478 counters[m]++;
7479 while (counters[m] == RARRAY_LEN(arrays[m])) {
7480 counters[m] = 0;
7481 /* If the first counter overflows, we are done */
7482 if (--m < 0) goto done;
7483 counters[m]++;
7487 done:
7488 ALLOCV_END(t1);
7490 return NIL_P(result) ? ary : result;
7494 * call-seq:
7495 * take(count) -> new_array
7497 * Returns a new array containing the first +count+ element of +self+
7498 * (as available);
7499 * +count+ must be a non-negative numeric;
7500 * does not modify +self+:
7502 * a = ['a', 'b', 'c', 'd']
7503 * a.take(2) # => ["a", "b"]
7504 * a.take(2.1) # => ["a", "b"]
7505 * a.take(50) # => ["a", "b", "c", "d"]
7506 * a.take(0) # => []
7508 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7511 static VALUE
7512 rb_ary_take(VALUE obj, VALUE n)
7514 long len = NUM2LONG(n);
7515 if (len < 0) {
7516 rb_raise(rb_eArgError, "attempt to take negative size");
7518 return rb_ary_subseq(obj, 0, len);
7522 * call-seq:
7523 * take_while {|element| ... } -> new_array
7524 * take_while -> new_enumerator
7526 * With a block given, calls the block with each successive element of +self+;
7527 * stops iterating if the block returns +false+ or +nil+;
7528 * returns a new array containing those elements for which the block returned a truthy value:
7530 * a = [0, 1, 2, 3, 4, 5]
7531 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7532 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7533 * a.take_while {|element| false } # => []
7535 * With no block given, returns a new Enumerator.
7537 * Does not modify +self+.
7539 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7542 static VALUE
7543 rb_ary_take_while(VALUE ary)
7545 long i;
7547 RETURN_ENUMERATOR(ary, 0, 0);
7548 for (i = 0; i < RARRAY_LEN(ary); i++) {
7549 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7551 return rb_ary_take(ary, LONG2FIX(i));
7555 * call-seq:
7556 * drop(n) -> new_array
7558 * Returns a new array containing all but the first +n+ element of +self+,
7559 * where +n+ is a non-negative Integer;
7560 * does not modify +self+.
7562 * Examples:
7564 * a = [0, 1, 2, 3, 4, 5]
7565 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7566 * a.drop(1) # => [1, 2, 3, 4, 5]
7567 * a.drop(2) # => [2, 3, 4, 5]
7568 * a.drop(9) # => []
7570 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7573 static VALUE
7574 rb_ary_drop(VALUE ary, VALUE n)
7576 VALUE result;
7577 long pos = NUM2LONG(n);
7578 if (pos < 0) {
7579 rb_raise(rb_eArgError, "attempt to drop negative size");
7582 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7583 if (NIL_P(result)) result = rb_ary_new();
7584 return result;
7588 * call-seq:
7589 * drop_while {|element| ... } -> new_array
7590 * drop_while -> new_enumerator
7592 * With a block given, calls the block with each successive element of +self+;
7593 * stops if the block returns +false+ or +nil+;
7594 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7595 * does not modify +self+:
7597 * a = [0, 1, 2, 3, 4, 5]
7598 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7600 * With no block given, returns a new Enumerator.
7602 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7605 static VALUE
7606 rb_ary_drop_while(VALUE ary)
7608 long i;
7610 RETURN_ENUMERATOR(ary, 0, 0);
7611 for (i = 0; i < RARRAY_LEN(ary); i++) {
7612 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7614 return rb_ary_drop(ary, LONG2FIX(i));
7618 * call-seq:
7619 * any? -> true or false
7620 * any?(object) -> true or false
7621 * any? {|element| ... } -> true or false
7623 * Returns whether for any element of +self+, a given criterion is satisfied.
7625 * With no block and no argument, returns whether any element of +self+ is truthy:
7627 * [nil, false, []].any? # => true # Array object is truthy.
7628 * [nil, false, {}].any? # => true # Hash object is truthy.
7629 * [nil, false, ''].any? # => true # String object is truthy.
7630 * [nil, false].any? # => false # Nil and false are not truthy.
7632 * With argument +object+ given,
7633 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7635 * [nil, false, 0].any?(0) # => true
7636 * [nil, false, 1].any?(0) # => false
7637 * [nil, false, 'food'].any?(/foo/) # => true
7638 * [nil, false, 'food'].any?(/bar/) # => false
7640 * With a block given,
7641 * calls the block with each element in +self+;
7642 * returns whether the block returns any truthy value:
7644 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7645 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7647 * With both a block and argument +object+ given,
7648 * ignores the block and uses +object+ as above.
7650 * <b>Special case</b>: returns +false+ if +self+ is empty
7651 * (regardless of any given argument or block).
7653 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7656 static VALUE
7657 rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
7659 long i, len = RARRAY_LEN(ary);
7661 rb_check_arity(argc, 0, 1);
7662 if (!len) return Qfalse;
7663 if (argc) {
7664 if (rb_block_given_p()) {
7665 rb_warn("given block not used");
7667 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7668 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
7671 else if (!rb_block_given_p()) {
7672 for (i = 0; i < len; ++i) {
7673 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
7676 else {
7677 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7678 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
7681 return Qfalse;
7685 * call-seq:
7686 * all? -> true or false
7687 * all?(object) -> true or false
7688 * all? {|element| ... } -> true or false
7690 * Returns whether for every element of +self+,
7691 * a given criterion is satisfied.
7693 * With no block and no argument,
7694 * returns whether every element of +self+ is truthy:
7696 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7697 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7698 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7700 * With argument +object+ given, returns whether <tt>object === ele</tt>
7701 * for every element +ele+ in +self+:
7703 * [0, 0, 0].all?(0) # => true
7704 * [0, 1, 2].all?(1) # => false
7705 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7706 * ['food', 'drink'].all?(/foo/) # => false
7708 * With a block given, calls the block with each element in +self+;
7709 * returns whether the block returns only truthy values:
7711 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7712 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7714 * With both a block and argument +object+ given,
7715 * ignores the block and uses +object+ as above.
7717 * <b>Special case</b>: returns +true+ if +self+ is empty
7718 * (regardless of any given argument or block).
7720 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7723 static VALUE
7724 rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
7726 long i, len = RARRAY_LEN(ary);
7728 rb_check_arity(argc, 0, 1);
7729 if (!len) return Qtrue;
7730 if (argc) {
7731 if (rb_block_given_p()) {
7732 rb_warn("given block not used");
7734 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7735 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7738 else if (!rb_block_given_p()) {
7739 for (i = 0; i < len; ++i) {
7740 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7743 else {
7744 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7745 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7748 return Qtrue;
7752 * call-seq:
7753 * none? -> true or false
7754 * none?(object) -> true or false
7755 * none? {|element| ... } -> true or false
7757 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
7759 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7760 * +false+ otherwise:
7762 * [nil, false].none? # => true
7763 * [nil, 0, false].none? # => false
7764 * [].none? # => true
7766 * With argument +object+ given, returns +false+ if for any element +element+,
7767 * <tt>object === element</tt>; +true+ otherwise:
7769 * ['food', 'drink'].none?(/bar/) # => true
7770 * ['food', 'drink'].none?(/foo/) # => false
7771 * [].none?(/foo/) # => true
7772 * [0, 1, 2].none?(3) # => true
7773 * [0, 1, 2].none?(1) # => false
7775 * With a block given, calls the block with each element in +self+;
7776 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7778 * [0, 1, 2].none? {|element| element > 3 } # => true
7779 * [0, 1, 2].none? {|element| element > 1 } # => false
7781 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7784 static VALUE
7785 rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
7787 long i, len = RARRAY_LEN(ary);
7789 rb_check_arity(argc, 0, 1);
7790 if (!len) return Qtrue;
7791 if (argc) {
7792 if (rb_block_given_p()) {
7793 rb_warn("given block not used");
7795 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7796 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7799 else if (!rb_block_given_p()) {
7800 for (i = 0; i < len; ++i) {
7801 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7804 else {
7805 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7806 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7809 return Qtrue;
7813 * call-seq:
7814 * one? -> true or false
7815 * one? {|element| ... } -> true or false
7816 * one?(object) -> true or false
7818 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7820 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7821 * +false+ otherwise:
7823 * [nil, 0].one? # => true
7824 * [0, 0].one? # => false
7825 * [nil, nil].one? # => false
7826 * [].one? # => false
7828 * With a block given, calls the block with each element in +self+;
7829 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7831 * [0, 1, 2].one? {|element| element > 0 } # => false
7832 * [0, 1, 2].one? {|element| element > 1 } # => true
7833 * [0, 1, 2].one? {|element| element > 2 } # => false
7835 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
7836 * +false+ otherwise:
7838 * [0, 1, 2].one?(0) # => true
7839 * [0, 0, 1].one?(0) # => false
7840 * [1, 1, 2].one?(0) # => false
7841 * ['food', 'drink'].one?(/bar/) # => false
7842 * ['food', 'drink'].one?(/foo/) # => true
7843 * [].one?(/foo/) # => false
7845 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7848 static VALUE
7849 rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
7851 long i, len = RARRAY_LEN(ary);
7852 VALUE result = Qfalse;
7854 rb_check_arity(argc, 0, 1);
7855 if (!len) return Qfalse;
7856 if (argc) {
7857 if (rb_block_given_p()) {
7858 rb_warn("given block not used");
7860 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7861 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
7862 if (result) return Qfalse;
7863 result = Qtrue;
7867 else if (!rb_block_given_p()) {
7868 for (i = 0; i < len; ++i) {
7869 if (RTEST(RARRAY_AREF(ary, i))) {
7870 if (result) return Qfalse;
7871 result = Qtrue;
7875 else {
7876 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7877 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
7878 if (result) return Qfalse;
7879 result = Qtrue;
7883 return result;
7887 * call-seq:
7888 * array.dig(index, *identifiers) -> object
7890 * Finds and returns the object in nested object
7891 * specified by +index+ and +identifiers+;
7892 * the nested objects may be instances of various classes.
7893 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
7895 * Examples:
7897 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
7898 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
7899 * a.dig(1, 2) # => [:bat, :bam]
7900 * a.dig(1, 2, 0) # => :bat
7901 * a.dig(1, 2, 3) # => nil
7903 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7906 static VALUE
7907 rb_ary_dig(int argc, VALUE *argv, VALUE self)
7909 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
7910 self = rb_ary_at(self, *argv);
7911 if (!--argc) return self;
7912 ++argv;
7913 return rb_obj_dig(argc, argv, self, Qnil);
7916 static inline VALUE
7917 finish_exact_sum(long n, VALUE r, VALUE v, int z)
7919 if (n != 0)
7920 v = rb_fix_plus(LONG2FIX(n), v);
7921 if (!UNDEF_P(r)) {
7922 v = rb_rational_plus(r, v);
7924 else if (!n && z) {
7925 v = rb_fix_plus(LONG2FIX(0), v);
7927 return v;
7931 * call-seq:
7932 * sum(init = 0) -> object
7933 * sum(init = 0) {|element| ... } -> object
7935 * With no block given, returns the sum of +init+ and all elements of +self+;
7936 * for array +array+ and value +init+, equivalent to:
7938 * sum = init
7939 * array.each {|element| sum += element }
7940 * sum
7942 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
7944 * Examples:
7946 * [0, 1, 2, 3].sum # => 6
7947 * [0, 1, 2, 3].sum(100) # => 106
7948 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
7949 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
7950 * # => [2, 3, :foo, :bar, "foo", "bar"]
7952 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
7954 * # Raises TypeError: Array can't be coerced into Integer.
7955 * [[:foo, :bar], ['foo', 'bar']].sum(2)
7957 * With a block given, calls the block with each element of +self+;
7958 * the block's return value (instead of the element itself) is used as the addend:
7960 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
7961 * # => "Coerced and concatenated: zero1two"
7963 * Notes:
7965 * - Array#join and Array#flatten may be faster than Array#sum
7966 * for an array of strings or an array of arrays.
7967 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
7971 static VALUE
7972 rb_ary_sum(int argc, VALUE *argv, VALUE ary)
7974 VALUE e, v, r;
7975 long i, n;
7976 int block_given;
7978 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
7980 block_given = rb_block_given_p();
7982 if (RARRAY_LEN(ary) == 0)
7983 return v;
7985 n = 0;
7986 r = Qundef;
7988 if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
7989 i = 0;
7990 goto init_is_a_value;
7993 for (i = 0; i < RARRAY_LEN(ary); i++) {
7994 e = RARRAY_AREF(ary, i);
7995 if (block_given)
7996 e = rb_yield(e);
7997 if (FIXNUM_P(e)) {
7998 n += FIX2LONG(e); /* should not overflow long type */
7999 if (!FIXABLE(n)) {
8000 v = rb_big_plus(LONG2NUM(n), v);
8001 n = 0;
8004 else if (RB_BIGNUM_TYPE_P(e))
8005 v = rb_big_plus(e, v);
8006 else if (RB_TYPE_P(e, T_RATIONAL)) {
8007 if (UNDEF_P(r))
8008 r = e;
8009 else
8010 r = rb_rational_plus(r, e);
8012 else
8013 goto not_exact;
8015 v = finish_exact_sum(n, r, v, argc!=0);
8016 return v;
8018 not_exact:
8019 v = finish_exact_sum(n, r, v, i!=0);
8021 if (RB_FLOAT_TYPE_P(e)) {
8023 * Kahan-Babuska balancing compensated summation algorithm
8024 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8026 double f, c;
8027 double x, t;
8029 f = NUM2DBL(v);
8030 c = 0.0;
8031 goto has_float_value;
8032 for (; i < RARRAY_LEN(ary); i++) {
8033 e = RARRAY_AREF(ary, i);
8034 if (block_given)
8035 e = rb_yield(e);
8036 if (RB_FLOAT_TYPE_P(e))
8037 has_float_value:
8038 x = RFLOAT_VALUE(e);
8039 else if (FIXNUM_P(e))
8040 x = FIX2LONG(e);
8041 else if (RB_BIGNUM_TYPE_P(e))
8042 x = rb_big2dbl(e);
8043 else if (RB_TYPE_P(e, T_RATIONAL))
8044 x = rb_num2dbl(e);
8045 else
8046 goto not_float;
8048 if (isnan(f)) continue;
8049 if (isnan(x)) {
8050 f = x;
8051 continue;
8053 if (isinf(x)) {
8054 if (isinf(f) && signbit(x) != signbit(f))
8055 f = NAN;
8056 else
8057 f = x;
8058 continue;
8060 if (isinf(f)) continue;
8062 t = f + x;
8063 if (fabs(f) >= fabs(x))
8064 c += ((f - t) + x);
8065 else
8066 c += ((x - t) + f);
8067 f = t;
8069 f += c;
8070 return DBL2NUM(f);
8072 not_float:
8073 v = DBL2NUM(f);
8076 goto has_some_value;
8077 init_is_a_value:
8078 for (; i < RARRAY_LEN(ary); i++) {
8079 e = RARRAY_AREF(ary, i);
8080 if (block_given)
8081 e = rb_yield(e);
8082 has_some_value:
8083 v = rb_funcall(v, idPLUS, 1, e);
8085 return v;
8088 /* :nodoc: */
8089 static VALUE
8090 rb_ary_deconstruct(VALUE ary)
8092 return ary;
8096 * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
8097 * Any object (even another array) may be an array element,
8098 * and an array can contain objects of different types.
8100 * == +Array+ Indexes
8102 * +Array+ indexing starts at 0, as in C or Java.
8104 * A positive index is an offset from the first element:
8106 * - Index 0 indicates the first element.
8107 * - Index 1 indicates the second element.
8108 * - ...
8110 * A negative index is an offset, backwards, from the end of the array:
8112 * - Index -1 indicates the last element.
8113 * - Index -2 indicates the next-to-last element.
8114 * - ...
8116 * A non-negative index is <i>in range</i> if and only if it is smaller than
8117 * the size of the array. For a 3-element array:
8119 * - Indexes 0 through 2 are in range.
8120 * - Index 3 is out of range.
8122 * A negative index is <i>in range</i> if and only if its absolute value is
8123 * not larger than the size of the array. For a 3-element array:
8125 * - Indexes -1 through -3 are in range.
8126 * - Index -4 is out of range.
8128 * Although the effective index into an array is always an integer,
8129 * some methods (both within and outside of class +Array+)
8130 * accept one or more non-integer arguments that are
8131 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8134 * == Creating Arrays
8136 * You can create an +Array+ object explicitly with:
8138 * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
8140 * [1, 'one', :one, [2, 'two', :two]]
8142 * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8144 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8145 * %w[1 % *] # => ["1", "%", "*"]
8147 * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8149 * %i[foo bar baz] # => [:foo, :bar, :baz]
8150 * %i[1 % *] # => [:"1", :%, :*]
8152 * - \Method Kernel#Array:
8154 * Array(["a", "b"]) # => ["a", "b"]
8155 * Array(1..5) # => [1, 2, 3, 4, 5]
8156 * Array(key: :value) # => [[:key, :value]]
8157 * Array(nil) # => []
8158 * Array(1) # => [1]
8159 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8161 * - \Method Array.new:
8163 * Array.new # => []
8164 * Array.new(3) # => [nil, nil, nil]
8165 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8166 * Array.new(3, true) # => [true, true, true]
8168 * Note that the last example above populates the array
8169 * with references to the same object.
8170 * This is recommended only in cases where that object is a natively immutable object
8171 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8173 * Another way to create an array with various objects, using a block;
8174 * this usage is safe for mutable objects such as hashes, strings or
8175 * other arrays:
8177 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8179 * Here is a way to create a multi-dimensional array:
8181 * Array.new(3) {Array.new(3)}
8182 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8184 * A number of Ruby methods, both in the core and in the standard library,
8185 * provide instance method +to_a+, which converts an object to an array.
8187 * - ARGF#to_a
8188 * - Array#to_a
8189 * - Enumerable#to_a
8190 * - Hash#to_a
8191 * - MatchData#to_a
8192 * - NilClass#to_a
8193 * - OptionParser#to_a
8194 * - Range#to_a
8195 * - Set#to_a
8196 * - Struct#to_a
8197 * - Time#to_a
8198 * - Benchmark::Tms#to_a
8199 * - CSV::Table#to_a
8200 * - Enumerator::Lazy#to_a
8201 * - Gem::List#to_a
8202 * - Gem::NameTuple#to_a
8203 * - Gem::Platform#to_a
8204 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8205 * - Gem::SourceList#to_a
8206 * - OpenSSL::X509::Extension#to_a
8207 * - OpenSSL::X509::Name#to_a
8208 * - Racc::ISet#to_a
8209 * - Rinda::RingFinger#to_a
8210 * - Ripper::Lexer::Elem#to_a
8211 * - RubyVM::InstructionSequence#to_a
8212 * - YAML::DBM#to_a
8214 * == Example Usage
8216 * In addition to the methods it mixes in through the Enumerable module, the
8217 * +Array+ class has proprietary methods for accessing, searching and otherwise
8218 * manipulating arrays.
8220 * Some of the more common ones are illustrated below.
8222 * == Accessing Elements
8224 * Elements in an array can be retrieved using the Array#[] method. It can
8225 * take a single integer argument (a numeric index), a pair of arguments
8226 * (start and length) or a range. Negative indices start counting from the end,
8227 * with -1 being the last element.
8229 * arr = [1, 2, 3, 4, 5, 6]
8230 * arr[2] #=> 3
8231 * arr[100] #=> nil
8232 * arr[-3] #=> 4
8233 * arr[2, 3] #=> [3, 4, 5]
8234 * arr[1..4] #=> [2, 3, 4, 5]
8235 * arr[1..-3] #=> [2, 3, 4]
8237 * Another way to access a particular array element is by using the #at method
8239 * arr.at(0) #=> 1
8241 * The #slice method works in an identical manner to Array#[].
8243 * To raise an error for indices outside of the array bounds or else to
8244 * provide a default value when that happens, you can use #fetch.
8246 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8247 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8248 * arr.fetch(100, "oops") #=> "oops"
8250 * The special methods #first and #last will return the first and last
8251 * elements of an array, respectively.
8253 * arr.first #=> 1
8254 * arr.last #=> 6
8256 * To return the first +n+ elements of an array, use #take
8258 * arr.take(3) #=> [1, 2, 3]
8260 * #drop does the opposite of #take, by returning the elements after +n+
8261 * elements have been dropped:
8263 * arr.drop(3) #=> [4, 5, 6]
8265 * == Obtaining Information about an +Array+
8267 * Arrays keep track of their own length at all times. To query an array
8268 * about the number of elements it contains, use #length, #count or #size.
8270 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8271 * browsers.length #=> 5
8272 * browsers.count #=> 5
8274 * To check whether an array contains any elements at all
8276 * browsers.empty? #=> false
8278 * To check whether a particular item is included in the array
8280 * browsers.include?('Konqueror') #=> false
8282 * == Adding Items to Arrays
8284 * Items can be added to the end of an array by using either #push or #<<
8286 * arr = [1, 2, 3, 4]
8287 * arr.push(5) #=> [1, 2, 3, 4, 5]
8288 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8290 * #unshift will add a new item to the beginning of an array.
8292 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8294 * With #insert you can add a new element to an array at any position.
8296 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8298 * Using the #insert method, you can also insert multiple values at once:
8300 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8301 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8303 * == Removing Items from an +Array+
8305 * The method #pop removes the last element in an array and returns it:
8307 * arr = [1, 2, 3, 4, 5, 6]
8308 * arr.pop #=> 6
8309 * arr #=> [1, 2, 3, 4, 5]
8311 * To retrieve and at the same time remove the first item, use #shift:
8313 * arr.shift #=> 1
8314 * arr #=> [2, 3, 4, 5]
8316 * To delete an element at a particular index:
8318 * arr.delete_at(2) #=> 4
8319 * arr #=> [2, 3, 5]
8321 * To delete a particular element anywhere in an array, use #delete:
8323 * arr = [1, 2, 2, 3]
8324 * arr.delete(2) #=> 2
8325 * arr #=> [1,3]
8327 * A useful method if you need to remove +nil+ values from an array is
8328 * #compact:
8330 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8331 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8332 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8333 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8334 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8336 * Another common need is to remove duplicate elements from an array.
8338 * It has the non-destructive #uniq, and destructive method #uniq!
8340 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8341 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8343 * == Iterating over Arrays
8345 * Like all classes that include the Enumerable module, +Array+ has an each
8346 * method, which defines what elements should be iterated over and how. In
8347 * case of Array's #each, all elements in the +Array+ instance are yielded to
8348 * the supplied block in sequence.
8350 * Note that this operation leaves the array unchanged.
8352 * arr = [1, 2, 3, 4, 5]
8353 * arr.each {|a| print a -= 10, " "}
8354 * # prints: -9 -8 -7 -6 -5
8355 * #=> [1, 2, 3, 4, 5]
8357 * Another sometimes useful iterator is #reverse_each which will iterate over
8358 * the elements in the array in reverse order.
8360 * words = %w[first second third fourth fifth sixth]
8361 * str = ""
8362 * words.reverse_each {|word| str += "#{word} "}
8363 * p str #=> "sixth fifth fourth third second first "
8365 * The #map method can be used to create a new array based on the original
8366 * array, but with the values modified by the supplied block:
8368 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8369 * arr #=> [1, 2, 3, 4, 5]
8370 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8371 * arr #=> [1, 4, 9, 16, 25]
8374 * == Selecting Items from an +Array+
8376 * Elements can be selected from an array according to criteria defined in a
8377 * block. The selection can happen in a destructive or a non-destructive
8378 * manner. While the destructive operations will modify the array they were
8379 * called on, the non-destructive methods usually return a new array with the
8380 * selected elements, but leave the original array unchanged.
8382 * === Non-destructive Selection
8384 * arr = [1, 2, 3, 4, 5, 6]
8385 * arr.select {|a| a > 3} #=> [4, 5, 6]
8386 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8387 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8388 * arr #=> [1, 2, 3, 4, 5, 6]
8390 * === Destructive Selection
8392 * #select! and #reject! are the corresponding destructive methods to #select
8393 * and #reject
8395 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8396 * opposite result when supplied with the same block:
8398 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8399 * arr #=> [4, 5, 6]
8401 * arr = [1, 2, 3, 4, 5, 6]
8402 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8403 * arr #=> [1, 2, 3]
8405 * == What's Here
8407 * First, what's elsewhere. \Class +Array+:
8409 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8410 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8411 * which provides dozens of additional methods.
8413 * Here, class +Array+ provides methods that are useful for:
8415 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8416 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8417 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8418 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8419 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8420 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8421 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8422 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8423 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8424 * - {And more....}[rdoc-ref:Array@Other+Methods]
8426 * === Methods for Creating an +Array+
8428 * - ::[]: Returns a new array populated with given objects.
8429 * - ::new: Returns a new array.
8430 * - ::try_convert: Returns a new array created from a given object.
8432 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8434 * === Methods for Querying
8436 * - #length (aliased as #size): Returns the count of elements.
8437 * - #include?: Returns whether any element <tt>==</tt> a given object.
8438 * - #empty?: Returns whether there are no elements.
8439 * - #all?: Returns whether all elements meet a given criterion.
8440 * - #any?: Returns whether any element meets a given criterion.
8441 * - #none?: Returns whether no element <tt>==</tt> a given object.
8442 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8443 * - #count: Returns the count of elements that meet a given criterion.
8444 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8445 * - #rindex: Returns the index of the last element that meets a given criterion.
8446 * - #hash: Returns the integer hash code.
8448 * === Methods for Comparing
8450 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or
8451 * greater than a given object.
8452 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
8453 * in a given object.
8454 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8455 * element in a given object.
8457 * === Methods for Fetching
8459 * These methods do not modify +self+.
8461 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8462 * - #fetch: Returns the element at a given offset.
8463 * - #fetch_values: Returns elements at given offsets.
8464 * - #first: Returns one or more leading elements.
8465 * - #last: Returns one or more trailing elements.
8466 * - #max: Returns one or more maximum-valued elements,
8467 * as determined by <tt>#<=></tt> or a given block.
8468 * - #min: Returns one or more minimum-valued elements,
8469 * as determined by <tt>#<=></tt> or a given block.
8470 * - #minmax: Returns the minimum-valued and maximum-valued elements,
8471 * as determined by <tt>#<=></tt> or a given block.
8472 * - #assoc: Returns the first element that is an array
8473 * whose first element <tt>==</tt> a given object.
8474 * - #rassoc: Returns the first element that is an array
8475 * whose second element <tt>==</tt> a given object.
8476 * - #at: Returns the element at a given offset.
8477 * - #values_at: Returns the elements at given offsets.
8478 * - #dig: Returns the object in nested objects
8479 * that is specified by a given index and additional arguments.
8480 * - #drop: Returns trailing elements as determined by a given index.
8481 * - #take: Returns leading elements as determined by a given index.
8482 * - #drop_while: Returns trailing elements as determined by a given block.
8483 * - #take_while: Returns leading elements as determined by a given block.
8484 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8485 * - #reverse: Returns all elements in reverse order.
8486 * - #compact: Returns an array containing all non-+nil+ elements.
8487 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8488 * - #uniq: Returns an array containing non-duplicate elements.
8489 * - #rotate: Returns all elements with some rotated from one end to the other.
8490 * - #bsearch: Returns an element selected via a binary search
8491 * as determined by a given block.
8492 * - #bsearch_index: Returns the index of an element selected via a binary search
8493 * as determined by a given block.
8494 * - #sample: Returns one or more random elements.
8495 * - #shuffle: Returns elements in a random order.
8496 * - #reject: Returns an array containing elements not rejected by a given block.
8498 * === Methods for Assigning
8500 * These methods add, replace, or reorder elements in +self+.
8502 * - #[]=: Assigns specified elements with a given object.
8503 * - #<<: Appends an element.
8504 * - #push (aliased as #append): Appends elements.
8505 * - #unshift (aliased as #prepend): Prepends leading elements.
8506 * - #insert: Inserts given objects at a given offset; does not replace elements.
8507 * - #concat: Appends all elements from given arrays.
8508 * - #fill: Replaces specified elements with specified objects.
8509 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8510 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8511 * - #reverse!: Replaces +self+ with its elements reversed.
8512 * - #rotate!: Replaces +self+ with its elements rotated.
8513 * - #shuffle!: Replaces +self+ with its elements in random order.
8514 * - #sort!: Replaces +self+ with its elements sorted,
8515 * as determined by <tt>#<=></tt> or a given block.
8516 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8518 * === Methods for Deleting
8520 * Each of these methods removes elements from +self+:
8522 * - #pop: Removes and returns the last element.
8523 * - #shift: Removes and returns the first element.
8524 * - #compact!: Removes all +nil+ elements.
8525 * - #delete: Removes elements equal to a given object.
8526 * - #delete_at: Removes the element at a given offset.
8527 * - #delete_if: Removes elements specified by a given block.
8528 * - #clear: Removes all elements.
8529 * - #keep_if: Removes elements not specified by a given block.
8530 * - #reject!: Removes elements specified by a given block.
8531 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8532 * - #slice!: Removes and returns a sequence of elements.
8533 * - #uniq!: Removes duplicates.
8535 * === Methods for Combining
8537 * - #&: Returns an array containing elements found both in +self+ and a given array.
8538 * - #intersection: Returns an array containing elements found both in +self+
8539 * and in each given array.
8540 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8541 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8542 * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
8543 * duplicates removed.
8544 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
8545 * duplicates removed.
8546 * - #difference: Returns an array containing all elements of +self+ that are not found
8547 * in any of the given arrays..
8548 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8549 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8551 * === Methods for Iterating
8553 * - #each: Passes each element to a given block.
8554 * - #reverse_each: Passes each element, in reverse order, to a given block.
8555 * - #each_index: Passes each element index to a given block.
8556 * - #cycle: Calls a given block with each element, then does so again,
8557 * for a specified number of times, or forever.
8558 * - #combination: Calls a given block with combinations of elements of +self+;
8559 * a combination does not use the same element more than once.
8560 * - #permutation: Calls a given block with permutations of elements of +self+;
8561 * a permutation does not use the same element more than once.
8562 * - #repeated_combination: Calls a given block with combinations of elements of +self+;
8563 * a combination may use the same element more than once.
8564 * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
8565 * a permutation may use the same element more than once.
8567 * === Methods for Converting
8569 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8570 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8571 * - #flatten: Returns an array that is a recursive flattening of +self+.
8572 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8573 * - #join: Returns a newsString containing the elements joined by the field separator.
8574 * - #to_a: Returns +self+ or a new array containing all elements.
8575 * - #to_ary: Returns +self+.
8576 * - #to_h: Returns a new hash formed from the elements.
8577 * - #transpose: Transposes +self+, which must be an array of arrays.
8578 * - #zip: Returns a new array of arrays containing +self+ and given arrays;
8579 * follow the link for details.
8581 * === Other Methods
8583 * - #*: Returns one of the following:
8585 * - With integer argument +n+, a new array that is the concatenation
8586 * of +n+ copies of +self+.
8587 * - With string argument +field_separator+, a new string that is equivalent to
8588 * <tt>join(field_separator)</tt>.
8590 * - #pack: Packs the elements into a binary sequence.
8591 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8594 void
8595 Init_Array(void)
8597 fake_ary_flags = init_fake_ary_flags();
8599 rb_cArray = rb_define_class("Array", rb_cObject);
8600 rb_include_module(rb_cArray, rb_mEnumerable);
8602 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8603 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
8604 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8605 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8606 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8607 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8609 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
8610 rb_define_alias(rb_cArray, "to_s", "inspect");
8611 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
8612 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
8613 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
8615 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
8616 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
8617 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
8619 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
8620 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
8621 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
8622 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8623 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
8624 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
8625 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
8626 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
8627 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
8628 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
8629 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
8630 rb_define_alias(rb_cArray, "append", "push");
8631 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
8632 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
8633 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
8634 rb_define_alias(rb_cArray, "prepend", "unshift");
8635 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
8636 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
8637 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
8638 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
8639 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
8640 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
8641 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
8642 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
8643 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
8644 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
8645 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
8646 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
8647 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
8648 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
8649 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
8650 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
8651 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
8652 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
8653 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
8654 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
8655 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8656 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
8657 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8658 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
8659 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
8660 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
8661 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
8662 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
8663 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
8664 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
8665 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
8666 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
8667 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
8668 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
8669 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
8670 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
8671 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
8672 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
8673 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
8675 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
8676 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
8678 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
8679 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
8681 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
8682 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
8684 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
8685 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
8686 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
8688 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
8689 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
8690 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
8692 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
8693 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
8694 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
8695 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
8696 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
8697 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
8698 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
8699 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
8700 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
8701 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
8702 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
8703 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
8704 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
8706 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
8707 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
8708 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
8709 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
8710 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
8711 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
8712 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
8713 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
8714 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
8715 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
8716 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
8717 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
8718 rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
8720 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
8722 rb_cArray_empty_frozen = rb_ary_freeze(rb_ary_new());
8723 rb_vm_register_global_object(rb_cArray_empty_frozen);
8726 #include "array.rbinc"