[DOC] Tweaks for Array#fetch (#11602)
[ruby.git] / array.c
blob059d6911ee7cd35ce3af91c3df85e2bf3d61583a
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 * array.freeze -> self
634 * Freezes +self+; returns +self+:
636 * a = []
637 * a.frozen? # => false
638 * a.freeze
639 * a.frozen? # => true
641 * An attempt to modify a frozen +Array+ raises FrozenError.
644 VALUE
645 rb_ary_freeze(VALUE ary)
647 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
649 if (OBJ_FROZEN(ary)) return ary;
651 if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) {
652 ary_shrink_capa(ary);
655 return rb_obj_freeze(ary);
658 /* This can be used to take a snapshot of an array (with
659 e.g. rb_ary_replace) and check later whether the array has been
660 modified from the snapshot. The snapshot is cheap, though if
661 something does modify the array it will pay the cost of copying
662 it. If Array#pop or Array#shift has been called, the array will
663 be still shared with the snapshot, but the array length will
664 differ. */
665 VALUE
666 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
668 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
669 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
670 ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
671 ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
672 return Qtrue;
674 return Qfalse;
677 static VALUE
678 ary_alloc_embed(VALUE klass, long capa)
680 size_t size = ary_embed_size(capa);
681 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
682 NEWOBJ_OF(ary, struct RArray, klass,
683 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
684 size, 0);
685 /* Created array is:
686 * FL_SET_EMBED((VALUE)ary);
687 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
689 return (VALUE)ary;
692 static VALUE
693 ary_alloc_heap(VALUE klass)
695 NEWOBJ_OF(ary, struct RArray, klass,
696 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
697 sizeof(struct RArray), 0);
698 return (VALUE)ary;
701 static VALUE
702 empty_ary_alloc(VALUE klass)
704 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
705 return ary_alloc_embed(klass, 0);
708 static VALUE
709 ary_new(VALUE klass, long capa)
711 VALUE ary;
713 if (capa < 0) {
714 rb_raise(rb_eArgError, "negative array size (or size too big)");
716 if (capa > ARY_MAX_SIZE) {
717 rb_raise(rb_eArgError, "array size too big");
720 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
722 if (ary_embeddable_p(capa)) {
723 ary = ary_alloc_embed(klass, capa);
725 else {
726 ary = ary_alloc_heap(klass);
727 ARY_SET_CAPA(ary, capa);
728 RUBY_ASSERT(!ARY_EMBED_P(ary));
730 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
731 ARY_SET_HEAP_LEN(ary, 0);
734 return ary;
737 VALUE
738 rb_ary_new_capa(long capa)
740 return ary_new(rb_cArray, capa);
743 VALUE
744 rb_ary_new(void)
746 return rb_ary_new_capa(0);
749 VALUE
750 (rb_ary_new_from_args)(long n, ...)
752 va_list ar;
753 VALUE ary;
754 long i;
756 ary = rb_ary_new2(n);
758 va_start(ar, n);
759 for (i=0; i<n; i++) {
760 ARY_SET(ary, i, va_arg(ar, VALUE));
762 va_end(ar);
764 ARY_SET_LEN(ary, n);
765 return ary;
768 VALUE
769 rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
771 VALUE ary;
773 ary = ary_new(klass, n);
774 if (n > 0 && elts) {
775 ary_memcpy(ary, 0, n, elts);
776 ARY_SET_LEN(ary, n);
779 return ary;
782 VALUE
783 rb_ary_new_from_values(long n, const VALUE *elts)
785 return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
788 static VALUE
789 ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
791 size_t size = ary_embed_size(capa);
792 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
793 NEWOBJ_OF(ary, struct RArray, klass,
794 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
795 size, ec);
796 /* Created array is:
797 * FL_SET_EMBED((VALUE)ary);
798 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
800 return (VALUE)ary;
803 static VALUE
804 ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
806 NEWOBJ_OF(ary, struct RArray, klass,
807 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
808 sizeof(struct RArray), ec);
809 return (VALUE)ary;
812 static VALUE
813 ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
815 VALUE ary;
817 if (capa < 0) {
818 rb_raise(rb_eArgError, "negative array size (or size too big)");
820 if (capa > ARY_MAX_SIZE) {
821 rb_raise(rb_eArgError, "array size too big");
824 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
826 if (ary_embeddable_p(capa)) {
827 ary = ec_ary_alloc_embed(ec, klass, capa);
829 else {
830 ary = ec_ary_alloc_heap(ec, klass);
831 ARY_SET_CAPA(ary, capa);
832 RUBY_ASSERT(!ARY_EMBED_P(ary));
834 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
835 ARY_SET_HEAP_LEN(ary, 0);
838 return ary;
841 VALUE
842 rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
844 VALUE ary;
846 ary = ec_ary_new(ec, rb_cArray, n);
847 if (n > 0 && elts) {
848 ary_memcpy(ary, 0, n, elts);
849 ARY_SET_LEN(ary, n);
852 return ary;
855 VALUE
856 rb_ary_hidden_new(long capa)
858 VALUE ary = ary_new(0, capa);
859 return ary;
862 VALUE
863 rb_ary_hidden_new_fill(long capa)
865 VALUE ary = rb_ary_hidden_new(capa);
866 ary_memfill(ary, 0, capa, Qnil);
867 ARY_SET_LEN(ary, capa);
868 return ary;
871 void
872 rb_ary_free(VALUE ary)
874 if (ARY_OWNS_HEAP_P(ary)) {
875 if (USE_DEBUG_COUNTER &&
876 !ARY_SHARED_ROOT_P(ary) &&
877 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
878 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
881 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
882 ary_heap_free(ary);
884 else {
885 RB_DEBUG_COUNTER_INC(obj_ary_embed);
888 if (ARY_SHARED_P(ary)) {
889 RB_DEBUG_COUNTER_INC(obj_ary_shared);
891 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
892 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
896 static VALUE fake_ary_flags;
898 static VALUE
899 init_fake_ary_flags(void)
901 struct RArray fake_ary = {0};
902 fake_ary.basic.flags = T_ARRAY;
903 VALUE ary = (VALUE)&fake_ary;
904 rb_ary_freeze(ary);
905 return fake_ary.basic.flags;
908 VALUE
909 rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len)
911 fake_ary->basic.flags = fake_ary_flags;
912 RBASIC_CLEAR_CLASS((VALUE)fake_ary);
914 // bypass frozen checks
915 fake_ary->as.heap.ptr = list;
916 fake_ary->as.heap.len = len;
917 fake_ary->as.heap.aux.capa = len;
918 return (VALUE)fake_ary;
921 size_t
922 rb_ary_memsize(VALUE ary)
924 if (ARY_OWNS_HEAP_P(ary)) {
925 return ARY_CAPA(ary) * sizeof(VALUE);
927 else {
928 return 0;
932 static VALUE
933 ary_make_shared(VALUE ary)
935 ary_verify(ary);
937 if (ARY_SHARED_P(ary)) {
938 return ARY_SHARED_ROOT(ary);
940 else if (ARY_SHARED_ROOT_P(ary)) {
941 return ary;
943 else if (OBJ_FROZEN(ary)) {
944 return ary;
946 else {
947 long capa = ARY_CAPA(ary);
948 long len = RARRAY_LEN(ary);
950 /* Shared roots cannot be embedded because the reference count
951 * (refcnt) is stored in as.heap.aux.capa. */
952 VALUE shared = ary_alloc_heap(0);
953 FL_SET_SHARED_ROOT(shared);
955 if (ARY_EMBED_P(ary)) {
956 VALUE *ptr = ary_heap_alloc_buffer(capa);
957 ARY_SET_PTR(shared, ptr);
958 ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary));
960 FL_UNSET_EMBED(ary);
961 ARY_SET_HEAP_LEN(ary, len);
962 ARY_SET_PTR(ary, ptr);
964 else {
965 ARY_SET_PTR(shared, RARRAY_CONST_PTR(ary));
968 ARY_SET_LEN(shared, capa);
969 ary_mem_clear(shared, len, capa - len);
970 rb_ary_set_shared(ary, shared);
972 ary_verify(shared);
973 ary_verify(ary);
975 return shared;
979 static VALUE
980 ary_make_substitution(VALUE ary)
982 long len = RARRAY_LEN(ary);
984 if (ary_embeddable_p(len)) {
985 VALUE subst = rb_ary_new_capa(len);
986 RUBY_ASSERT(ARY_EMBED_P(subst));
988 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
989 ARY_SET_EMBED_LEN(subst, len);
990 return subst;
992 else {
993 return rb_ary_increment_share(ary_make_shared(ary));
997 VALUE
998 rb_assoc_new(VALUE car, VALUE cdr)
1000 return rb_ary_new3(2, car, cdr);
1003 VALUE
1004 rb_to_array_type(VALUE ary)
1006 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1008 #define to_ary rb_to_array_type
1010 VALUE
1011 rb_check_array_type(VALUE ary)
1013 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1016 VALUE
1017 rb_check_to_array(VALUE ary)
1019 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1022 VALUE
1023 rb_to_array(VALUE ary)
1025 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1029 * call-seq:
1030 * Array.try_convert(object) -> object, new_array, or nil
1032 * Attempts to return an array, based on the given +object+.
1034 * If +object+ is an array, returns +object+.
1036 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1037 * calls <tt>object.to_ary</tt>:
1038 * if the return value is an array or +nil+, returns that value;
1039 * if not, raises TypeError.
1041 * Otherwise returns +nil+.
1043 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1046 static VALUE
1047 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
1049 return rb_check_array_type(ary);
1052 /* :nodoc: */
1053 static VALUE
1054 rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
1056 VALUE ary;
1058 if (klass == rb_cArray) {
1059 long size = 0;
1060 if (argc > 0 && FIXNUM_P(argv[0])) {
1061 size = FIX2LONG(argv[0]);
1062 if (size < 0) size = 0;
1065 ary = ary_new(klass, size);
1067 rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
1069 else {
1070 ary = rb_class_new_instance_pass_kw(argc, argv, klass);
1073 return ary;
1077 * call-seq:
1078 * Array.new -> new_empty_array
1079 * Array.new(array) -> new_array
1080 * Array.new(size, default_value = nil) -> new_array
1081 * Array.new(size = 0) {|index| ... } -> new_array
1083 * Returns a new array.
1085 * With no block and no argument given, returns a new empty array:
1087 * Array.new # => []
1089 * With no block and array argument given, returns a new array with the same elements:
1091 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1093 * With no block and integer argument given, returns a new array containing
1094 * that many instances of the given +default_value+:
1096 * Array.new(0) # => []
1097 * Array.new(3) # => [nil, nil, nil]
1098 * Array.new(2, 3) # => [3, 3]
1100 * With a block given, returns an array of the given +size+;
1101 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1102 * the element at that +index+ in the returned array is the blocks return value:
1104 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1106 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1108 * array = Array.new(2, {})
1109 * array # => [{}, {}]
1110 * array[0][:a] = 1
1111 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1113 * If you want the elements of the array to be distinct, you should pass a block:
1115 * array = Array.new(2) { {} }
1116 * array # => [{}, {}]
1117 * array[0][:a] = 1
1118 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1120 * Raises TypeError if the first argument is not either an array
1121 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1122 * Raises ArgumentError if the first argument is a negative integer.
1124 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1127 static VALUE
1128 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1130 long len;
1131 VALUE size, val;
1133 rb_ary_modify(ary);
1134 if (argc == 0) {
1135 rb_ary_reset(ary);
1136 RUBY_ASSERT(ARY_EMBED_P(ary));
1137 RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
1138 if (rb_block_given_p()) {
1139 rb_warning("given block not used");
1141 return ary;
1143 rb_scan_args(argc, argv, "02", &size, &val);
1144 if (argc == 1 && !FIXNUM_P(size)) {
1145 val = rb_check_array_type(size);
1146 if (!NIL_P(val)) {
1147 rb_ary_replace(ary, val);
1148 return ary;
1152 len = NUM2LONG(size);
1153 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1154 if (len < 0) {
1155 rb_raise(rb_eArgError, "negative array size");
1157 if (len > ARY_MAX_SIZE) {
1158 rb_raise(rb_eArgError, "array size too big");
1160 /* recheck after argument conversion */
1161 rb_ary_modify(ary);
1162 ary_resize_capa(ary, len);
1163 if (rb_block_given_p()) {
1164 long i;
1166 if (argc == 2) {
1167 rb_warn("block supersedes default value argument");
1169 for (i=0; i<len; i++) {
1170 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
1171 ARY_SET_LEN(ary, i + 1);
1174 else {
1175 ary_memfill(ary, 0, len, val);
1176 ARY_SET_LEN(ary, len);
1178 return ary;
1182 * Returns a new array, populated with the given objects:
1184 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1185 * Array[] # => []
1186 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1188 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1191 static VALUE
1192 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1194 VALUE ary = ary_new(klass, argc);
1195 if (argc > 0 && argv) {
1196 ary_memcpy(ary, 0, argc, argv);
1197 ARY_SET_LEN(ary, argc);
1200 return ary;
1203 void
1204 rb_ary_store(VALUE ary, long idx, VALUE val)
1206 long len = RARRAY_LEN(ary);
1208 if (idx < 0) {
1209 idx += len;
1210 if (idx < 0) {
1211 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1212 idx - len, -len);
1215 else if (idx >= ARY_MAX_SIZE) {
1216 rb_raise(rb_eIndexError, "index %ld too big", idx);
1219 rb_ary_modify(ary);
1220 if (idx >= ARY_CAPA(ary)) {
1221 ary_double_capa(ary, idx);
1223 if (idx > len) {
1224 ary_mem_clear(ary, len, idx - len + 1);
1227 if (idx >= len) {
1228 ARY_SET_LEN(ary, idx + 1);
1230 ARY_SET(ary, idx, val);
1233 static VALUE
1234 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1236 RUBY_ASSERT(offset >= 0);
1237 RUBY_ASSERT(len >= 0);
1238 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1240 VALUE result = ary_alloc_heap(klass);
1241 size_t embed_capa = ary_embed_capa(result);
1242 if ((size_t)len <= embed_capa) {
1243 FL_SET_EMBED(result);
1244 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
1245 ARY_SET_EMBED_LEN(result, len);
1247 else {
1248 VALUE shared = ary_make_shared(ary);
1250 /* The ary_make_shared call may allocate, which can trigger a GC
1251 * compaction. This can cause the array to be embedded because it has
1252 * a length of 0. */
1253 FL_UNSET_EMBED(result);
1255 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
1256 ARY_SET_LEN(result, RARRAY_LEN(ary));
1257 rb_ary_set_shared(result, shared);
1259 ARY_INCREASE_PTR(result, offset);
1260 ARY_SET_LEN(result, len);
1262 ary_verify(shared);
1265 ary_verify(result);
1266 return result;
1269 static VALUE
1270 ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
1272 RUBY_ASSERT(offset >= 0);
1273 RUBY_ASSERT(len >= 0);
1274 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1275 RUBY_ASSERT(step != 0);
1277 const long orig_len = len;
1279 if (step > 0 && step >= len) {
1280 VALUE result = ary_new(klass, 1);
1281 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1282 const VALUE *values = RARRAY_CONST_PTR(ary);
1284 RB_OBJ_WRITE(result, ptr, values[offset]);
1285 ARY_SET_EMBED_LEN(result, 1);
1286 return result;
1288 else if (step < 0 && step < -len) {
1289 step = -len;
1292 long ustep = (step < 0) ? -step : step;
1293 len = roomof(len, ustep);
1295 long i;
1296 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1298 VALUE result = ary_new(klass, len);
1299 if (ARY_EMBED_P(result)) {
1300 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1301 const VALUE *values = RARRAY_CONST_PTR(ary);
1303 for (i = 0; i < len; ++i) {
1304 RB_OBJ_WRITE(result, ptr+i, values[j]);
1305 j += step;
1307 ARY_SET_EMBED_LEN(result, len);
1309 else {
1310 const VALUE *values = RARRAY_CONST_PTR(ary);
1312 RARRAY_PTR_USE(result, ptr, {
1313 for (i = 0; i < len; ++i) {
1314 RB_OBJ_WRITE(result, ptr+i, values[j]);
1315 j += step;
1318 ARY_SET_LEN(result, len);
1321 return result;
1324 static VALUE
1325 ary_make_shared_copy(VALUE ary)
1327 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
1330 enum ary_take_pos_flags
1332 ARY_TAKE_FIRST = 0,
1333 ARY_TAKE_LAST = 1
1336 static VALUE
1337 ary_take_first_or_last_n(VALUE ary, long n, enum ary_take_pos_flags last)
1339 long len = RARRAY_LEN(ary);
1340 long offset = 0;
1342 if (n > len) {
1343 n = len;
1345 else if (n < 0) {
1346 rb_raise(rb_eArgError, "negative array size");
1348 if (last) {
1349 offset = len - n;
1351 return ary_make_partial(ary, rb_cArray, offset, n);
1354 static VALUE
1355 ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1357 argc = rb_check_arity(argc, 0, 1);
1358 /* the case optional argument is omitted should be handled in
1359 * callers of this function. if another arity case is added,
1360 * this arity check needs to rewrite. */
1361 RUBY_ASSERT_ALWAYS(argc == 1);
1362 return ary_take_first_or_last_n(ary, NUM2LONG(argv[0]), last);
1366 * call-seq:
1367 * self << object -> self
1369 * Appends +object+ as the last element in +self+; returns +self+:
1371 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1373 * Appends +object+ as a single element, even if it is another array:
1375 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1377 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1380 VALUE
1381 rb_ary_push(VALUE ary, VALUE item)
1383 long idx = RARRAY_LEN((ary_verify(ary), ary));
1384 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1385 RARRAY_PTR_USE(ary, ptr, {
1386 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1388 ARY_SET_LEN(ary, idx + 1);
1389 ary_verify(ary);
1390 return ary;
1393 VALUE
1394 rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1396 long oldlen = RARRAY_LEN(ary);
1397 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1398 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1399 ARY_SET_LEN(ary, oldlen + len);
1400 return ary;
1404 * call-seq:
1405 * push(*objects) -> self
1406 * append(*objects) -> self
1408 * Appends each argument in +objects+ to +self+; returns +self+:
1410 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1411 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1413 * Appends each argument as a single element, even if it is another array:
1415 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1416 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1418 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1421 static VALUE
1422 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1424 return rb_ary_cat(ary, argv, argc);
1427 VALUE
1428 rb_ary_pop(VALUE ary)
1430 long n;
1431 rb_ary_modify_check(ary);
1432 n = RARRAY_LEN(ary);
1433 if (n == 0) return Qnil;
1434 if (ARY_OWNS_HEAP_P(ary) &&
1435 n * 3 < ARY_CAPA(ary) &&
1436 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1438 ary_resize_capa(ary, n * 2);
1440 --n;
1441 ARY_SET_LEN(ary, n);
1442 ary_verify(ary);
1443 return RARRAY_AREF(ary, n);
1447 * call-seq:
1448 * array.pop -> object or nil
1449 * array.pop(n) -> new_array
1451 * Removes and returns trailing elements.
1453 * When no argument is given and +self+ is not empty,
1454 * removes and returns the last element:
1456 * a = [:foo, 'bar', 2]
1457 * a.pop # => 2
1458 * a # => [:foo, "bar"]
1460 * Returns +nil+ if the array is empty.
1462 * When a non-negative Integer argument +n+ is given and is in range,
1464 * removes and returns the last +n+ elements in a new +Array+:
1465 * a = [:foo, 'bar', 2]
1466 * a.pop(2) # => ["bar", 2]
1468 * If +n+ is positive and out of range,
1469 * removes and returns all elements:
1471 * a = [:foo, 'bar', 2]
1472 * a.pop(50) # => [:foo, "bar", 2]
1474 * Related: #push, #shift, #unshift.
1477 static VALUE
1478 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1480 VALUE result;
1482 if (argc == 0) {
1483 return rb_ary_pop(ary);
1486 rb_ary_modify_check(ary);
1487 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1488 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1489 ary_verify(ary);
1490 return result;
1493 VALUE
1494 rb_ary_shift(VALUE ary)
1496 VALUE top;
1497 long len = RARRAY_LEN(ary);
1499 if (len == 0) {
1500 rb_ary_modify_check(ary);
1501 return Qnil;
1504 top = RARRAY_AREF(ary, 0);
1506 rb_ary_behead(ary, 1);
1508 return top;
1512 * call-seq:
1513 * array.shift -> object or nil
1514 * array.shift(n) -> new_array
1516 * Removes and returns leading elements.
1518 * When no argument is given, removes and returns the first element:
1520 * a = [:foo, 'bar', 2]
1521 * a.shift # => :foo
1522 * a # => ['bar', 2]
1524 * Returns +nil+ if +self+ is empty.
1526 * When positive Integer argument +n+ is given, removes the first +n+ elements;
1527 * returns those elements in a new +Array+:
1529 * a = [:foo, 'bar', 2]
1530 * a.shift(2) # => [:foo, 'bar']
1531 * a # => [2]
1533 * If +n+ is as large as or larger than <tt>self.length</tt>,
1534 * removes all elements; returns those elements in a new +Array+:
1536 * a = [:foo, 'bar', 2]
1537 * a.shift(3) # => [:foo, 'bar', 2]
1539 * If +n+ is zero, returns a new empty +Array+; +self+ is unmodified.
1541 * Related: #push, #pop, #unshift.
1544 static VALUE
1545 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1547 VALUE result;
1548 long n;
1550 if (argc == 0) {
1551 return rb_ary_shift(ary);
1554 rb_ary_modify_check(ary);
1555 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1556 n = RARRAY_LEN(result);
1557 rb_ary_behead(ary,n);
1559 return result;
1562 VALUE
1563 rb_ary_behead(VALUE ary, long n)
1565 if (n <= 0) {
1566 return ary;
1569 rb_ary_modify_check(ary);
1571 if (!ARY_SHARED_P(ary)) {
1572 if (ARY_EMBED_P(ary) || RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
1573 RARRAY_PTR_USE(ary, ptr, {
1574 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary) - n);
1575 }); /* WB: no new reference */
1576 ARY_INCREASE_LEN(ary, -n);
1577 ary_verify(ary);
1578 return ary;
1581 ary_mem_clear(ary, 0, n);
1582 ary_make_shared(ary);
1584 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1585 ary_mem_clear(ary, 0, n);
1588 ARY_INCREASE_PTR(ary, n);
1589 ARY_INCREASE_LEN(ary, -n);
1590 ary_verify(ary);
1592 return ary;
1595 static VALUE
1596 make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
1598 if (head - sharedp < argc) {
1599 long room = capa - len - argc;
1601 room -= room >> 4;
1602 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1603 head = sharedp + argc + room;
1605 ARY_SET_PTR(ary, head - argc);
1606 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1608 ary_verify(ary);
1609 return ARY_SHARED_ROOT(ary);
1612 static VALUE
1613 ary_modify_for_unshift(VALUE ary, int argc)
1615 long len = RARRAY_LEN(ary);
1616 long new_len = len + argc;
1617 long capa;
1618 const VALUE *head, *sharedp;
1620 rb_ary_modify(ary);
1621 capa = ARY_CAPA(ary);
1622 if (capa - (capa >> 6) <= new_len) {
1623 ary_double_capa(ary, new_len);
1626 /* use shared array for big "queues" */
1627 if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
1628 ary_verify(ary);
1630 /* make a room for unshifted items */
1631 capa = ARY_CAPA(ary);
1632 ary_make_shared(ary);
1634 head = sharedp = RARRAY_CONST_PTR(ary);
1635 return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
1637 else {
1638 /* sliding items */
1639 RARRAY_PTR_USE(ary, ptr, {
1640 MEMMOVE(ptr + argc, ptr, VALUE, len);
1643 ary_verify(ary);
1644 return ary;
1648 static VALUE
1649 ary_ensure_room_for_unshift(VALUE ary, int argc)
1651 long len = RARRAY_LEN(ary);
1652 long new_len = len + argc;
1654 if (len > ARY_MAX_SIZE - argc) {
1655 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1657 else if (! ARY_SHARED_P(ary)) {
1658 return ary_modify_for_unshift(ary, argc);
1660 else {
1661 VALUE shared_root = ARY_SHARED_ROOT(ary);
1662 long capa = RARRAY_LEN(shared_root);
1664 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1665 return ary_modify_for_unshift(ary, argc);
1667 else if (new_len > capa) {
1668 return ary_modify_for_unshift(ary, argc);
1670 else {
1671 const VALUE * head = RARRAY_CONST_PTR(ary);
1672 void *sharedp = (void *)RARRAY_CONST_PTR(shared_root);
1674 rb_ary_modify_check(ary);
1675 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1681 * call-seq:
1682 * array.unshift(*objects) -> self
1684 * Prepends the given +objects+ to +self+:
1686 * a = [:foo, 'bar', 2]
1687 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1689 * Related: #push, #pop, #shift.
1692 VALUE
1693 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1695 long len = RARRAY_LEN(ary);
1696 VALUE target_ary;
1698 if (argc == 0) {
1699 rb_ary_modify_check(ary);
1700 return ary;
1703 target_ary = ary_ensure_room_for_unshift(ary, argc);
1704 ary_memcpy0(ary, 0, argc, argv, target_ary);
1705 ARY_SET_LEN(ary, len + argc);
1706 return ary;
1709 VALUE
1710 rb_ary_unshift(VALUE ary, VALUE item)
1712 return rb_ary_unshift_m(1, &item, ary);
1715 /* faster version - use this if you don't need to treat negative offset */
1716 static inline VALUE
1717 rb_ary_elt(VALUE ary, long offset)
1719 long len = RARRAY_LEN(ary);
1720 if (len == 0) return Qnil;
1721 if (offset < 0 || len <= offset) {
1722 return Qnil;
1724 return RARRAY_AREF(ary, offset);
1727 VALUE
1728 rb_ary_entry(VALUE ary, long offset)
1730 return rb_ary_entry_internal(ary, offset);
1733 VALUE
1734 rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
1736 VALUE klass;
1737 long alen = RARRAY_LEN(ary);
1739 if (beg > alen) return Qnil;
1740 if (beg < 0 || len < 0) return Qnil;
1742 if (alen < len || alen < beg + len) {
1743 len = alen - beg;
1745 klass = rb_cArray;
1746 if (len == 0) return ary_new(klass, 0);
1747 if (step == 0)
1748 rb_raise(rb_eArgError, "slice step cannot be zero");
1749 if (step == 1)
1750 return ary_make_partial(ary, klass, beg, len);
1751 else
1752 return ary_make_partial_step(ary, klass, beg, len, step);
1755 VALUE
1756 rb_ary_subseq(VALUE ary, long beg, long len)
1758 return rb_ary_subseq_step(ary, beg, len, 1);
1761 static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1764 * call-seq:
1765 * self[index] -> object or nil
1766 * self[start, length] -> object or nil
1767 * self[range] -> object or nil
1768 * self[aseq] -> object or nil
1769 * slice(index) -> object or nil
1770 * slice(start, length) -> object or nil
1771 * slice(range) -> object or nil
1772 * slice(aseq) -> object or nil
1774 * Returns elements from +self+; does not modify +self+.
1776 * In brief:
1778 * a = [:foo, 'bar', 2]
1780 * # Single argument index: returns one element.
1781 * a[0] # => :foo # Zero-based index.
1782 * a[-1] # => 2 # Negative index counts backwards from end.
1784 * # Arguments start and length: returns an array.
1785 * a[1, 2] # => ["bar", 2]
1786 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1788 * # Single argument range: returns an array.
1789 * a[0..1] # => [:foo, "bar"]
1790 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1791 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1793 * When a single integer argument +index+ is given, returns the element at offset +index+:
1795 * a = [:foo, 'bar', 2]
1796 * a[0] # => :foo
1797 * a[2] # => 2
1798 * a # => [:foo, "bar", 2]
1800 * If +index+ is negative, counts backwards from the end of +self+:
1802 * a = [:foo, 'bar', 2]
1803 * a[-1] # => 2
1804 * a[-2] # => "bar"
1806 * If +index+ is out of range, returns +nil+.
1808 * When two Integer arguments +start+ and +length+ are given,
1809 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1811 * a = [:foo, 'bar', 2]
1812 * a[0, 2] # => [:foo, "bar"]
1813 * a[1, 2] # => ["bar", 2]
1815 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1816 * returns all elements from offset +start+ to the end:
1818 * a = [:foo, 'bar', 2]
1819 * a[0, 4] # => [:foo, "bar", 2]
1820 * a[1, 3] # => ["bar", 2]
1821 * a[2, 2] # => [2]
1823 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1824 * returns a new empty +Array+.
1826 * If +length+ is negative, returns +nil+.
1828 * When a single Range argument +range+ is given,
1829 * treats <tt>range.min</tt> as +start+ above
1830 * and <tt>range.size</tt> as +length+ above:
1832 * a = [:foo, 'bar', 2]
1833 * a[0..1] # => [:foo, "bar"]
1834 * a[1..2] # => ["bar", 2]
1836 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1838 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1840 * a = [:foo, 'bar', 2]
1841 * a[0..-1] # => [:foo, "bar", 2]
1842 * a[0..-2] # => [:foo, "bar"]
1843 * a[0..-3] # => [:foo]
1845 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1847 * a = [:foo, 'bar', 2]
1848 * a[-1..2] # => [2]
1849 * a[-2..2] # => ["bar", 2]
1850 * a[-3..2] # => [:foo, "bar", 2]
1852 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1854 * a = [:foo, 'bar', 2]
1855 * a[4..1] # => nil
1856 * a[4..0] # => nil
1857 * a[4..-1] # => nil
1859 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1860 * returns an +Array+ of elements corresponding to the indexes produced by
1861 * the sequence.
1863 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1864 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1866 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1867 * is larger than array size, throws RangeError.
1869 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1870 * a[(1..11).step(2)]
1871 * # RangeError (((1..11).step(2)) out of range)
1872 * a[(7..).step(2)]
1873 * # RangeError (((7..).step(2)) out of range)
1875 * If given a single argument, and its type is not one of the listed, tries to
1876 * convert it to Integer, and raises if it is impossible:
1878 * a = [:foo, 'bar', 2]
1879 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1880 * a[:foo]
1882 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1885 VALUE
1886 rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
1888 rb_check_arity(argc, 1, 2);
1889 if (argc == 2) {
1890 return rb_ary_aref2(ary, argv[0], argv[1]);
1892 return rb_ary_aref1(ary, argv[0]);
1895 static VALUE
1896 rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1898 long beg = NUM2LONG(b);
1899 long len = NUM2LONG(e);
1900 if (beg < 0) {
1901 beg += RARRAY_LEN(ary);
1903 return rb_ary_subseq(ary, beg, len);
1906 VALUE
1907 rb_ary_aref1(VALUE ary, VALUE arg)
1909 long beg, len, step;
1911 /* special case - speeding up */
1912 if (FIXNUM_P(arg)) {
1913 return rb_ary_entry(ary, FIX2LONG(arg));
1915 /* check if idx is Range or ArithmeticSequence */
1916 switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
1917 case Qfalse:
1918 break;
1919 case Qnil:
1920 return Qnil;
1921 default:
1922 return rb_ary_subseq_step(ary, beg, len, step);
1925 return rb_ary_entry(ary, NUM2LONG(arg));
1929 * call-seq:
1930 * at(index) -> object or nil
1932 * Returns the element of +self+ specified by the given +index+
1933 * or +nil+ if there is no such element;
1934 * +index+ must be an
1935 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1937 * For non-negative +index+, returns the element of +self+ at offset +index+:
1939 * a = [:foo, 'bar', 2]
1940 * a.at(0) # => :foo
1941 * a.at(2) # => 2
1942 * a.at(2.0) # => 2
1944 * For negative +index+, counts backwards from the end of +self+:
1946 * a.at(-2) # => "bar"
1948 * Related: Array#[];
1949 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1952 VALUE
1953 rb_ary_at(VALUE ary, VALUE pos)
1955 return rb_ary_entry(ary, NUM2LONG(pos));
1958 #if 0
1959 static VALUE
1960 rb_ary_first(int argc, VALUE *argv, VALUE ary)
1962 if (argc == 0) {
1963 if (RARRAY_LEN(ary) == 0) return Qnil;
1964 return RARRAY_AREF(ary, 0);
1966 else {
1967 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1970 #endif
1972 static VALUE
1973 ary_first(VALUE self)
1975 return (RARRAY_LEN(self) == 0) ? Qnil : RARRAY_AREF(self, 0);
1978 static VALUE
1979 ary_last(VALUE self)
1981 long len = RARRAY_LEN(self);
1982 return (len == 0) ? Qnil : RARRAY_AREF(self, len-1);
1985 VALUE
1986 rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
1988 if (argc == 0) {
1989 return ary_last(ary);
1991 else {
1992 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1997 * call-seq:
1998 * fetch(index) -> element
1999 * fetch(index, default_value) -> element or default_value
2000 * fetch(index) {|index| ... } -> element or block_return_value
2002 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2003 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2005 * With the single argument +index+ and no block,
2006 * returns the element at offset +index+:
2008 * a = [:foo, 'bar', 2]
2009 * a.fetch(1) # => "bar"
2010 * a.fetch(1.1) # => "bar"
2012 * If +index+ is negative, counts from the end of the array:
2014 * a = [:foo, 'bar', 2]
2015 * a.fetch(-1) # => 2
2016 * a.fetch(-2) # => "bar"
2018 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2019 * returns +default_value+ if +index+ is out-of-range:
2021 * a = [:foo, 'bar', 2]
2022 * a.fetch(1, nil) # => "bar"
2023 * a.fetch(3, :foo) # => :foo
2025 * With argument +index+ and a block,
2026 * returns the element at offset +index+ if index is in range
2027 * (and the block is not called); otherwise calls the block with index and returns its return value:
2029 * a = [:foo, 'bar', 2]
2030 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2031 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2033 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2036 static VALUE
2037 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
2039 VALUE pos, ifnone;
2040 long block_given;
2041 long idx;
2043 rb_scan_args(argc, argv, "11", &pos, &ifnone);
2044 block_given = rb_block_given_p();
2045 if (block_given && argc == 2) {
2046 rb_warn("block supersedes default value argument");
2048 idx = NUM2LONG(pos);
2050 if (idx < 0) {
2051 idx += RARRAY_LEN(ary);
2053 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
2054 if (block_given) return rb_yield(pos);
2055 if (argc == 1) {
2056 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
2057 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
2059 return ifnone;
2061 return RARRAY_AREF(ary, idx);
2065 * call-seq:
2066 * array.index(object) -> integer or nil
2067 * array.index {|element| ... } -> integer or nil
2068 * array.index -> new_enumerator
2070 * Returns the index of a specified element.
2072 * When argument +object+ is given but no block,
2073 * returns the index of the first element +element+
2074 * for which <tt>object == element</tt>:
2076 * a = [:foo, 'bar', 2, 'bar']
2077 * a.index('bar') # => 1
2079 * Returns +nil+ if no such element found.
2081 * When both argument +object+ and a block are given,
2082 * calls the block with each successive element;
2083 * returns the index of the first element for which the block returns a truthy value:
2085 * a = [:foo, 'bar', 2, 'bar']
2086 * a.index {|element| element == 'bar' } # => 1
2088 * Returns +nil+ if the block never returns a truthy value.
2090 * When neither an argument nor a block is given, returns a new Enumerator:
2092 * a = [:foo, 'bar', 2]
2093 * e = a.index
2094 * e # => #<Enumerator: [:foo, "bar", 2]:index>
2095 * e.each {|element| element == 'bar' } # => 1
2097 * Related: #rindex.
2100 static VALUE
2101 rb_ary_index(int argc, VALUE *argv, VALUE ary)
2103 VALUE val;
2104 long i;
2106 if (argc == 0) {
2107 RETURN_ENUMERATOR(ary, 0, 0);
2108 for (i=0; i<RARRAY_LEN(ary); i++) {
2109 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2110 return LONG2NUM(i);
2113 return Qnil;
2115 rb_check_arity(argc, 0, 1);
2116 val = argv[0];
2117 if (rb_block_given_p())
2118 rb_warn("given block not used");
2119 for (i=0; i<RARRAY_LEN(ary); i++) {
2120 VALUE e = RARRAY_AREF(ary, i);
2121 if (rb_equal(e, val)) {
2122 return LONG2NUM(i);
2125 return Qnil;
2129 * call-seq:
2130 * array.rindex(object) -> integer or nil
2131 * array.rindex {|element| ... } -> integer or nil
2132 * array.rindex -> new_enumerator
2134 * Returns the index of the last element for which <tt>object == element</tt>.
2136 * When argument +object+ is given but no block, returns the index of the last such element found:
2138 * a = [:foo, 'bar', 2, 'bar']
2139 * a.rindex('bar') # => 3
2141 * Returns +nil+ if no such object found.
2143 * When a block is given but no argument, calls the block with each successive element;
2144 * returns the index of the last element for which the block returns a truthy value:
2146 * a = [:foo, 'bar', 2, 'bar']
2147 * a.rindex {|element| element == 'bar' } # => 3
2149 * Returns +nil+ if the block never returns a truthy value.
2151 * When neither an argument nor a block is given, returns a new Enumerator:
2153 * a = [:foo, 'bar', 2, 'bar']
2154 * e = a.rindex
2155 * e # => #<Enumerator: [:foo, "bar", 2, "bar"]:rindex>
2156 * e.each {|element| element == 'bar' } # => 3
2158 * Related: #index.
2161 static VALUE
2162 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
2164 VALUE val;
2165 long i = RARRAY_LEN(ary), len;
2167 if (argc == 0) {
2168 RETURN_ENUMERATOR(ary, 0, 0);
2169 while (i--) {
2170 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
2171 return LONG2NUM(i);
2172 if (i > (len = RARRAY_LEN(ary))) {
2173 i = len;
2176 return Qnil;
2178 rb_check_arity(argc, 0, 1);
2179 val = argv[0];
2180 if (rb_block_given_p())
2181 rb_warn("given block not used");
2182 while (i--) {
2183 VALUE e = RARRAY_AREF(ary, i);
2184 if (rb_equal(e, val)) {
2185 return LONG2NUM(i);
2187 if (i > RARRAY_LEN(ary)) {
2188 break;
2191 return Qnil;
2194 VALUE
2195 rb_ary_to_ary(VALUE obj)
2197 VALUE tmp = rb_check_array_type(obj);
2199 if (!NIL_P(tmp)) return tmp;
2200 return rb_ary_new3(1, obj);
2203 static void
2204 rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
2206 long olen;
2207 long rofs;
2209 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2210 olen = RARRAY_LEN(ary);
2211 if (beg < 0) {
2212 beg += olen;
2213 if (beg < 0) {
2214 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2215 beg - olen, -olen);
2218 if (olen < len || olen < beg + len) {
2219 len = olen - beg;
2223 const VALUE *optr = RARRAY_CONST_PTR(ary);
2224 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2227 if (beg >= olen) {
2228 VALUE target_ary;
2229 if (beg > ARY_MAX_SIZE - rlen) {
2230 rb_raise(rb_eIndexError, "index %ld too big", beg);
2232 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2233 len = beg + rlen;
2234 ary_mem_clear(ary, olen, beg - olen);
2235 if (rlen > 0) {
2236 if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
2237 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2239 ARY_SET_LEN(ary, len);
2241 else {
2242 long alen;
2244 if (olen - len > ARY_MAX_SIZE - rlen) {
2245 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2247 rb_ary_modify(ary);
2248 alen = olen + rlen - len;
2249 if (alen >= ARY_CAPA(ary)) {
2250 ary_double_capa(ary, alen);
2253 if (len != rlen) {
2254 RARRAY_PTR_USE(ary, ptr,
2255 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2256 VALUE, olen - (beg + len)));
2257 ARY_SET_LEN(ary, alen);
2259 if (rlen > 0) {
2260 if (rofs == -1) {
2261 rb_gc_writebarrier_remember(ary);
2263 else {
2264 /* In this case, we're copying from a region in this array, so
2265 * we don't need to fire the write barrier. */
2266 rptr = RARRAY_CONST_PTR(ary) + rofs;
2269 /* do not use RARRAY_PTR() because it can causes GC.
2270 * ary can contain T_NONE object because it is not cleared.
2272 RARRAY_PTR_USE(ary, ptr,
2273 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2278 void
2279 rb_ary_set_len(VALUE ary, long len)
2281 long capa;
2283 rb_ary_modify_check(ary);
2284 if (ARY_SHARED_P(ary)) {
2285 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2287 if (len > (capa = (long)ARY_CAPA(ary))) {
2288 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2290 ARY_SET_LEN(ary, len);
2293 VALUE
2294 rb_ary_resize(VALUE ary, long len)
2296 long olen;
2298 rb_ary_modify(ary);
2299 olen = RARRAY_LEN(ary);
2300 if (len == olen) return ary;
2301 if (len > ARY_MAX_SIZE) {
2302 rb_raise(rb_eIndexError, "index %ld too big", len);
2304 if (len > olen) {
2305 if (len >= ARY_CAPA(ary)) {
2306 ary_double_capa(ary, len);
2308 ary_mem_clear(ary, olen, len - olen);
2309 ARY_SET_LEN(ary, len);
2311 else if (ARY_EMBED_P(ary)) {
2312 ARY_SET_EMBED_LEN(ary, len);
2314 else if (len <= ary_embed_capa(ary)) {
2315 const VALUE *ptr = ARY_HEAP_PTR(ary);
2316 long ptr_capa = ARY_HEAP_SIZE(ary);
2317 bool is_malloc_ptr = !ARY_SHARED_P(ary);
2319 FL_SET_EMBED(ary);
2321 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
2322 ARY_SET_EMBED_LEN(ary, len);
2324 if (is_malloc_ptr) ruby_sized_xfree((void *)ptr, ptr_capa);
2326 else {
2327 if (olen > len + ARY_DEFAULT_SIZE) {
2328 size_t new_capa = ary_heap_realloc(ary, len);
2329 ARY_SET_CAPA(ary, new_capa);
2331 ARY_SET_HEAP_LEN(ary, len);
2333 ary_verify(ary);
2334 return ary;
2337 static VALUE
2338 ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2340 rb_ary_store(ary, key, val);
2341 return val;
2344 static VALUE
2345 ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2347 VALUE rpl = rb_ary_to_ary(val);
2348 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl));
2349 RB_GC_GUARD(rpl);
2350 return val;
2354 * call-seq:
2355 * self[index] = object -> object
2356 * self[start, length] = object -> object
2357 * self[range] = object -> object
2359 * Assigns elements in +self+, based on the given +object+; returns +object+.
2361 * In brief:
2363 * a_orig = [:foo, 'bar', 2]
2365 * # With argument index.
2366 * a = a_orig.dup
2367 * a[0] = 'foo' # => "foo"
2368 * a # => ["foo", "bar", 2]
2369 * a = a_orig.dup
2370 * a[7] = 'foo' # => "foo"
2371 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2373 * # With arguments start and length.
2374 * a = a_orig.dup
2375 * a[0, 2] = 'foo' # => "foo"
2376 * a # => ["foo", 2]
2377 * a = a_orig.dup
2378 * a[6, 50] = 'foo' # => "foo"
2379 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2381 * # With argument range.
2382 * a = a_orig.dup
2383 * a[0..1] = 'foo' # => "foo"
2384 * a # => ["foo", 2]
2385 * a = a_orig.dup
2386 * a[6..50] = 'foo' # => "foo"
2387 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2389 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2391 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2393 * a = [:foo, 'bar', 2]
2394 * a[0] = 'foo' # => "foo"
2395 * a # => ["foo", "bar", 2]
2397 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2399 * a = [:foo, 'bar', 2]
2400 * a[7] = 'foo' # => "foo"
2401 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2403 * If +index+ is negative, counts backwards from the end of the array:
2405 * a = [:foo, 'bar', 2]
2406 * a[-1] = 'two' # => "two"
2407 * a # => [:foo, "bar", "two"]
2409 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2410 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2411 * and assigns +object+ at offset +start+:
2413 * a = [:foo, 'bar', 2]
2414 * a[0, 2] = 'foo' # => "foo"
2415 * a # => ["foo", 2]
2417 * If +start+ is negative, counts backwards from the end of the array:
2419 * a = [:foo, 'bar', 2]
2420 * a[-2, 2] = 'foo' # => "foo"
2421 * a # => [:foo, "foo"]
2423 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2424 * extends the array with +nil+, assigns +object+ at offset +start+,
2425 * and ignores +length+:
2427 * a = [:foo, 'bar', 2]
2428 * a[6, 50] = 'foo' # => "foo"
2429 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2431 * If +length+ is zero, shifts elements at and following offset +start+
2432 * and assigns +object+ at offset +start+:
2434 * a = [:foo, 'bar', 2]
2435 * a[1, 0] = 'foo' # => "foo"
2436 * a # => [:foo, "foo", "bar", 2]
2438 * If +length+ is too large for the existing array, does not extend the array:
2440 * a = [:foo, 'bar', 2]
2441 * a[1, 5] = 'foo' # => "foo"
2442 * a # => [:foo, "foo"]
2444 * When Range argument +range+ is given and +object+ is not an +Array+,
2445 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2446 * and assigns +object+ at offset +start+:
2448 * a = [:foo, 'bar', 2]
2449 * a[0..1] = 'foo' # => "foo"
2450 * a # => ["foo", 2]
2452 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2454 * a = [:foo, 'bar', 2]
2455 * a[-2..2] = 'foo' # => "foo"
2456 * a # => [:foo, "foo"]
2458 * If the array length is less than <tt>range.begin</tt>,
2459 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2460 * and ignores +length+:
2462 * a = [:foo, 'bar', 2]
2463 * a[6..50] = 'foo' # => "foo"
2464 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2466 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2467 * and assigns +object+ at offset +start+:
2469 * a = [:foo, 'bar', 2]
2470 * a[1..0] = 'foo' # => "foo"
2471 * a # => [:foo, "foo", "bar", 2]
2473 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2474 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2476 * a = [:foo, 'bar', 2]
2477 * a[1..-1] = 'foo' # => "foo"
2478 * a # => [:foo, "foo"]
2479 * a = [:foo, 'bar', 2]
2480 * a[1..-2] = 'foo' # => "foo"
2481 * a # => [:foo, "foo", 2]
2482 * a = [:foo, 'bar', 2]
2483 * a[1..-3] = 'foo' # => "foo"
2484 * a # => [:foo, "foo", "bar", 2]
2485 * a = [:foo, 'bar', 2]
2487 * If <tt>range.end</tt> is too large for the existing array,
2488 * replaces array elements, but does not extend the array with +nil+ values:
2490 * a = [:foo, 'bar', 2]
2491 * a[1..5] = 'foo' # => "foo"
2492 * a # => [:foo, "foo"]
2494 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2497 static VALUE
2498 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2500 long offset, beg, len;
2502 rb_check_arity(argc, 2, 3);
2503 rb_ary_modify_check(ary);
2504 if (argc == 3) {
2505 beg = NUM2LONG(argv[0]);
2506 len = NUM2LONG(argv[1]);
2507 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2509 if (FIXNUM_P(argv[0])) {
2510 offset = FIX2LONG(argv[0]);
2511 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2513 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2514 /* check if idx is Range */
2515 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2518 offset = NUM2LONG(argv[0]);
2519 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2523 * call-seq:
2524 * array.insert(index, *objects) -> self
2526 * Inserts given +objects+ before or after the element at Integer index +offset+;
2527 * returns +self+.
2529 * When +index+ is non-negative, inserts all given +objects+
2530 * before the element at offset +index+:
2532 * a = [:foo, 'bar', 2]
2533 * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2]
2535 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2537 * a = [:foo, 'bar', 2]
2538 * a.insert(5, :bat, :bam)
2539 * a # => [:foo, "bar", 2, nil, nil, :bat, :bam]
2541 * Does nothing if no objects given:
2543 * a = [:foo, 'bar', 2]
2544 * a.insert(1)
2545 * a.insert(50)
2546 * a.insert(-50)
2547 * a # => [:foo, "bar", 2]
2549 * When +index+ is negative, inserts all given +objects+
2550 * _after_ the element at offset <tt>index+self.size</tt>:
2552 * a = [:foo, 'bar', 2]
2553 * a.insert(-2, :bat, :bam)
2554 * a # => [:foo, "bar", :bat, :bam, 2]
2558 static VALUE
2559 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2561 long pos;
2563 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
2564 rb_ary_modify_check(ary);
2565 pos = NUM2LONG(argv[0]);
2566 if (argc == 1) return ary;
2567 if (pos == -1) {
2568 pos = RARRAY_LEN(ary);
2570 else if (pos < 0) {
2571 long minpos = -RARRAY_LEN(ary) - 1;
2572 if (pos < minpos) {
2573 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2574 pos, minpos);
2576 pos++;
2578 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2579 return ary;
2582 static VALUE
2583 rb_ary_length(VALUE ary);
2585 static VALUE
2586 ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2588 return rb_ary_length(ary);
2591 // Primitive to avoid a race condition in Array#each.
2592 // Return `true` and write `value` and `index` if the element exists.
2593 static VALUE
2594 ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
2596 long i = NUM2LONG(*index);
2597 if (i >= RARRAY_LEN(self)) {
2598 return Qfalse;
2600 *value = RARRAY_AREF(self, i);
2601 *index = LONG2NUM(i + 1);
2602 return Qtrue;
2605 VALUE
2606 rb_ary_each(VALUE ary)
2608 long i;
2609 ary_verify(ary);
2610 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2611 for (i=0; i<RARRAY_LEN(ary); i++) {
2612 rb_yield(RARRAY_AREF(ary, i));
2614 return ary;
2618 * call-seq:
2619 * each_index {|index| ... } -> self
2620 * each_index -> new_enumerator
2622 * With a block given, iterates over the elements of +self+,
2623 * passing each <i>array index</i> to the block;
2624 * returns +self+:
2626 * a = [:foo, 'bar', 2]
2627 * a.each_index {|index| puts "#{index} #{a[index]}" }
2629 * Output:
2631 * 0 foo
2632 * 1 bar
2633 * 2 2
2635 * Allows the array to be modified during iteration:
2637 * a = [:foo, 'bar', 2]
2638 * a.each_index {|index| puts index; a.clear if index > 0 }
2640 * Output:
2645 * With no block given, returns a new Enumerator.
2647 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2650 static VALUE
2651 rb_ary_each_index(VALUE ary)
2653 long i;
2654 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2656 for (i=0; i<RARRAY_LEN(ary); i++) {
2657 rb_yield(LONG2NUM(i));
2659 return ary;
2663 * call-seq:
2664 * array.reverse_each {|element| ... } -> self
2665 * array.reverse_each -> Enumerator
2667 * Iterates backwards over array elements.
2669 * When a block given, passes, in reverse order, each element to the block;
2670 * returns +self+:
2672 * a = [:foo, 'bar', 2]
2673 * a.reverse_each {|element| puts "#{element.class} #{element}" }
2675 * Output:
2677 * Integer 2
2678 * String bar
2679 * Symbol foo
2681 * Allows the array to be modified during iteration:
2683 * a = [:foo, 'bar', 2]
2684 * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2686 * Output:
2689 * bar
2691 * When no block given, returns a new Enumerator:
2693 * a = [:foo, 'bar', 2]
2694 * e = a.reverse_each
2695 * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
2696 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2698 * Output:
2700 * Integer 2
2701 * String bar
2702 * Symbol foo
2704 * Related: #each, #each_index.
2707 static VALUE
2708 rb_ary_reverse_each(VALUE ary)
2710 long len;
2712 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2713 len = RARRAY_LEN(ary);
2714 while (len--) {
2715 long nlen;
2716 rb_yield(RARRAY_AREF(ary, len));
2717 nlen = RARRAY_LEN(ary);
2718 if (nlen < len) {
2719 len = nlen;
2722 return ary;
2726 * call-seq:
2727 * array.length -> an_integer
2729 * Returns the count of elements in +self+.
2732 static VALUE
2733 rb_ary_length(VALUE ary)
2735 long len = RARRAY_LEN(ary);
2736 return LONG2NUM(len);
2740 * call-seq:
2741 * array.empty? -> true or false
2743 * Returns +true+ if the count of elements in +self+ is zero,
2744 * +false+ otherwise.
2746 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2749 static VALUE
2750 rb_ary_empty_p(VALUE ary)
2752 return RBOOL(RARRAY_LEN(ary) == 0);
2755 VALUE
2756 rb_ary_dup(VALUE ary)
2758 long len = RARRAY_LEN(ary);
2759 VALUE dup = rb_ary_new2(len);
2760 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2761 ARY_SET_LEN(dup, len);
2763 ary_verify(ary);
2764 ary_verify(dup);
2765 return dup;
2768 VALUE
2769 rb_ary_resurrect(VALUE ary)
2771 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2774 extern VALUE rb_output_fs;
2776 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2778 static VALUE
2779 recursive_join(VALUE obj, VALUE argp, int recur)
2781 VALUE *arg = (VALUE *)argp;
2782 VALUE ary = arg[0];
2783 VALUE sep = arg[1];
2784 VALUE result = arg[2];
2785 int *first = (int *)arg[3];
2787 if (recur) {
2788 rb_raise(rb_eArgError, "recursive array join");
2790 else {
2791 ary_join_1(obj, ary, sep, 0, result, first);
2793 return Qnil;
2796 static long
2797 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2799 long i;
2800 VALUE val;
2802 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2803 for (i=0; i<max; i++) {
2804 val = RARRAY_AREF(ary, i);
2805 if (!RB_TYPE_P(val, T_STRING)) break;
2806 if (i > 0 && !NIL_P(sep))
2807 rb_str_buf_append(result, sep);
2808 rb_str_buf_append(result, val);
2810 return i;
2813 static void
2814 ary_join_1_str(VALUE dst, VALUE src, int *first)
2816 rb_str_buf_append(dst, src);
2817 if (*first) {
2818 rb_enc_copy(dst, src);
2819 *first = FALSE;
2823 static void
2824 ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
2826 if (val == ary) {
2827 rb_raise(rb_eArgError, "recursive array join");
2829 else {
2830 VALUE args[4];
2832 *first = FALSE;
2833 args[0] = val;
2834 args[1] = sep;
2835 args[2] = result;
2836 args[3] = (VALUE)first;
2837 rb_exec_recursive(recursive_join, obj, (VALUE)args);
2841 static void
2842 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
2844 VALUE val, tmp;
2846 for (; i<RARRAY_LEN(ary); i++) {
2847 if (i > 0 && !NIL_P(sep))
2848 rb_str_buf_append(result, sep);
2850 val = RARRAY_AREF(ary, i);
2851 if (RB_TYPE_P(val, T_STRING)) {
2852 ary_join_1_str(result, val, first);
2854 else if (RB_TYPE_P(val, T_ARRAY)) {
2855 ary_join_1_ary(val, ary, sep, result, val, first);
2857 else if (!NIL_P(tmp = rb_check_string_type(val))) {
2858 ary_join_1_str(result, tmp, first);
2860 else if (!NIL_P(tmp = rb_check_array_type(val))) {
2861 ary_join_1_ary(val, ary, sep, result, tmp, first);
2863 else {
2864 ary_join_1_str(result, rb_obj_as_string(val), first);
2869 VALUE
2870 rb_ary_join(VALUE ary, VALUE sep)
2872 long len = 1, i;
2873 VALUE val, tmp, result;
2875 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
2877 if (!NIL_P(sep)) {
2878 StringValue(sep);
2879 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
2881 for (i=0; i<RARRAY_LEN(ary); i++) {
2882 val = RARRAY_AREF(ary, i);
2883 tmp = rb_check_string_type(val);
2885 if (NIL_P(tmp) || tmp != val) {
2886 int first;
2887 long n = RARRAY_LEN(ary);
2888 if (i > n) i = n;
2889 result = rb_str_buf_new(len + (n-i)*10);
2890 rb_enc_associate(result, rb_usascii_encoding());
2891 i = ary_join_0(ary, sep, i, result);
2892 first = i == 0;
2893 ary_join_1(ary, ary, sep, i, result, &first);
2894 return result;
2897 len += RSTRING_LEN(tmp);
2900 result = rb_str_new(0, len);
2901 rb_str_set_len(result, 0);
2903 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
2905 return result;
2909 * call-seq:
2910 * array.join ->new_string
2911 * array.join(separator = $,) -> new_string
2913 * Returns the new String formed by joining the array elements after conversion.
2914 * For each element +element+:
2916 * - Uses <tt>element.to_s</tt> if +element+ is not a <tt>kind_of?(Array)</tt>.
2917 * - Uses recursive <tt>element.join(separator)</tt> if +element+ is a <tt>kind_of?(Array)</tt>.
2919 * With no argument, joins using the output field separator, <tt>$,</tt>:
2921 * a = [:foo, 'bar', 2]
2922 * $, # => nil
2923 * a.join # => "foobar2"
2925 * With \string argument +separator+, joins using that separator:
2927 * a = [:foo, 'bar', 2]
2928 * a.join("\n") # => "foo\nbar\n2"
2930 * Joins recursively for nested Arrays:
2932 * a = [:foo, [:bar, [:baz, :bat]]]
2933 * a.join # => "foobarbazbat"
2936 static VALUE
2937 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
2939 VALUE sep;
2941 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
2942 sep = rb_output_fs;
2943 if (!NIL_P(sep)) {
2944 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
2948 return rb_ary_join(ary, sep);
2951 static VALUE
2952 inspect_ary(VALUE ary, VALUE dummy, int recur)
2954 long i;
2955 VALUE s, str;
2957 if (recur) return rb_usascii_str_new_cstr("[...]");
2958 str = rb_str_buf_new2("[");
2959 for (i=0; i<RARRAY_LEN(ary); i++) {
2960 s = rb_inspect(RARRAY_AREF(ary, i));
2961 if (i > 0) rb_str_buf_cat2(str, ", ");
2962 else rb_enc_copy(str, s);
2963 rb_str_buf_append(str, s);
2965 rb_str_buf_cat2(str, "]");
2966 return str;
2970 * call-seq:
2971 * array.inspect -> new_string
2973 * Returns the new String formed by calling method <tt>#inspect</tt>
2974 * on each array element:
2976 * a = [:foo, 'bar', 2]
2977 * a.inspect # => "[:foo, \"bar\", 2]"
2981 static VALUE
2982 rb_ary_inspect(VALUE ary)
2984 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
2985 return rb_exec_recursive(inspect_ary, ary, 0);
2988 VALUE
2989 rb_ary_to_s(VALUE ary)
2991 return rb_ary_inspect(ary);
2995 * call-seq:
2996 * to_a -> self or new_array
2998 * When +self+ is an instance of +Array+, returns +self+:
3000 * a = [:foo, 'bar', 2]
3001 * a.to_a # => [:foo, "bar", 2]
3003 * Otherwise, returns a new +Array+ containing the elements of +self+:
3005 * class MyArray < Array; end
3006 * a = MyArray.new(['foo', 'bar', 'two'])
3007 * a.instance_of?(Array) # => false
3008 * a.kind_of?(Array) # => true
3009 * a1 = a.to_a
3010 * a1 # => ["foo", "bar", "two"]
3011 * a1.class # => Array # Not MyArray
3015 static VALUE
3016 rb_ary_to_a(VALUE ary)
3018 if (rb_obj_class(ary) != rb_cArray) {
3019 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
3020 rb_ary_replace(dup, ary);
3021 return dup;
3023 return ary;
3027 * call-seq:
3028 * array.to_h -> new_hash
3029 * array.to_h {|item| ... } -> new_hash
3031 * Returns a new Hash formed from +self+.
3033 * When a block is given, calls the block with each array element;
3034 * the block must return a 2-element +Array+ whose two elements
3035 * form a key-value pair in the returned Hash:
3037 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3038 * h = a.to_h {|item| [item, item] }
3039 * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
3041 * When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
3042 * each sub-array is formed into a key-value pair in the new Hash:
3044 * [].to_h # => {}
3045 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3046 * h = a.to_h
3047 * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3051 static VALUE
3052 rb_ary_to_h(VALUE ary)
3054 long i;
3055 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
3056 int block_given = rb_block_given_p();
3058 for (i=0; i<RARRAY_LEN(ary); i++) {
3059 const VALUE e = rb_ary_elt(ary, i);
3060 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3061 const VALUE key_value_pair = rb_check_array_type(elt);
3062 if (NIL_P(key_value_pair)) {
3063 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
3064 rb_obj_class(elt), i);
3066 if (RARRAY_LEN(key_value_pair) != 2) {
3067 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
3068 i, RARRAY_LEN(key_value_pair));
3070 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3072 return hash;
3076 * call-seq:
3077 * array.to_ary -> self
3079 * Returns +self+.
3082 static VALUE
3083 rb_ary_to_ary_m(VALUE ary)
3085 return ary;
3088 static void
3089 ary_reverse(VALUE *p1, VALUE *p2)
3091 while (p1 < p2) {
3092 VALUE tmp = *p1;
3093 *p1++ = *p2;
3094 *p2-- = tmp;
3098 VALUE
3099 rb_ary_reverse(VALUE ary)
3101 VALUE *p2;
3102 long len = RARRAY_LEN(ary);
3104 rb_ary_modify(ary);
3105 if (len > 1) {
3106 RARRAY_PTR_USE(ary, p1, {
3107 p2 = p1 + len - 1; /* points last item */
3108 ary_reverse(p1, p2);
3109 }); /* WB: no new reference */
3111 return ary;
3115 * call-seq:
3116 * array.reverse! -> self
3118 * Reverses +self+ in place:
3120 * a = ['foo', 'bar', 'two']
3121 * a.reverse! # => ["two", "bar", "foo"]
3125 static VALUE
3126 rb_ary_reverse_bang(VALUE ary)
3128 return rb_ary_reverse(ary);
3132 * call-seq:
3133 * array.reverse -> new_array
3135 * Returns a new +Array+ with the elements of +self+ in reverse order:
3137 * a = ['foo', 'bar', 'two']
3138 * a1 = a.reverse
3139 * a1 # => ["two", "bar", "foo"]
3143 static VALUE
3144 rb_ary_reverse_m(VALUE ary)
3146 long len = RARRAY_LEN(ary);
3147 VALUE dup = rb_ary_new2(len);
3149 if (len > 0) {
3150 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3151 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3152 do *p2-- = *p1++; while (--len > 0);
3154 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3155 return dup;
3158 static inline long
3159 rotate_count(long cnt, long len)
3161 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3164 static void
3165 ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3167 if (cnt == 1) {
3168 VALUE tmp = *ptr;
3169 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3170 *(ptr + len - 1) = tmp;
3172 else if (cnt == len - 1) {
3173 VALUE tmp = *(ptr + len - 1);
3174 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3175 *ptr = tmp;
3177 else {
3178 --len;
3179 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3180 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3181 if (len > 0) ary_reverse(ptr, ptr + len);
3185 VALUE
3186 rb_ary_rotate(VALUE ary, long cnt)
3188 rb_ary_modify(ary);
3190 if (cnt != 0) {
3191 long len = RARRAY_LEN(ary);
3192 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3193 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3194 return ary;
3197 return Qnil;
3201 * call-seq:
3202 * array.rotate! -> self
3203 * array.rotate!(count) -> self
3205 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3207 * When no argument given, rotates the first element to the last position:
3209 * a = [:foo, 'bar', 2, 'bar']
3210 * a.rotate! # => ["bar", 2, "bar", :foo]
3212 * When given a non-negative Integer +count+,
3213 * rotates +count+ elements from the beginning to the end:
3215 * a = [:foo, 'bar', 2]
3216 * a.rotate!(2)
3217 * a # => [2, :foo, "bar"]
3219 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3221 * a = [:foo, 'bar', 2]
3222 * a.rotate!(20)
3223 * a # => [2, :foo, "bar"]
3225 * If +count+ is zero, returns +self+ unmodified:
3227 * a = [:foo, 'bar', 2]
3228 * a.rotate!(0)
3229 * a # => [:foo, "bar", 2]
3231 * When given a negative Integer +count+, rotates in the opposite direction,
3232 * from end to beginning:
3234 * a = [:foo, 'bar', 2]
3235 * a.rotate!(-2)
3236 * a # => ["bar", 2, :foo]
3238 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3240 * a = [:foo, 'bar', 2]
3241 * a.rotate!(-5)
3242 * a # => ["bar", 2, :foo]
3246 static VALUE
3247 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3249 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3250 rb_ary_rotate(ary, n);
3251 return ary;
3255 * call-seq:
3256 * array.rotate -> new_array
3257 * array.rotate(count) -> new_array
3259 * Returns a new +Array+ formed from +self+ with elements
3260 * rotated from one end to the other.
3262 * When no argument given, returns a new +Array+ that is like +self+,
3263 * except that the first element has been rotated to the last position:
3265 * a = [:foo, 'bar', 2, 'bar']
3266 * a1 = a.rotate
3267 * a1 # => ["bar", 2, "bar", :foo]
3269 * When given a non-negative Integer +count+,
3270 * returns a new +Array+ with +count+ elements rotated from the beginning to the end:
3272 * a = [:foo, 'bar', 2]
3273 * a1 = a.rotate(2)
3274 * a1 # => [2, :foo, "bar"]
3276 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3278 * a = [:foo, 'bar', 2]
3279 * a1 = a.rotate(20)
3280 * a1 # => [2, :foo, "bar"]
3282 * If +count+ is zero, returns a copy of +self+, unmodified:
3284 * a = [:foo, 'bar', 2]
3285 * a1 = a.rotate(0)
3286 * a1 # => [:foo, "bar", 2]
3288 * When given a negative Integer +count+, rotates in the opposite direction,
3289 * from end to beginning:
3291 * a = [:foo, 'bar', 2]
3292 * a1 = a.rotate(-2)
3293 * a1 # => ["bar", 2, :foo]
3295 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3297 * a = [:foo, 'bar', 2]
3298 * a1 = a.rotate(-5)
3299 * a1 # => ["bar", 2, :foo]
3303 static VALUE
3304 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3306 VALUE rotated;
3307 const VALUE *ptr;
3308 long len;
3309 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3311 len = RARRAY_LEN(ary);
3312 rotated = rb_ary_new2(len);
3313 if (len > 0) {
3314 cnt = rotate_count(cnt, len);
3315 ptr = RARRAY_CONST_PTR(ary);
3316 len -= cnt;
3317 ary_memcpy(rotated, 0, len, ptr + cnt);
3318 ary_memcpy(rotated, len, cnt, ptr);
3320 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3321 return rotated;
3324 struct ary_sort_data {
3325 VALUE ary;
3326 VALUE receiver;
3329 static VALUE
3330 sort_reentered(VALUE ary)
3332 if (RBASIC(ary)->klass) {
3333 rb_raise(rb_eRuntimeError, "sort reentered");
3335 return Qnil;
3338 static void
3339 sort_returned(struct ary_sort_data *data)
3341 if (rb_obj_frozen_p(data->receiver)) {
3342 rb_raise(rb_eFrozenError, "array frozen during sort");
3344 sort_reentered(data->ary);
3347 static int
3348 sort_1(const void *ap, const void *bp, void *dummy)
3350 struct ary_sort_data *data = dummy;
3351 VALUE retval = sort_reentered(data->ary);
3352 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3353 VALUE args[2];
3354 int n;
3356 args[0] = a;
3357 args[1] = b;
3358 retval = rb_yield_values2(2, args);
3359 n = rb_cmpint(retval, a, b);
3360 sort_returned(data);
3361 return n;
3364 static int
3365 sort_2(const void *ap, const void *bp, void *dummy)
3367 struct ary_sort_data *data = dummy;
3368 VALUE retval = sort_reentered(data->ary);
3369 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3370 int n;
3372 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3373 if ((long)a > (long)b) return 1;
3374 if ((long)a < (long)b) return -1;
3375 return 0;
3377 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3378 return rb_str_cmp(a, b);
3380 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3381 return rb_float_cmp(a, b);
3384 retval = rb_funcallv(a, id_cmp, 1, &b);
3385 n = rb_cmpint(retval, a, b);
3386 sort_returned(data);
3388 return n;
3392 * call-seq:
3393 * array.sort! -> self
3394 * array.sort! {|a, b| ... } -> self
3396 * Returns +self+ with its elements sorted in place.
3398 * With no block, compares elements using operator <tt><=></tt>
3399 * (see Comparable):
3401 * a = 'abcde'.split('').shuffle
3402 * a # => ["e", "b", "d", "a", "c"]
3403 * a.sort!
3404 * a # => ["a", "b", "c", "d", "e"]
3406 * With a block, calls the block with each element pair;
3407 * for each element pair +a+ and +b+, the block should return an integer:
3409 * - Negative when +b+ is to follow +a+.
3410 * - Zero when +a+ and +b+ are equivalent.
3411 * - Positive when +a+ is to follow +b+.
3413 * Example:
3415 * a = 'abcde'.split('').shuffle
3416 * a # => ["e", "b", "d", "a", "c"]
3417 * a.sort! {|a, b| a <=> b }
3418 * a # => ["a", "b", "c", "d", "e"]
3419 * a.sort! {|a, b| b <=> a }
3420 * a # => ["e", "d", "c", "b", "a"]
3422 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3423 * and may be unstable:
3425 * a = 'abcde'.split('').shuffle
3426 * a # => ["e", "b", "d", "a", "c"]
3427 * a.sort! {|a, b| 0 }
3428 * a # => ["d", "e", "c", "a", "b"]
3432 VALUE
3433 rb_ary_sort_bang(VALUE ary)
3435 rb_ary_modify(ary);
3436 RUBY_ASSERT(!ARY_SHARED_P(ary));
3437 if (RARRAY_LEN(ary) > 1) {
3438 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3439 struct ary_sort_data data;
3440 long len = RARRAY_LEN(ary);
3441 RBASIC_CLEAR_CLASS(tmp);
3442 data.ary = tmp;
3443 data.receiver = ary;
3444 RARRAY_PTR_USE(tmp, ptr, {
3445 ruby_qsort(ptr, len, sizeof(VALUE),
3446 rb_block_given_p()?sort_1:sort_2, &data);
3447 }); /* WB: no new reference */
3448 rb_ary_modify(ary);
3449 if (ARY_EMBED_P(tmp)) {
3450 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3451 rb_ary_unshare(ary);
3452 FL_SET_EMBED(ary);
3454 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3455 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3457 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3458 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3460 else {
3461 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3462 FL_UNSET_SHARED(ary);
3463 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3465 else {
3466 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3467 if (ARY_EMBED_P(ary)) {
3468 FL_UNSET_EMBED(ary);
3470 else if (ARY_SHARED_P(ary)) {
3471 /* ary might be destructively operated in the given block */
3472 rb_ary_unshare(ary);
3474 else {
3475 ary_heap_free(ary);
3477 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3478 ARY_SET_HEAP_LEN(ary, len);
3479 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3481 /* tmp was lost ownership for the ptr */
3482 FL_UNSET(tmp, FL_FREEZE);
3483 FL_SET_EMBED(tmp);
3484 ARY_SET_EMBED_LEN(tmp, 0);
3485 FL_SET(tmp, FL_FREEZE);
3487 /* tmp will be GC'ed. */
3488 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3490 ary_verify(ary);
3491 return ary;
3495 * call-seq:
3496 * array.sort -> new_array
3497 * array.sort {|a, b| ... } -> new_array
3499 * Returns a new +Array+ whose elements are those from +self+, sorted.
3501 * With no block, compares elements using operator <tt><=></tt>
3502 * (see Comparable):
3504 * a = 'abcde'.split('').shuffle
3505 * a # => ["e", "b", "d", "a", "c"]
3506 * a1 = a.sort
3507 * a1 # => ["a", "b", "c", "d", "e"]
3509 * With a block, calls the block with each element pair;
3510 * for each element pair +a+ and +b+, the block should return an integer:
3512 * - Negative when +b+ is to follow +a+.
3513 * - Zero when +a+ and +b+ are equivalent.
3514 * - Positive when +a+ is to follow +b+.
3516 * Example:
3518 * a = 'abcde'.split('').shuffle
3519 * a # => ["e", "b", "d", "a", "c"]
3520 * a1 = a.sort {|a, b| a <=> b }
3521 * a1 # => ["a", "b", "c", "d", "e"]
3522 * a2 = a.sort {|a, b| b <=> a }
3523 * a2 # => ["e", "d", "c", "b", "a"]
3525 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3526 * and may be unstable:
3528 * a = 'abcde'.split('').shuffle
3529 * a # => ["e", "b", "d", "a", "c"]
3530 * a1 = a.sort {|a, b| 0 }
3531 * a1 # => ["c", "e", "b", "d", "a"]
3533 * Related: Enumerable#sort_by.
3536 VALUE
3537 rb_ary_sort(VALUE ary)
3539 ary = rb_ary_dup(ary);
3540 rb_ary_sort_bang(ary);
3541 return ary;
3544 static VALUE rb_ary_bsearch_index(VALUE ary);
3547 * call-seq:
3548 * bsearch {|element| ... } -> found_element or nil
3549 * bsearch -> new_enumerator
3551 * Returns the element from +self+ found by a binary search,
3552 * or +nil+ if the search found no suitable element.
3554 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3556 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3559 static VALUE
3560 rb_ary_bsearch(VALUE ary)
3562 VALUE index_result = rb_ary_bsearch_index(ary);
3564 if (FIXNUM_P(index_result)) {
3565 return rb_ary_entry(ary, FIX2LONG(index_result));
3567 return index_result;
3571 * call-seq:
3572 * bsearch_index {|element| ... } -> integer or nil
3573 * bsearch_index -> new_enumerator
3575 * Returns the integer index of the element from +self+ found by a binary search,
3576 * or +nil+ if the search found no suitable element.
3578 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3580 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3583 static VALUE
3584 rb_ary_bsearch_index(VALUE ary)
3586 long low = 0, high = RARRAY_LEN(ary), mid;
3587 int smaller = 0, satisfied = 0;
3588 VALUE v, val;
3590 RETURN_ENUMERATOR(ary, 0, 0);
3591 while (low < high) {
3592 mid = low + ((high - low) / 2);
3593 val = rb_ary_entry(ary, mid);
3594 v = rb_yield(val);
3595 if (FIXNUM_P(v)) {
3596 if (v == INT2FIX(0)) return INT2FIX(mid);
3597 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3599 else if (v == Qtrue) {
3600 satisfied = 1;
3601 smaller = 1;
3603 else if (!RTEST(v)) {
3604 smaller = 0;
3606 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3607 const VALUE zero = INT2FIX(0);
3608 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3609 case 0: return INT2FIX(mid);
3610 case 1: smaller = 0; break;
3611 case -1: smaller = 1;
3614 else {
3615 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3616 " (must be numeric, true, false or nil)",
3617 rb_obj_class(v));
3619 if (smaller) {
3620 high = mid;
3622 else {
3623 low = mid + 1;
3626 if (!satisfied) return Qnil;
3627 return INT2FIX(low);
3631 static VALUE
3632 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3634 return rb_yield(i);
3638 * call-seq:
3639 * array.sort_by! {|element| ... } -> self
3640 * array.sort_by! -> new_enumerator
3642 * Sorts the elements of +self+ in place,
3643 * using an ordering determined by the block; returns self.
3645 * Calls the block with each successive element;
3646 * sorts elements based on the values returned from the block.
3648 * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
3650 * This example sorts strings based on their sizes:
3652 * a = ['aaaa', 'bbb', 'cc', 'd']
3653 * a.sort_by! {|element| element.size }
3654 * a # => ["d", "cc", "bbb", "aaaa"]
3656 * Returns a new Enumerator if no block given:
3658 * a = ['aaaa', 'bbb', 'cc', 'd']
3659 * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
3663 static VALUE
3664 rb_ary_sort_by_bang(VALUE ary)
3666 VALUE sorted;
3668 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3669 rb_ary_modify(ary);
3670 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3671 rb_ary_replace(ary, sorted);
3672 return ary;
3677 * call-seq:
3678 * collect {|element| ... } -> new_array
3679 * collect -> new_enumerator
3680 * map {|element| ... } -> new_array
3681 * map -> new_enumerator
3683 * With a block given, calls the block with each element of +self+;
3684 * returns a new array whose elements are the return values from the block:
3686 * a = [:foo, 'bar', 2]
3687 * a1 = a.map {|element| element.class }
3688 * a1 # => [Symbol, String, Integer]
3690 * With no block given, returns a new Enumerator.
3692 * Related: #collect!;
3693 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3696 static VALUE
3697 rb_ary_collect(VALUE ary)
3699 long i;
3700 VALUE collect;
3702 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3703 collect = rb_ary_new2(RARRAY_LEN(ary));
3704 for (i = 0; i < RARRAY_LEN(ary); i++) {
3705 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3707 return collect;
3712 * call-seq:
3713 * collect! {|element| ... } -> new_array
3714 * collect! -> new_enumerator
3715 * map! {|element| ... } -> new_array
3716 * map! -> new_enumerator
3718 * With a block given, calls the block with each element of +self+
3719 * and replaces the element with the block's return value;
3720 * returns +self+:
3722 * a = [:foo, 'bar', 2]
3723 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3725 * With no block given, returns a new Enumerator.
3727 * Related: #collect;
3728 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3731 static VALUE
3732 rb_ary_collect_bang(VALUE ary)
3734 long i;
3736 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3737 rb_ary_modify(ary);
3738 for (i = 0; i < RARRAY_LEN(ary); i++) {
3739 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3741 return ary;
3744 VALUE
3745 rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3747 VALUE result = rb_ary_new2(argc);
3748 long beg, len, i, j;
3750 for (i=0; i<argc; i++) {
3751 if (FIXNUM_P(argv[i])) {
3752 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3753 continue;
3755 /* check if idx is Range */
3756 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3757 long end = olen < beg+len ? olen : beg+len;
3758 for (j = beg; j < end; j++) {
3759 rb_ary_push(result, (*func)(obj, j));
3761 if (beg + len > j)
3762 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3763 continue;
3765 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3767 return result;
3770 static VALUE
3771 append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3773 long beg, len;
3774 if (FIXNUM_P(idx)) {
3775 beg = FIX2LONG(idx);
3777 /* check if idx is Range */
3778 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3779 if (len > 0) {
3780 const VALUE *const src = RARRAY_CONST_PTR(ary);
3781 const long end = beg + len;
3782 const long prevlen = RARRAY_LEN(result);
3783 if (beg < olen) {
3784 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3786 if (end > olen) {
3787 rb_ary_store(result, prevlen + len - 1, Qnil);
3790 return result;
3792 else {
3793 beg = NUM2LONG(idx);
3795 return rb_ary_push(result, rb_ary_entry(ary, beg));
3799 * call-seq:
3800 * array.values_at(*indexes) -> new_array
3802 * Returns a new +Array+ whose elements are the elements
3803 * of +self+ at the given Integer or Range +indexes+.
3805 * For each positive +index+, returns the element at offset +index+:
3807 * a = [:foo, 'bar', 2]
3808 * a.values_at(0, 2) # => [:foo, 2]
3809 * a.values_at(0..1) # => [:foo, "bar"]
3811 * The given +indexes+ may be in any order, and may repeat:
3813 * a = [:foo, 'bar', 2]
3814 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3815 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3817 * Assigns +nil+ for an +index+ that is too large:
3819 * a = [:foo, 'bar', 2]
3820 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3822 * Returns a new empty +Array+ if no arguments given.
3824 * For each negative +index+, counts backward from the end of the array:
3826 * a = [:foo, 'bar', 2]
3827 * a.values_at(-1, -3) # => [2, :foo]
3829 * Assigns +nil+ for an +index+ that is too small:
3831 * a = [:foo, 'bar', 2]
3832 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3834 * The given +indexes+ may have a mixture of signs:
3836 * a = [:foo, 'bar', 2]
3837 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3841 static VALUE
3842 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
3844 long i, olen = RARRAY_LEN(ary);
3845 VALUE result = rb_ary_new_capa(argc);
3846 for (i = 0; i < argc; ++i) {
3847 append_values_at_single(result, ary, olen, argv[i]);
3849 RB_GC_GUARD(ary);
3850 return result;
3855 * call-seq:
3856 * array.select {|element| ... } -> new_array
3857 * array.select -> new_enumerator
3859 * Calls the block, if given, with each element of +self+;
3860 * returns a new +Array+ containing those elements of +self+
3861 * for which the block returns a truthy value:
3863 * a = [:foo, 'bar', 2, :bam]
3864 * a1 = a.select {|element| element.to_s.start_with?('b') }
3865 * a1 # => ["bar", :bam]
3867 * Returns a new Enumerator if no block given:
3869 * a = [:foo, 'bar', 2, :bam]
3870 * a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
3874 static VALUE
3875 rb_ary_select(VALUE ary)
3877 VALUE result;
3878 long i;
3880 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3881 result = rb_ary_new2(RARRAY_LEN(ary));
3882 for (i = 0; i < RARRAY_LEN(ary); i++) {
3883 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
3884 rb_ary_push(result, rb_ary_elt(ary, i));
3887 return result;
3890 struct select_bang_arg {
3891 VALUE ary;
3892 long len[2];
3895 static VALUE
3896 select_bang_i(VALUE a)
3898 volatile struct select_bang_arg *arg = (void *)a;
3899 VALUE ary = arg->ary;
3900 long i1, i2;
3902 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
3903 VALUE v = RARRAY_AREF(ary, i1);
3904 if (!RTEST(rb_yield(v))) continue;
3905 if (i1 != i2) {
3906 rb_ary_store(ary, i2, v);
3908 arg->len[1] = ++i2;
3910 return (i1 == i2) ? Qnil : ary;
3913 static VALUE
3914 select_bang_ensure(VALUE a)
3916 volatile struct select_bang_arg *arg = (void *)a;
3917 VALUE ary = arg->ary;
3918 long len = RARRAY_LEN(ary);
3919 long i1 = arg->len[0], i2 = arg->len[1];
3921 if (i2 < len && i2 < i1) {
3922 long tail = 0;
3923 rb_ary_modify(ary);
3924 if (i1 < len) {
3925 tail = len - i1;
3926 RARRAY_PTR_USE(ary, ptr, {
3927 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
3930 ARY_SET_LEN(ary, i2 + tail);
3932 return ary;
3936 * call-seq:
3937 * array.select! {|element| ... } -> self or nil
3938 * array.select! -> new_enumerator
3940 * Calls the block, if given with each element of +self+;
3941 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3943 * Returns +self+ if any elements were removed:
3945 * a = [:foo, 'bar', 2, :bam]
3946 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3948 * Returns +nil+ if no elements were removed.
3950 * Returns a new Enumerator if no block given:
3952 * a = [:foo, 'bar', 2, :bam]
3953 * a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
3957 static VALUE
3958 rb_ary_select_bang(VALUE ary)
3960 struct select_bang_arg args;
3962 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3963 rb_ary_modify(ary);
3965 args.ary = ary;
3966 args.len[0] = args.len[1] = 0;
3967 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
3971 * call-seq:
3972 * array.keep_if {|element| ... } -> self
3973 * array.keep_if -> new_enumeration
3975 * Retains those elements for which the block returns a truthy value;
3976 * deletes all other elements; returns +self+:
3978 * a = [:foo, 'bar', 2, :bam]
3979 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3981 * Returns a new Enumerator if no block given:
3983 * a = [:foo, 'bar', 2, :bam]
3984 * a.keep_if # => #<Enumerator: [:foo, "bar", 2, :bam]:keep_if>
3988 static VALUE
3989 rb_ary_keep_if(VALUE ary)
3991 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3992 rb_ary_select_bang(ary);
3993 return ary;
3996 static void
3997 ary_resize_smaller(VALUE ary, long len)
3999 rb_ary_modify(ary);
4000 if (RARRAY_LEN(ary) > len) {
4001 ARY_SET_LEN(ary, len);
4002 if (len * 2 < ARY_CAPA(ary) &&
4003 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
4004 ary_resize_capa(ary, len * 2);
4010 * call-seq:
4011 * delete(object) -> last_removed_object
4012 * delete(object) {|element| ... } -> last_removed_object or block_return
4014 * Removes zero or more elements from +self+.
4016 * With no block given,
4017 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4018 * returns the last removed element:
4020 * a = [0, 1, 2, 2.0]
4021 * a.delete(2) # => 2.0
4022 * a # => [0, 1]
4024 * Returns +nil+ if no elements removed:
4026 * a.delete(2) # => nil
4028 * With a block given,
4029 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4031 * If any such elements are found, ignores the block
4032 * and returns the last removed element:
4034 * a = [0, 1, 2, 2.0]
4035 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4036 * a # => [0, 1]
4038 * If no such element is found, returns the block's return value:
4040 * a.delete(2) {|element| "Element #{element} not found." }
4041 * # => "Element 2 not found."
4043 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4046 VALUE
4047 rb_ary_delete(VALUE ary, VALUE item)
4049 VALUE v = item;
4050 long i1, i2;
4052 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4053 VALUE e = RARRAY_AREF(ary, i1);
4055 if (rb_equal(e, item)) {
4056 v = e;
4057 continue;
4059 if (i1 != i2) {
4060 rb_ary_store(ary, i2, e);
4062 i2++;
4064 if (RARRAY_LEN(ary) == i2) {
4065 if (rb_block_given_p()) {
4066 return rb_yield(item);
4068 return Qnil;
4071 ary_resize_smaller(ary, i2);
4073 ary_verify(ary);
4074 return v;
4077 void
4078 rb_ary_delete_same(VALUE ary, VALUE item)
4080 long i1, i2;
4082 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4083 VALUE e = RARRAY_AREF(ary, i1);
4085 if (e == item) {
4086 continue;
4088 if (i1 != i2) {
4089 rb_ary_store(ary, i2, e);
4091 i2++;
4093 if (RARRAY_LEN(ary) == i2) {
4094 return;
4097 ary_resize_smaller(ary, i2);
4100 VALUE
4101 rb_ary_delete_at(VALUE ary, long pos)
4103 long len = RARRAY_LEN(ary);
4104 VALUE del;
4106 if (pos >= len) return Qnil;
4107 if (pos < 0) {
4108 pos += len;
4109 if (pos < 0) return Qnil;
4112 rb_ary_modify(ary);
4113 del = RARRAY_AREF(ary, pos);
4114 RARRAY_PTR_USE(ary, ptr, {
4115 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4117 ARY_INCREASE_LEN(ary, -1);
4118 ary_verify(ary);
4119 return del;
4123 * call-seq:
4124 * delete_at(index) -> removed_object or nil
4126 * Removes the element of +self+ at the given +index+, which must be an
4127 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4129 * When +index+ is non-negative, deletes the element at offset +index+:
4131 * a = [:foo, 'bar', 2]
4132 * a.delete_at(1) # => "bar"
4133 * a # => [:foo, 2]
4135 * When +index+ is negative, counts backward from the end of the array:
4137 * a = [:foo, 'bar', 2]
4138 * a.delete_at(-2) # => "bar"
4139 * a # => [:foo, 2]
4141 * When +index+ is out of range, returns +nil+.
4143 * a = [:foo, 'bar', 2]
4144 * a.delete_at(3) # => nil
4145 * a.delete_at(-4) # => nil
4147 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4150 static VALUE
4151 rb_ary_delete_at_m(VALUE ary, VALUE pos)
4153 return rb_ary_delete_at(ary, NUM2LONG(pos));
4156 static VALUE
4157 ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
4159 const long orig_len = RARRAY_LEN(ary);
4161 if (len < 0) {
4162 return Qnil;
4164 else if (pos < -orig_len) {
4165 return Qnil;
4167 else if (pos < 0) {
4168 pos += orig_len;
4170 else if (orig_len < pos) {
4171 return Qnil;
4173 if (orig_len < pos + len) {
4174 len = orig_len - pos;
4176 if (len == 0) {
4177 return rb_ary_new2(0);
4179 else {
4180 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4181 rb_ary_splice(ary, pos, len, 0, 0);
4182 return arg2;
4187 * call-seq:
4188 * array.slice!(n) -> object or nil
4189 * array.slice!(start, length) -> new_array or nil
4190 * array.slice!(range) -> new_array or nil
4192 * Removes and returns elements from +self+.
4194 * When the only argument is an Integer +n+,
4195 * removes and returns the _nth_ element in +self+:
4197 * a = [:foo, 'bar', 2]
4198 * a.slice!(1) # => "bar"
4199 * a # => [:foo, 2]
4201 * If +n+ is negative, counts backwards from the end of +self+:
4203 * a = [:foo, 'bar', 2]
4204 * a.slice!(-1) # => 2
4205 * a # => [:foo, "bar"]
4207 * If +n+ is out of range, returns +nil+.
4209 * When the only arguments are Integers +start+ and +length+,
4210 * removes +length+ elements from +self+ beginning at offset +start+;
4211 * returns the deleted objects in a new +Array+:
4213 * a = [:foo, 'bar', 2]
4214 * a.slice!(0, 2) # => [:foo, "bar"]
4215 * a # => [2]
4217 * If <tt>start + length</tt> exceeds the array size,
4218 * removes and returns all elements from offset +start+ to the end:
4220 * a = [:foo, 'bar', 2]
4221 * a.slice!(1, 50) # => ["bar", 2]
4222 * a # => [:foo]
4224 * If <tt>start == a.size</tt> and +length+ is non-negative,
4225 * returns a new empty +Array+.
4227 * If +length+ is negative, returns +nil+.
4229 * When the only argument is a Range object +range+,
4230 * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
4232 * a = [:foo, 'bar', 2]
4233 * a.slice!(1..2) # => ["bar", 2]
4234 * a # => [:foo]
4236 * If <tt>range.start == a.size</tt>, returns a new empty +Array+.
4238 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
4240 * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
4242 * a = [:foo, 'bar', 2]
4243 * a.slice!(0..-2) # => [:foo, "bar"]
4244 * a # => [2]
4246 * If <tt>range.start</tt> is negative,
4247 * calculates the start index backwards from the end of the array:
4249 * a = [:foo, 'bar', 2]
4250 * a.slice!(-2..2) # => ["bar", 2]
4251 * a # => [:foo]
4255 static VALUE
4256 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4258 VALUE arg1;
4259 long pos, len;
4261 rb_ary_modify_check(ary);
4262 rb_check_arity(argc, 1, 2);
4263 arg1 = argv[0];
4265 if (argc == 2) {
4266 pos = NUM2LONG(argv[0]);
4267 len = NUM2LONG(argv[1]);
4268 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4271 if (!FIXNUM_P(arg1)) {
4272 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4273 case Qtrue:
4274 /* valid range */
4275 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4276 case Qnil:
4277 /* invalid range */
4278 return Qnil;
4279 default:
4280 /* not a range */
4281 break;
4285 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4288 static VALUE
4289 ary_reject(VALUE orig, VALUE result)
4291 long i;
4293 for (i = 0; i < RARRAY_LEN(orig); i++) {
4294 VALUE v = RARRAY_AREF(orig, i);
4296 if (!RTEST(rb_yield(v))) {
4297 rb_ary_push(result, v);
4300 return result;
4303 static VALUE
4304 reject_bang_i(VALUE a)
4306 volatile struct select_bang_arg *arg = (void *)a;
4307 VALUE ary = arg->ary;
4308 long i1, i2;
4310 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4311 VALUE v = RARRAY_AREF(ary, i1);
4312 if (RTEST(rb_yield(v))) continue;
4313 if (i1 != i2) {
4314 rb_ary_store(ary, i2, v);
4316 arg->len[1] = ++i2;
4318 return (i1 == i2) ? Qnil : ary;
4321 static VALUE
4322 ary_reject_bang(VALUE ary)
4324 struct select_bang_arg args;
4325 rb_ary_modify_check(ary);
4326 args.ary = ary;
4327 args.len[0] = args.len[1] = 0;
4328 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4332 * call-seq:
4333 * array.reject! {|element| ... } -> self or nil
4334 * array.reject! -> new_enumerator
4336 * Removes each element for which the block returns a truthy value.
4338 * Returns +self+ if any elements removed:
4340 * a = [:foo, 'bar', 2, 'bat']
4341 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4343 * Returns +nil+ if no elements removed.
4345 * Returns a new Enumerator if no block given:
4347 * a = [:foo, 'bar', 2]
4348 * a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
4352 static VALUE
4353 rb_ary_reject_bang(VALUE ary)
4355 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4356 rb_ary_modify(ary);
4357 return ary_reject_bang(ary);
4361 * call-seq:
4362 * array.reject {|element| ... } -> new_array
4363 * array.reject -> new_enumerator
4365 * Returns a new +Array+ whose elements are all those from +self+
4366 * for which the block returns +false+ or +nil+:
4368 * a = [:foo, 'bar', 2, 'bat']
4369 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4370 * a1 # => [:foo, 2]
4372 * Returns a new Enumerator if no block given:
4374 * a = [:foo, 'bar', 2]
4375 * a.reject # => #<Enumerator: [:foo, "bar", 2]:reject>
4379 static VALUE
4380 rb_ary_reject(VALUE ary)
4382 VALUE rejected_ary;
4384 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4385 rejected_ary = rb_ary_new();
4386 ary_reject(ary, rejected_ary);
4387 return rejected_ary;
4391 * call-seq:
4392 * delete_if {|element| ... } -> self
4393 * delete_if -> new_numerator
4395 * With a block given, calls the block with each element of +self+;
4396 * removes the element if the block returns a truthy value;
4397 * returns +self+:
4399 * a = [:foo, 'bar', 2, 'bat']
4400 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4402 * With no block given, returns a new Enumerator.
4404 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4407 static VALUE
4408 rb_ary_delete_if(VALUE ary)
4410 ary_verify(ary);
4411 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4412 ary_reject_bang(ary);
4413 return ary;
4416 static VALUE
4417 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4419 VALUE *args = (VALUE *)cbarg;
4420 if (argc > 1) val = rb_ary_new4(argc, argv);
4421 rb_ary_push(args[0], val);
4422 if (--args[1] == 0) rb_iter_break();
4423 return Qnil;
4426 static VALUE
4427 take_items(VALUE obj, long n)
4429 VALUE result = rb_check_array_type(obj);
4430 VALUE args[2];
4432 if (n == 0) return result;
4433 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4434 result = rb_ary_new2(n);
4435 args[0] = result; args[1] = (VALUE)n;
4436 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4437 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4438 rb_obj_class(obj));
4439 return result;
4444 * call-seq:
4445 * array.zip(*other_arrays) -> new_array
4446 * array.zip(*other_arrays) {|other_array| ... } -> nil
4448 * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
4449 * whose elements are Arrays.
4451 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4452 * and contains:
4454 * - The _nth_ element of +self+.
4455 * - The _nth_ element of each of the +other_arrays+.
4457 * If all +other_arrays+ and +self+ are the same size:
4459 * a = [:a0, :a1, :a2, :a3]
4460 * b = [:b0, :b1, :b2, :b3]
4461 * c = [:c0, :c1, :c2, :c3]
4462 * d = a.zip(b, c)
4463 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4465 * If any array in +other_arrays+ is smaller than +self+,
4466 * fills to <tt>self.size</tt> with +nil+:
4468 * a = [:a0, :a1, :a2, :a3]
4469 * b = [:b0, :b1, :b2]
4470 * c = [:c0, :c1]
4471 * d = a.zip(b, c)
4472 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4474 * If any array in +other_arrays+ is larger than +self+,
4475 * its trailing elements are ignored:
4477 * a = [:a0, :a1, :a2, :a3]
4478 * b = [:b0, :b1, :b2, :b3, :b4]
4479 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4480 * d = a.zip(b, c)
4481 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4483 * If an argument is not an array, it extracts the values by calling #each:
4485 * a = [:a0, :a1, :a2, :a2]
4486 * b = 1..4
4487 * c = a.zip(b)
4488 * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
4490 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
4492 * a = [:a0, :a1, :a2, :a3]
4493 * b = [:b0, :b1, :b2, :b3]
4494 * c = [:c0, :c1, :c2, :c3]
4495 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4497 * Output:
4499 * [:a0, :b0, :c0]
4500 * [:a1, :b1, :c1]
4501 * [:a2, :b2, :c2]
4502 * [:a3, :b3, :c3]
4506 static VALUE
4507 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4509 int i, j;
4510 long len = RARRAY_LEN(ary);
4511 VALUE result = Qnil;
4513 for (i=0; i<argc; i++) {
4514 argv[i] = take_items(argv[i], len);
4517 if (rb_block_given_p()) {
4518 int arity = rb_block_arity();
4520 if (arity > 1) {
4521 VALUE work, *tmp;
4523 tmp = ALLOCV_N(VALUE, work, argc+1);
4525 for (i=0; i<RARRAY_LEN(ary); i++) {
4526 tmp[0] = RARRAY_AREF(ary, i);
4527 for (j=0; j<argc; j++) {
4528 tmp[j+1] = rb_ary_elt(argv[j], i);
4530 rb_yield_values2(argc+1, tmp);
4533 if (work) ALLOCV_END(work);
4535 else {
4536 for (i=0; i<RARRAY_LEN(ary); i++) {
4537 VALUE tmp = rb_ary_new2(argc+1);
4539 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4540 for (j=0; j<argc; j++) {
4541 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4543 rb_yield(tmp);
4547 else {
4548 result = rb_ary_new_capa(len);
4550 for (i=0; i<len; i++) {
4551 VALUE tmp = rb_ary_new_capa(argc+1);
4553 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4554 for (j=0; j<argc; j++) {
4555 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4557 rb_ary_push(result, tmp);
4561 return result;
4565 * call-seq:
4566 * array.transpose -> new_array
4568 * Transposes the rows and columns in an +Array+ of Arrays;
4569 * the nested Arrays must all be the same size:
4571 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4572 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4576 static VALUE
4577 rb_ary_transpose(VALUE ary)
4579 long elen = -1, alen, i, j;
4580 VALUE tmp, result = 0;
4582 alen = RARRAY_LEN(ary);
4583 if (alen == 0) return rb_ary_dup(ary);
4584 for (i=0; i<alen; i++) {
4585 tmp = to_ary(rb_ary_elt(ary, i));
4586 if (elen < 0) { /* first element */
4587 elen = RARRAY_LEN(tmp);
4588 result = rb_ary_new2(elen);
4589 for (j=0; j<elen; j++) {
4590 rb_ary_store(result, j, rb_ary_new2(alen));
4593 else if (elen != RARRAY_LEN(tmp)) {
4594 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4595 RARRAY_LEN(tmp), elen);
4597 for (j=0; j<elen; j++) {
4598 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4601 return result;
4605 * call-seq:
4606 * array.replace(other_array) -> self
4608 * Replaces the content of +self+ with the content of +other_array+; returns +self+:
4610 * a = [:foo, 'bar', 2]
4611 * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3]
4615 VALUE
4616 rb_ary_replace(VALUE copy, VALUE orig)
4618 rb_ary_modify_check(copy);
4619 orig = to_ary(orig);
4620 if (copy == orig) return copy;
4622 rb_ary_reset(copy);
4624 /* orig has enough space to embed the contents of orig. */
4625 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4626 RUBY_ASSERT(ARY_EMBED_P(copy));
4627 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4628 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4630 /* orig is embedded but copy does not have enough space to embed the
4631 * contents of orig. */
4632 else if (ARY_EMBED_P(orig)) {
4633 long len = ARY_EMBED_LEN(orig);
4634 VALUE *ptr = ary_heap_alloc_buffer(len);
4636 FL_UNSET_EMBED(copy);
4637 ARY_SET_PTR(copy, ptr);
4638 ARY_SET_LEN(copy, len);
4639 ARY_SET_CAPA(copy, len);
4641 // No allocation and exception expected that could leave `copy` in a
4642 // bad state from the edits above.
4643 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
4645 /* Otherwise, orig is on heap and copy does not have enough space to embed
4646 * the contents of orig. */
4647 else {
4648 VALUE shared_root = ary_make_shared(orig);
4649 FL_UNSET_EMBED(copy);
4650 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4651 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4652 rb_ary_set_shared(copy, shared_root);
4654 ary_verify(copy);
4655 return copy;
4659 * call-seq:
4660 * clear -> self
4662 * Removes all elements from +self+; returns +self+:
4664 * a = [:foo, 'bar', 2]
4665 * a.clear # => []
4667 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4670 VALUE
4671 rb_ary_clear(VALUE ary)
4673 rb_ary_modify_check(ary);
4674 if (ARY_SHARED_P(ary)) {
4675 rb_ary_unshare(ary);
4676 FL_SET_EMBED(ary);
4677 ARY_SET_EMBED_LEN(ary, 0);
4679 else {
4680 ARY_SET_LEN(ary, 0);
4681 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4682 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4685 ary_verify(ary);
4686 return ary;
4690 * call-seq:
4691 * array.fill(obj) -> self
4692 * array.fill(obj, start) -> self
4693 * array.fill(obj, start, length) -> self
4694 * array.fill(obj, range) -> self
4695 * array.fill {|index| ... } -> self
4696 * array.fill(start) {|index| ... } -> self
4697 * array.fill(start, length) {|index| ... } -> self
4698 * array.fill(range) {|index| ... } -> self
4700 * Replaces specified elements in +self+ with specified objects; returns +self+.
4702 * With argument +obj+ and no block given, replaces all elements with that one object:
4704 * a = ['a', 'b', 'c', 'd']
4705 * a # => ["a", "b", "c", "d"]
4706 * a.fill(:X) # => [:X, :X, :X, :X]
4708 * With arguments +obj+ and Integer +start+, and no block given,
4709 * replaces elements based on the given start.
4711 * If +start+ is in range (<tt>0 <= start < array.size</tt>),
4712 * replaces all elements from offset +start+ through the end:
4714 * a = ['a', 'b', 'c', 'd']
4715 * a.fill(:X, 2) # => ["a", "b", :X, :X]
4717 * If +start+ is too large (<tt>start >= array.size</tt>), does nothing:
4719 * a = ['a', 'b', 'c', 'd']
4720 * a.fill(:X, 4) # => ["a", "b", "c", "d"]
4721 * a = ['a', 'b', 'c', 'd']
4722 * a.fill(:X, 5) # => ["a", "b", "c", "d"]
4724 * If +start+ is negative, counts from the end (starting index is <tt>start + array.size</tt>):
4726 * a = ['a', 'b', 'c', 'd']
4727 * a.fill(:X, -2) # => ["a", "b", :X, :X]
4729 * If +start+ is too small (less than and far from zero), replaces all elements:
4731 * a = ['a', 'b', 'c', 'd']
4732 * a.fill(:X, -6) # => [:X, :X, :X, :X]
4733 * a = ['a', 'b', 'c', 'd']
4734 * a.fill(:X, -50) # => [:X, :X, :X, :X]
4736 * With arguments +obj+, Integer +start+, and Integer +length+, and no block given,
4737 * replaces elements based on the given +start+ and +length+.
4739 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4741 * a = ['a', 'b', 'c', 'd']
4742 * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"]
4744 * If +start+ is negative, counts from the end:
4746 * a = ['a', 'b', 'c', 'd']
4747 * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"]
4749 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4751 * a = ['a', 'b', 'c', 'd']
4752 * a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil]
4753 * a = ['a', 'b', 'c', 'd']
4754 * a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X]
4756 * If +length+ is zero or negative, replaces no elements:
4758 * a = ['a', 'b', 'c', 'd']
4759 * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"]
4760 * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"]
4762 * With arguments +obj+ and Range +range+, and no block given,
4763 * replaces elements based on the given range.
4765 * If the range is positive and ascending (<tt>0 < range.begin <= range.end</tt>),
4766 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4768 * a = ['a', 'b', 'c', 'd']
4769 * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"]
4771 * If <tt>range.first</tt> is negative, replaces no elements:
4773 * a = ['a', 'b', 'c', 'd']
4774 * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"]
4776 * If <tt>range.last</tt> is negative, counts from the end:
4778 * a = ['a', 'b', 'c', 'd']
4779 * a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"]
4780 * a = ['a', 'b', 'c', 'd']
4781 * a.fill(:X, (1..-2)) # => ["a", :X, :X, "d"]
4783 * If <tt>range.last</tt> and <tt>range.last</tt> are both negative,
4784 * both count from the end of the array:
4786 * a = ['a', 'b', 'c', 'd']
4787 * a.fill(:X, (-1..-1)) # => ["a", "b", "c", :X]
4788 * a = ['a', 'b', 'c', 'd']
4789 * a.fill(:X, (-2..-2)) # => ["a", "b", :X, "d"]
4791 * With no arguments and a block given, calls the block with each index;
4792 * replaces the corresponding element with the block's return value:
4794 * a = ['a', 'b', 'c', 'd']
4795 * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4797 * With argument +start+ and a block given, calls the block with each index
4798 * from offset +start+ to the end; replaces the corresponding element
4799 * with the block's return value.
4801 * If start is in range (<tt>0 <= start < array.size</tt>),
4802 * replaces from offset +start+ to the end:
4804 * a = ['a', 'b', 'c', 'd']
4805 * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"]
4807 * If +start+ is too large(<tt>start >= array.size</tt>), does nothing:
4809 * a = ['a', 'b', 'c', 'd']
4810 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4811 * a = ['a', 'b', 'c', 'd']
4812 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4814 * If +start+ is negative, counts from the end:
4816 * a = ['a', 'b', 'c', 'd']
4817 * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"]
4819 * If start is too small (<tt>start <= -array.size</tt>, replaces all elements:
4821 * a = ['a', 'b', 'c', 'd']
4822 * a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4823 * a = ['a', 'b', 'c', 'd']
4824 * a.fill(-50) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4826 * With arguments +start+ and +length+, and a block given,
4827 * calls the block for each index specified by start length;
4828 * replaces the corresponding element with the block's return value.
4830 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4832 * a = ['a', 'b', 'c', 'd']
4833 * a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4835 * If start is negative, counts from the end:
4837 * a = ['a', 'b', 'c', 'd']
4838 * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4840 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4842 * a = ['a', 'b', 'c', 'd']
4843 * a.fill(5, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil]
4844 * a = ['a', 'b', 'c', 'd']
4845 * a.fill(5, 2) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil, "new_5", "new_6"]
4847 * If +length+ is zero or less, replaces no elements:
4849 * a = ['a', 'b', 'c', 'd']
4850 * a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4851 * a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4853 * With arguments +obj+ and +range+, and a block given,
4854 * calls the block with each index in the given range;
4855 * replaces the corresponding element with the block's return value.
4857 * If the range is positive and ascending (<tt>range 0 < range.begin <= range.end</tt>,
4858 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4860 * a = ['a', 'b', 'c', 'd']
4861 * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4863 * If +range.first+ is negative, does nothing:
4865 * a = ['a', 'b', 'c', 'd']
4866 * a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4868 * If <tt>range.last</tt> is negative, counts from the end:
4870 * a = ['a', 'b', 'c', 'd']
4871 * a.fill(0..-2) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "d"]
4872 * a = ['a', 'b', 'c', 'd']
4873 * a.fill(1..-2) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "d"]
4875 * If <tt>range.first</tt> and <tt>range.last</tt> are both negative,
4876 * both count from the end:
4878 * a = ['a', 'b', 'c', 'd']
4879 * a.fill(-1..-1) { |index| "new_#{index}" } # => ["a", "b", "c", "new_3"]
4880 * a = ['a', 'b', 'c', 'd']
4881 * a.fill(-2..-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4885 static VALUE
4886 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
4888 VALUE item = Qundef, arg1, arg2;
4889 long beg = 0, end = 0, len = 0;
4891 if (rb_block_given_p()) {
4892 rb_scan_args(argc, argv, "02", &arg1, &arg2);
4893 argc += 1; /* hackish */
4895 else {
4896 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
4898 switch (argc) {
4899 case 1:
4900 beg = 0;
4901 len = RARRAY_LEN(ary);
4902 break;
4903 case 2:
4904 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
4905 break;
4907 /* fall through */
4908 case 3:
4909 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
4910 if (beg < 0) {
4911 beg = RARRAY_LEN(ary) + beg;
4912 if (beg < 0) beg = 0;
4914 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
4915 break;
4917 rb_ary_modify(ary);
4918 if (len < 0) {
4919 return ary;
4921 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
4922 rb_raise(rb_eArgError, "argument too big");
4924 end = beg + len;
4925 if (RARRAY_LEN(ary) < end) {
4926 if (end >= ARY_CAPA(ary)) {
4927 ary_resize_capa(ary, end);
4929 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
4930 ARY_SET_LEN(ary, end);
4933 if (UNDEF_P(item)) {
4934 VALUE v;
4935 long i;
4937 for (i=beg; i<end; i++) {
4938 v = rb_yield(LONG2NUM(i));
4939 if (i>=RARRAY_LEN(ary)) break;
4940 ARY_SET(ary, i, v);
4943 else {
4944 ary_memfill(ary, beg, len, item);
4946 return ary;
4950 * call-seq:
4951 * self + other_array -> new_array
4953 * Returns a new array containing all elements of +self+
4954 * followed by all elements of +other_array+:
4956 * a = [0, 1] + [2, 3]
4957 * a # => [0, 1, 2, 3]
4959 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
4962 VALUE
4963 rb_ary_plus(VALUE x, VALUE y)
4965 VALUE z;
4966 long len, xlen, ylen;
4968 y = to_ary(y);
4969 xlen = RARRAY_LEN(x);
4970 ylen = RARRAY_LEN(y);
4971 len = xlen + ylen;
4972 z = rb_ary_new2(len);
4974 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
4975 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
4976 ARY_SET_LEN(z, len);
4977 return z;
4980 static VALUE
4981 ary_append(VALUE x, VALUE y)
4983 long n = RARRAY_LEN(y);
4984 if (n > 0) {
4985 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
4987 RB_GC_GUARD(y);
4988 return x;
4992 * call-seq:
4993 * concat(*other_arrays) -> self
4995 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
4997 * a = [0, 1]
4998 * a.concat(['two', 'three'], [:four, :five], a)
4999 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5001 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5004 static VALUE
5005 rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
5007 rb_ary_modify_check(ary);
5009 if (argc == 1) {
5010 rb_ary_concat(ary, argv[0]);
5012 else if (argc > 1) {
5013 int i;
5014 VALUE args = rb_ary_hidden_new(argc);
5015 for (i = 0; i < argc; i++) {
5016 rb_ary_concat(args, argv[i]);
5018 ary_append(ary, args);
5021 ary_verify(ary);
5022 return ary;
5025 VALUE
5026 rb_ary_concat(VALUE x, VALUE y)
5028 return ary_append(x, to_ary(y));
5032 * call-seq:
5033 * self * n -> new_array
5034 * self * string_separator -> new_string
5036 * When non-negative integer argument +n+ is given,
5037 * returns a new array built by concatenating +n+ copies of +self+:
5039 * a = ['x', 'y']
5040 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5042 * When string argument +string_separator+ is given,
5043 * equivalent to <tt>array.join(string_separator)</tt>:
5045 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
5049 static VALUE
5050 rb_ary_times(VALUE ary, VALUE times)
5052 VALUE ary2, tmp;
5053 const VALUE *ptr;
5054 long t, len;
5056 tmp = rb_check_string_type(times);
5057 if (!NIL_P(tmp)) {
5058 return rb_ary_join(ary, tmp);
5061 len = NUM2LONG(times);
5062 if (len == 0) {
5063 ary2 = ary_new(rb_cArray, 0);
5064 goto out;
5066 if (len < 0) {
5067 rb_raise(rb_eArgError, "negative argument");
5069 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
5070 rb_raise(rb_eArgError, "argument too big");
5072 len *= RARRAY_LEN(ary);
5074 ary2 = ary_new(rb_cArray, len);
5075 ARY_SET_LEN(ary2, len);
5077 ptr = RARRAY_CONST_PTR(ary);
5078 t = RARRAY_LEN(ary);
5079 if (0 < t) {
5080 ary_memcpy(ary2, 0, t, ptr);
5081 while (t <= len/2) {
5082 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5083 t *= 2;
5085 if (t < len) {
5086 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5089 out:
5090 return ary2;
5094 * call-seq:
5095 * assoc(object) -> found_array or nil
5097 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5098 * and <tt>ele[0] == object</tt>:
5100 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5101 * a.assoc(4) # => [4, 5, 6]
5103 * Returns +nil+ if no such element is found.
5105 * Related: Array#rassoc;
5106 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5109 VALUE
5110 rb_ary_assoc(VALUE ary, VALUE key)
5112 long i;
5113 VALUE v;
5115 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5116 v = rb_check_array_type(RARRAY_AREF(ary, i));
5117 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5118 rb_equal(RARRAY_AREF(v, 0), key))
5119 return v;
5121 return Qnil;
5125 * call-seq:
5126 * array.rassoc(obj) -> found_array or nil
5128 * Returns the first element in +self+ that is an +Array+
5129 * whose second element <tt>==</tt> +obj+:
5131 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5132 * a.rassoc(4) # => [2, 4]
5134 * Returns +nil+ if no such element is found.
5136 * Related: #assoc.
5139 VALUE
5140 rb_ary_rassoc(VALUE ary, VALUE value)
5142 long i;
5143 VALUE v;
5145 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5146 v = rb_check_array_type(RARRAY_AREF(ary, i));
5147 if (RB_TYPE_P(v, T_ARRAY) &&
5148 RARRAY_LEN(v) > 1 &&
5149 rb_equal(RARRAY_AREF(v, 1), value))
5150 return v;
5152 return Qnil;
5155 static VALUE
5156 recursive_equal(VALUE ary1, VALUE ary2, int recur)
5158 long i, len1;
5159 const VALUE *p1, *p2;
5161 if (recur) return Qtrue; /* Subtle! */
5163 /* rb_equal() can evacuate ptrs */
5164 p1 = RARRAY_CONST_PTR(ary1);
5165 p2 = RARRAY_CONST_PTR(ary2);
5166 len1 = RARRAY_LEN(ary1);
5168 for (i = 0; i < len1; i++) {
5169 if (*p1 != *p2) {
5170 if (rb_equal(*p1, *p2)) {
5171 len1 = RARRAY_LEN(ary1);
5172 if (len1 != RARRAY_LEN(ary2))
5173 return Qfalse;
5174 if (len1 < i)
5175 return Qtrue;
5176 p1 = RARRAY_CONST_PTR(ary1) + i;
5177 p2 = RARRAY_CONST_PTR(ary2) + i;
5179 else {
5180 return Qfalse;
5183 p1++;
5184 p2++;
5186 return Qtrue;
5190 * call-seq:
5191 * self == other_array -> true or false
5193 * Returns whether both:
5195 * - +self+ and +other_array+ are the same size.
5196 * - Their corresponding elements are the same;
5197 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5198 * <tt>self[i] == other_array[i]</tt>.
5200 * Examples:
5202 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5203 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5204 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5205 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5207 * This method is different from method Array#eql?,
5208 * which compares elements using <tt>Object#eql?</tt>.
5210 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5213 static VALUE
5214 rb_ary_equal(VALUE ary1, VALUE ary2)
5216 if (ary1 == ary2) return Qtrue;
5217 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5218 if (!rb_respond_to(ary2, idTo_ary)) {
5219 return Qfalse;
5221 return rb_equal(ary2, ary1);
5223 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5224 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5225 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5228 static VALUE
5229 recursive_eql(VALUE ary1, VALUE ary2, int recur)
5231 long i;
5233 if (recur) return Qtrue; /* Subtle! */
5234 for (i=0; i<RARRAY_LEN(ary1); i++) {
5235 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5236 return Qfalse;
5238 return Qtrue;
5242 * call-seq:
5243 * eql?(other_array) -> true or false
5245 * Returns +true+ if +self+ and +other_array+ are the same size,
5246 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5248 * a0 = [:foo, 'bar', 2]
5249 * a1 = [:foo, 'bar', 2]
5250 * a1.eql?(a0) # => true
5252 * Otherwise, returns +false+.
5254 * This method is different from method Array#==,
5255 * which compares using method <tt>Object#==</tt>.
5257 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5260 static VALUE
5261 rb_ary_eql(VALUE ary1, VALUE ary2)
5263 if (ary1 == ary2) return Qtrue;
5264 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5265 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5266 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5267 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5270 VALUE
5271 rb_ary_hash_values(long len, const VALUE *elements)
5273 long i;
5274 st_index_t h;
5275 VALUE n;
5277 h = rb_hash_start(len);
5278 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5279 for (i=0; i<len; i++) {
5280 n = rb_hash(elements[i]);
5281 h = rb_hash_uint(h, NUM2LONG(n));
5283 h = rb_hash_end(h);
5284 return ST2FIX(h);
5288 * call-seq:
5289 * array.hash -> integer
5291 * Returns the integer hash value for +self+.
5293 * Two arrays with the same content will have the same hash code (and will compare using #eql?):
5295 * [0, 1, 2].hash == [0, 1, 2].hash # => true
5296 * [0, 1, 2].hash == [0, 1, 3].hash # => false
5300 static VALUE
5301 rb_ary_hash(VALUE ary)
5303 return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
5307 * call-seq:
5308 * array.include?(obj) -> true or false
5310 * Returns +true+ if for some index +i+ in +self+, <tt>obj == self[i]</tt>;
5311 * otherwise +false+:
5313 * [0, 1, 2].include?(2) # => true
5314 * [0, 1, 2].include?(3) # => false
5317 VALUE
5318 rb_ary_includes(VALUE ary, VALUE item)
5320 long i;
5321 VALUE e;
5323 for (i=0; i<RARRAY_LEN(ary); i++) {
5324 e = RARRAY_AREF(ary, i);
5325 if (rb_equal(e, item)) {
5326 return Qtrue;
5329 return Qfalse;
5332 static VALUE
5333 rb_ary_includes_by_eql(VALUE ary, VALUE item)
5335 long i;
5336 VALUE e;
5338 for (i=0; i<RARRAY_LEN(ary); i++) {
5339 e = RARRAY_AREF(ary, i);
5340 if (rb_eql(item, e)) {
5341 return Qtrue;
5344 return Qfalse;
5347 static VALUE
5348 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5350 long i, len;
5352 if (recur) return Qundef; /* Subtle! */
5353 len = RARRAY_LEN(ary1);
5354 if (len > RARRAY_LEN(ary2)) {
5355 len = RARRAY_LEN(ary2);
5357 for (i=0; i<len; i++) {
5358 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5359 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5360 if (v != INT2FIX(0)) {
5361 return v;
5364 return Qundef;
5368 * call-seq:
5369 * self <=> other_array -> -1, 0, or 1
5371 * Returns -1, 0, or 1 as +self+ is determined
5372 * to be less than, equal to, or greater than +other_array+.
5374 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5376 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5377 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5379 * [0, 1, 2] <=> [0, 0, 2] # => 1
5381 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5383 * [0, 1, 2] <=> [0, 2, 2] # => -1
5385 * - Continues if <tt>result[i]</tt> is 0.
5387 * When every +result+ is 0,
5388 * returns <tt>self.size <=> other_array.size</tt>
5389 * (see Integer#<=>):
5391 * [0, 1, 2] <=> [0, 1] # => 1
5392 * [0, 1, 2] <=> [0, 1, 2] # => 0
5393 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5395 * Note that when +other_array+ is larger than +self+,
5396 * its trailing elements do not affect the result:
5398 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5399 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5400 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5402 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5405 VALUE
5406 rb_ary_cmp(VALUE ary1, VALUE ary2)
5408 long len;
5409 VALUE v;
5411 ary2 = rb_check_array_type(ary2);
5412 if (NIL_P(ary2)) return Qnil;
5413 if (ary1 == ary2) return INT2FIX(0);
5414 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5415 if (!UNDEF_P(v)) return v;
5416 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5417 if (len == 0) return INT2FIX(0);
5418 if (len > 0) return INT2FIX(1);
5419 return INT2FIX(-1);
5422 static VALUE
5423 ary_add_hash(VALUE hash, VALUE ary)
5425 long i;
5427 for (i=0; i<RARRAY_LEN(ary); i++) {
5428 VALUE elt = RARRAY_AREF(ary, i);
5429 rb_hash_add_new_element(hash, elt, elt);
5431 return hash;
5434 static inline VALUE
5435 ary_tmp_hash_new(VALUE ary)
5437 long size = RARRAY_LEN(ary);
5438 VALUE hash = rb_hash_new_with_size(size);
5440 RBASIC_CLEAR_CLASS(hash);
5441 return hash;
5444 static VALUE
5445 ary_make_hash(VALUE ary)
5447 VALUE hash = ary_tmp_hash_new(ary);
5448 return ary_add_hash(hash, ary);
5451 static VALUE
5452 ary_add_hash_by(VALUE hash, VALUE ary)
5454 long i;
5456 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5457 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5458 rb_hash_add_new_element(hash, k, v);
5460 return hash;
5463 static VALUE
5464 ary_make_hash_by(VALUE ary)
5466 VALUE hash = ary_tmp_hash_new(ary);
5467 return ary_add_hash_by(hash, ary);
5471 * call-seq:
5472 * self - other_array -> new_array
5474 * Returns a new array containing only those elements of +self+
5475 * that are not found in +other_array+;
5476 * the order from +self+ is preserved:
5478 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5479 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5480 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5482 * Element are compared using method <tt>#eql?</tt>
5483 * (as defined in each element of +self+).
5485 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5488 VALUE
5489 rb_ary_diff(VALUE ary1, VALUE ary2)
5491 VALUE ary3;
5492 VALUE hash;
5493 long i;
5495 ary2 = to_ary(ary2);
5496 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5497 ary3 = rb_ary_new();
5499 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5500 for (i=0; i<RARRAY_LEN(ary1); i++) {
5501 VALUE elt = rb_ary_elt(ary1, i);
5502 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5503 rb_ary_push(ary3, elt);
5505 return ary3;
5508 hash = ary_make_hash(ary2);
5509 for (i=0; i<RARRAY_LEN(ary1); i++) {
5510 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5511 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5514 return ary3;
5518 * call-seq:
5519 * difference(*other_arrays = []) -> new_array
5521 * Returns a new array containing only those elements from +self+
5522 * that are not found in any of the given +other_arrays+;
5523 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5525 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5526 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5527 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5528 * [0, 1, 2].difference # => [0, 1, 2]
5530 * Returns a copy of +self+ if no arguments are given.
5532 * Related: Array#-;
5533 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5536 static VALUE
5537 rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5539 VALUE ary_diff;
5540 long i, length;
5541 volatile VALUE t0;
5542 bool *is_hash = ALLOCV_N(bool, t0, argc);
5543 ary_diff = rb_ary_new();
5544 length = RARRAY_LEN(ary);
5546 for (i = 0; i < argc; i++) {
5547 argv[i] = to_ary(argv[i]);
5548 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5549 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5552 for (i = 0; i < RARRAY_LEN(ary); i++) {
5553 int j;
5554 VALUE elt = rb_ary_elt(ary, i);
5555 for (j = 0; j < argc; j++) {
5556 if (is_hash[j]) {
5557 if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
5558 break;
5560 else {
5561 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5564 if (j == argc) rb_ary_push(ary_diff, elt);
5567 ALLOCV_END(t0);
5569 return ary_diff;
5574 * call-seq:
5575 * self & other_array -> new_array
5577 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5578 * that is, containing those elements found in both +self+ and +other_array+:
5580 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5582 * Omits duplicates:
5584 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5586 * Preserves order from +self+:
5588 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5590 * Identifies common elements using method <tt>#eql?</tt>
5591 * (as defined in each element of +self+).
5593 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5597 static VALUE
5598 rb_ary_and(VALUE ary1, VALUE ary2)
5600 VALUE hash, ary3, v;
5601 st_data_t vv;
5602 long i;
5604 ary2 = to_ary(ary2);
5605 ary3 = rb_ary_new();
5606 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5608 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5609 for (i=0; i<RARRAY_LEN(ary1); i++) {
5610 v = RARRAY_AREF(ary1, i);
5611 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5612 if (rb_ary_includes_by_eql(ary3, v)) continue;
5613 rb_ary_push(ary3, v);
5615 return ary3;
5618 hash = ary_make_hash(ary2);
5620 for (i=0; i<RARRAY_LEN(ary1); i++) {
5621 v = RARRAY_AREF(ary1, i);
5622 vv = (st_data_t)v;
5623 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5624 rb_ary_push(ary3, v);
5628 return ary3;
5632 * call-seq:
5633 * array.intersection(*other_arrays) -> new_array
5635 * Returns a new +Array+ containing each element found both in +self+
5636 * and in all of the given Arrays +other_arrays+;
5637 * duplicates are omitted; items are compared using <tt>eql?</tt>
5638 * (items must also implement +hash+ correctly):
5640 * [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5641 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5643 * Preserves order from +self+:
5645 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5647 * Returns a copy of +self+ if no arguments given.
5649 * Related: Array#&.
5652 static VALUE
5653 rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5655 VALUE result = rb_ary_dup(ary);
5656 int i;
5658 for (i = 0; i < argc; i++) {
5659 result = rb_ary_and(result, argv[i]);
5662 return result;
5665 static int
5666 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5668 if (existing) return ST_STOP;
5669 *key = *value = (VALUE)arg;
5670 return ST_CONTINUE;
5673 static void
5674 rb_ary_union(VALUE ary_union, VALUE ary)
5676 long i;
5677 for (i = 0; i < RARRAY_LEN(ary); i++) {
5678 VALUE elt = rb_ary_elt(ary, i);
5679 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5680 rb_ary_push(ary_union, elt);
5684 static void
5685 rb_ary_union_hash(VALUE hash, VALUE ary2)
5687 long i;
5688 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5689 VALUE elt = RARRAY_AREF(ary2, i);
5690 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5691 RB_OBJ_WRITTEN(hash, Qundef, elt);
5697 * call-seq:
5698 * array | other_array -> new_array
5700 * Returns the union of +array+ and +Array+ +other_array+;
5701 * duplicates are removed; order is preserved;
5702 * items are compared using <tt>eql?</tt>:
5704 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5705 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5706 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5708 * Related: Array#union.
5711 static VALUE
5712 rb_ary_or(VALUE ary1, VALUE ary2)
5714 VALUE hash;
5716 ary2 = to_ary(ary2);
5717 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5718 VALUE ary3 = rb_ary_new();
5719 rb_ary_union(ary3, ary1);
5720 rb_ary_union(ary3, ary2);
5721 return ary3;
5724 hash = ary_make_hash(ary1);
5725 rb_ary_union_hash(hash, ary2);
5727 return rb_hash_values(hash);
5731 * call-seq:
5732 * array.union(*other_arrays) -> new_array
5734 * Returns a new +Array+ that is the union of +self+ and all given Arrays +other_arrays+;
5735 * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
5737 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5738 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5739 * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
5741 * Returns a copy of +self+ if no arguments given.
5743 * Related: Array#|.
5746 static VALUE
5747 rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
5749 int i;
5750 long sum;
5751 VALUE hash;
5753 sum = RARRAY_LEN(ary);
5754 for (i = 0; i < argc; i++) {
5755 argv[i] = to_ary(argv[i]);
5756 sum += RARRAY_LEN(argv[i]);
5759 if (sum <= SMALL_ARRAY_LEN) {
5760 VALUE ary_union = rb_ary_new();
5762 rb_ary_union(ary_union, ary);
5763 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5765 return ary_union;
5768 hash = ary_make_hash(ary);
5769 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5771 return rb_hash_values(hash);
5775 * call-seq:
5776 * ary.intersect?(other_ary) -> true or false
5778 * Returns +true+ if the array and +other_ary+ have at least one element in
5779 * common, otherwise returns +false+:
5781 * a = [ 1, 2, 3 ]
5782 * b = [ 3, 4, 5 ]
5783 * c = [ 5, 6, 7 ]
5784 * a.intersect?(b) #=> true
5785 * a.intersect?(c) #=> false
5787 * +Array+ elements are compared using <tt>eql?</tt>
5788 * (items must also implement +hash+ correctly).
5791 static VALUE
5792 rb_ary_intersect_p(VALUE ary1, VALUE ary2)
5794 VALUE hash, v, result, shorter, longer;
5795 st_data_t vv;
5796 long i;
5798 ary2 = to_ary(ary2);
5799 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
5801 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5802 for (i=0; i<RARRAY_LEN(ary1); i++) {
5803 v = RARRAY_AREF(ary1, i);
5804 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
5806 return Qfalse;
5809 shorter = ary1;
5810 longer = ary2;
5811 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
5812 longer = ary1;
5813 shorter = ary2;
5816 hash = ary_make_hash(shorter);
5817 result = Qfalse;
5819 for (i=0; i<RARRAY_LEN(longer); i++) {
5820 v = RARRAY_AREF(longer, i);
5821 vv = (st_data_t)v;
5822 if (rb_hash_stlike_lookup(hash, vv, 0)) {
5823 result = Qtrue;
5824 break;
5828 return result;
5831 static VALUE
5832 ary_max_generic(VALUE ary, long i, VALUE vmax)
5834 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5836 VALUE v;
5837 for (; i < RARRAY_LEN(ary); ++i) {
5838 v = RARRAY_AREF(ary, i);
5840 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
5841 vmax = v;
5845 return vmax;
5848 static VALUE
5849 ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
5851 const long n = RARRAY_LEN(ary);
5852 RUBY_ASSERT(i > 0 && i < n);
5853 RUBY_ASSERT(FIXNUM_P(vmax));
5855 VALUE v;
5856 for (; i < n; ++i) {
5857 v = RARRAY_AREF(ary, i);
5859 if (FIXNUM_P(v)) {
5860 if ((long)vmax < (long)v) {
5861 vmax = v;
5864 else {
5865 return ary_max_generic(ary, i, vmax);
5869 return vmax;
5872 static VALUE
5873 ary_max_opt_float(VALUE ary, long i, VALUE vmax)
5875 const long n = RARRAY_LEN(ary);
5876 RUBY_ASSERT(i > 0 && i < n);
5877 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax));
5879 VALUE v;
5880 for (; i < n; ++i) {
5881 v = RARRAY_AREF(ary, i);
5883 if (RB_FLOAT_TYPE_P(v)) {
5884 if (rb_float_cmp(vmax, v) < 0) {
5885 vmax = v;
5888 else {
5889 return ary_max_generic(ary, i, vmax);
5893 return vmax;
5896 static VALUE
5897 ary_max_opt_string(VALUE ary, long i, VALUE vmax)
5899 const long n = RARRAY_LEN(ary);
5900 RUBY_ASSERT(i > 0 && i < n);
5901 RUBY_ASSERT(STRING_P(vmax));
5903 VALUE v;
5904 for (; i < n; ++i) {
5905 v = RARRAY_AREF(ary, i);
5907 if (STRING_P(v)) {
5908 if (rb_str_cmp(vmax, v) < 0) {
5909 vmax = v;
5912 else {
5913 return ary_max_generic(ary, i, vmax);
5917 return vmax;
5921 * call-seq:
5922 * array.max -> element
5923 * array.max {|a, b| ... } -> element
5924 * array.max(n) -> new_array
5925 * array.max(n) {|a, b| ... } -> new_array
5927 * Returns one of the following:
5929 * - The maximum-valued element from +self+.
5930 * - A new +Array+ of maximum-valued elements selected from +self+.
5932 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5933 * with an Integer.
5935 * With no argument and no block, returns the element in +self+
5936 * having the maximum value per method <tt><=></tt>:
5938 * [0, 1, 2].max # => 2
5940 * With an argument Integer +n+ and no block, returns a new +Array+ with at most +n+ elements,
5941 * in descending order per method <tt><=></tt>:
5943 * [0, 1, 2, 3].max(3) # => [3, 2, 1]
5944 * [0, 1, 2, 3].max(6) # => [3, 2, 1, 0]
5946 * When a block is given, the block must return an Integer.
5948 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
5949 * returns the element having the maximum value per the block:
5951 * ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000"
5953 * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
5954 * in descending order per the block:
5956 * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
5959 static VALUE
5960 rb_ary_max(int argc, VALUE *argv, VALUE ary)
5962 VALUE result = Qundef, v;
5963 VALUE num;
5964 long i;
5966 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
5967 return rb_nmin_run(ary, num, 0, 1, 1);
5969 const long n = RARRAY_LEN(ary);
5970 if (rb_block_given_p()) {
5971 for (i = 0; i < RARRAY_LEN(ary); i++) {
5972 v = RARRAY_AREF(ary, i);
5973 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
5974 result = v;
5978 else if (n > 0) {
5979 result = RARRAY_AREF(ary, 0);
5980 if (n > 1) {
5981 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
5982 return ary_max_opt_fixnum(ary, 1, result);
5984 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
5985 return ary_max_opt_string(ary, 1, result);
5987 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
5988 return ary_max_opt_float(ary, 1, result);
5990 else {
5991 return ary_max_generic(ary, 1, result);
5995 if (UNDEF_P(result)) return Qnil;
5996 return result;
5999 static VALUE
6000 ary_min_generic(VALUE ary, long i, VALUE vmin)
6002 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6004 VALUE v;
6005 for (; i < RARRAY_LEN(ary); ++i) {
6006 v = RARRAY_AREF(ary, i);
6008 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
6009 vmin = v;
6013 return vmin;
6016 static VALUE
6017 ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
6019 const long n = RARRAY_LEN(ary);
6020 RUBY_ASSERT(i > 0 && i < n);
6021 RUBY_ASSERT(FIXNUM_P(vmin));
6023 VALUE a;
6024 for (; i < n; ++i) {
6025 a = RARRAY_AREF(ary, i);
6027 if (FIXNUM_P(a)) {
6028 if ((long)vmin > (long)a) {
6029 vmin = a;
6032 else {
6033 return ary_min_generic(ary, i, vmin);
6037 return vmin;
6040 static VALUE
6041 ary_min_opt_float(VALUE ary, long i, VALUE vmin)
6043 const long n = RARRAY_LEN(ary);
6044 RUBY_ASSERT(i > 0 && i < n);
6045 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin));
6047 VALUE a;
6048 for (; i < n; ++i) {
6049 a = RARRAY_AREF(ary, i);
6051 if (RB_FLOAT_TYPE_P(a)) {
6052 if (rb_float_cmp(vmin, a) > 0) {
6053 vmin = a;
6056 else {
6057 return ary_min_generic(ary, i, vmin);
6061 return vmin;
6064 static VALUE
6065 ary_min_opt_string(VALUE ary, long i, VALUE vmin)
6067 const long n = RARRAY_LEN(ary);
6068 RUBY_ASSERT(i > 0 && i < n);
6069 RUBY_ASSERT(STRING_P(vmin));
6071 VALUE a;
6072 for (; i < n; ++i) {
6073 a = RARRAY_AREF(ary, i);
6075 if (STRING_P(a)) {
6076 if (rb_str_cmp(vmin, a) > 0) {
6077 vmin = a;
6080 else {
6081 return ary_min_generic(ary, i, vmin);
6085 return vmin;
6089 * call-seq:
6090 * array.min -> element
6091 * array.min { |a, b| ... } -> element
6092 * array.min(n) -> new_array
6093 * array.min(n) { |a, b| ... } -> new_array
6095 * Returns one of the following:
6097 * - The minimum-valued element from +self+.
6098 * - A new +Array+ of minimum-valued elements selected from +self+.
6100 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
6101 * with an Integer.
6103 * With no argument and no block, returns the element in +self+
6104 * having the minimum value per method <tt><=></tt>:
6106 * [0, 1, 2].min # => 0
6108 * With Integer argument +n+ and no block, returns a new +Array+ with at most +n+ elements,
6109 * in ascending order per method <tt><=></tt>:
6111 * [0, 1, 2, 3].min(3) # => [0, 1, 2]
6112 * [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
6114 * When a block is given, the block must return an Integer.
6116 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
6117 * returns the element having the minimum value per the block:
6119 * ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0"
6121 * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
6122 * in ascending order per the block:
6124 * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
6127 static VALUE
6128 rb_ary_min(int argc, VALUE *argv, VALUE ary)
6130 VALUE result = Qundef, v;
6131 VALUE num;
6132 long i;
6134 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6135 return rb_nmin_run(ary, num, 0, 0, 1);
6137 const long n = RARRAY_LEN(ary);
6138 if (rb_block_given_p()) {
6139 for (i = 0; i < RARRAY_LEN(ary); i++) {
6140 v = RARRAY_AREF(ary, i);
6141 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6142 result = v;
6146 else if (n > 0) {
6147 result = RARRAY_AREF(ary, 0);
6148 if (n > 1) {
6149 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6150 return ary_min_opt_fixnum(ary, 1, result);
6152 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6153 return ary_min_opt_string(ary, 1, result);
6155 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6156 return ary_min_opt_float(ary, 1, result);
6158 else {
6159 return ary_min_generic(ary, 1, result);
6163 if (UNDEF_P(result)) return Qnil;
6164 return result;
6168 * call-seq:
6169 * array.minmax -> [min_val, max_val]
6170 * array.minmax {|a, b| ... } -> [min_val, max_val]
6172 * Returns a new 2-element +Array+ containing the minimum and maximum values
6173 * from +self+, either per method <tt><=></tt> or per a given block:.
6175 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
6176 * with an Integer;
6177 * returns a new 2-element +Array+ containing the minimum and maximum values
6178 * from +self+, per method <tt><=></tt>:
6180 * [0, 1, 2].minmax # => [0, 2]
6182 * When a block is given, the block must return an Integer;
6183 * the block is called <tt>self.size-1</tt> times to compare elements;
6184 * returns a new 2-element +Array+ containing the minimum and maximum values
6185 * from +self+, per the block:
6187 * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
6190 static VALUE
6191 rb_ary_minmax(VALUE ary)
6193 if (rb_block_given_p()) {
6194 return rb_call_super(0, NULL);
6196 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6199 static int
6200 push_value(st_data_t key, st_data_t val, st_data_t ary)
6202 rb_ary_push((VALUE)ary, (VALUE)val);
6203 return ST_CONTINUE;
6207 * call-seq:
6208 * array.uniq! -> self or nil
6209 * array.uniq! {|element| ... } -> self or nil
6211 * Removes duplicate elements from +self+, the first occurrence always being retained;
6212 * returns +self+ if any elements removed, +nil+ otherwise.
6214 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6215 * to compare.
6217 * Returns +self+ if any elements removed:
6219 * a = [0, 0, 1, 1, 2, 2]
6220 * a.uniq! # => [0, 1, 2]
6222 * Returns +nil+ if no elements removed.
6224 * With a block given, calls the block for each element;
6225 * identifies (using method <tt>eql?</tt>) and removes
6226 * elements for which the block returns duplicate values.
6228 * Returns +self+ if any elements removed:
6230 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6231 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
6233 * Returns +nil+ if no elements removed.
6235 static VALUE
6236 rb_ary_uniq_bang(VALUE ary)
6238 VALUE hash;
6239 long hash_size;
6241 rb_ary_modify_check(ary);
6242 if (RARRAY_LEN(ary) <= 1)
6243 return Qnil;
6244 if (rb_block_given_p())
6245 hash = ary_make_hash_by(ary);
6246 else
6247 hash = ary_make_hash(ary);
6249 hash_size = RHASH_SIZE(hash);
6250 if (RARRAY_LEN(ary) == hash_size) {
6251 return Qnil;
6253 rb_ary_modify_check(ary);
6254 ARY_SET_LEN(ary, 0);
6255 if (ARY_SHARED_P(ary)) {
6256 rb_ary_unshare(ary);
6257 FL_SET_EMBED(ary);
6259 ary_resize_capa(ary, hash_size);
6260 rb_hash_foreach(hash, push_value, ary);
6262 return ary;
6266 * call-seq:
6267 * array.uniq -> new_array
6268 * array.uniq {|element| ... } -> new_array
6270 * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
6271 * the first occurrence always being retained.
6273 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
6274 * to compare:
6276 * a = [0, 0, 1, 1, 2, 2]
6277 * a.uniq # => [0, 1, 2]
6279 * With a block given, calls the block for each element;
6280 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
6281 * that is, those elements for which the block returns the same value:
6283 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6284 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6288 static VALUE
6289 rb_ary_uniq(VALUE ary)
6291 VALUE hash, uniq;
6293 if (RARRAY_LEN(ary) <= 1) {
6294 hash = 0;
6295 uniq = rb_ary_dup(ary);
6297 else if (rb_block_given_p()) {
6298 hash = ary_make_hash_by(ary);
6299 uniq = rb_hash_values(hash);
6301 else {
6302 hash = ary_make_hash(ary);
6303 uniq = rb_hash_values(hash);
6306 return uniq;
6310 * call-seq:
6311 * compact! -> self or nil
6313 * Removes all +nil+ elements from +self+;
6314 * Returns +self+ if any elements are removed, +nil+ otherwise:
6316 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6317 * a.compact! # => [0, false, "", [], {}]
6318 * a # => [0, false, "", [], {}]
6319 * a.compact! # => nil
6321 * Related: Array#compact;
6322 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6325 static VALUE
6326 rb_ary_compact_bang(VALUE ary)
6328 VALUE *p, *t, *end;
6329 long n;
6331 rb_ary_modify(ary);
6332 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6333 end = p + RARRAY_LEN(ary);
6335 while (t < end) {
6336 if (NIL_P(*t)) t++;
6337 else *p++ = *t++;
6339 n = p - RARRAY_CONST_PTR(ary);
6340 if (RARRAY_LEN(ary) == n) {
6341 return Qnil;
6343 ary_resize_smaller(ary, n);
6345 return ary;
6349 * call-seq:
6350 * compact -> new_array
6352 * Returns a new array containing only the non-+nil+ elements from +self+;
6353 * element order is preserved:
6355 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6356 * a.compact # => [0, false, "", [], {}]
6358 * Related: Array#compact!;
6359 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6362 static VALUE
6363 rb_ary_compact(VALUE ary)
6365 ary = rb_ary_dup(ary);
6366 rb_ary_compact_bang(ary);
6367 return ary;
6371 * call-seq:
6372 * count -> integer
6373 * count(object) -> integer
6374 * count {|element| ... } -> integer
6376 * Returns a count of specified elements.
6378 * With no argument and no block, returns the count of all elements:
6380 * [0, :one, 'two', 3, 3.0].count # => 5
6382 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6384 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6386 * With no argument and a block given, calls the block with each element;
6387 * returns the count of elements for which the block returns a truthy value:
6389 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6391 * With argument +object+ and a block given, issues a warning, ignores the block,
6392 * and returns the count of elements <tt>==</tt> to +object+.
6394 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6397 static VALUE
6398 rb_ary_count(int argc, VALUE *argv, VALUE ary)
6400 long i, n = 0;
6402 if (rb_check_arity(argc, 0, 1) == 0) {
6403 VALUE v;
6405 if (!rb_block_given_p())
6406 return LONG2NUM(RARRAY_LEN(ary));
6408 for (i = 0; i < RARRAY_LEN(ary); i++) {
6409 v = RARRAY_AREF(ary, i);
6410 if (RTEST(rb_yield(v))) n++;
6413 else {
6414 VALUE obj = argv[0];
6416 if (rb_block_given_p()) {
6417 rb_warn("given block not used");
6419 for (i = 0; i < RARRAY_LEN(ary); i++) {
6420 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6424 return LONG2NUM(n);
6427 static VALUE
6428 flatten(VALUE ary, int level)
6430 long i;
6431 VALUE stack, result, tmp = 0, elt;
6432 VALUE memo = Qfalse;
6434 for (i = 0; i < RARRAY_LEN(ary); i++) {
6435 elt = RARRAY_AREF(ary, i);
6436 tmp = rb_check_array_type(elt);
6437 if (!NIL_P(tmp)) {
6438 break;
6441 if (i == RARRAY_LEN(ary)) {
6442 return ary;
6445 result = ary_new(0, RARRAY_LEN(ary));
6446 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6447 ARY_SET_LEN(result, i);
6449 stack = ary_new(0, ARY_DEFAULT_SIZE);
6450 rb_ary_push(stack, ary);
6451 rb_ary_push(stack, LONG2NUM(i + 1));
6453 if (level < 0) {
6454 memo = rb_obj_hide(rb_ident_hash_new());
6455 rb_hash_aset(memo, ary, Qtrue);
6456 rb_hash_aset(memo, tmp, Qtrue);
6459 ary = tmp;
6460 i = 0;
6462 while (1) {
6463 while (i < RARRAY_LEN(ary)) {
6464 elt = RARRAY_AREF(ary, i++);
6465 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6466 rb_ary_push(result, elt);
6467 continue;
6469 tmp = rb_check_array_type(elt);
6470 if (RBASIC(result)->klass) {
6471 if (RTEST(memo)) {
6472 rb_hash_clear(memo);
6474 rb_raise(rb_eRuntimeError, "flatten reentered");
6476 if (NIL_P(tmp)) {
6477 rb_ary_push(result, elt);
6479 else {
6480 if (memo) {
6481 if (rb_hash_aref(memo, tmp) == Qtrue) {
6482 rb_hash_clear(memo);
6483 rb_raise(rb_eArgError, "tried to flatten recursive array");
6485 rb_hash_aset(memo, tmp, Qtrue);
6487 rb_ary_push(stack, ary);
6488 rb_ary_push(stack, LONG2NUM(i));
6489 ary = tmp;
6490 i = 0;
6493 if (RARRAY_LEN(stack) == 0) {
6494 break;
6496 if (memo) {
6497 rb_hash_delete(memo, ary);
6499 tmp = rb_ary_pop(stack);
6500 i = NUM2LONG(tmp);
6501 ary = rb_ary_pop(stack);
6504 if (memo) {
6505 rb_hash_clear(memo);
6508 RBASIC_SET_CLASS(result, rb_cArray);
6509 return result;
6513 * call-seq:
6514 * array.flatten! -> self or nil
6515 * array.flatten!(level) -> self or nil
6517 * Replaces each nested +Array+ in +self+ with the elements from that +Array+;
6518 * returns +self+ if any changes, +nil+ otherwise.
6520 * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
6522 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6523 * a.flatten!(1) # => [0, 1, [2, 3], 4, 5]
6524 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6525 * a.flatten!(2) # => [0, 1, 2, 3, 4, 5]
6526 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6527 * a.flatten!(3) # => [0, 1, 2, 3, 4, 5]
6528 * [0, 1, 2].flatten!(1) # => nil
6530 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6532 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6533 * a.flatten! # => [0, 1, 2, 3, 4, 5]
6534 * [0, 1, 2].flatten! # => nil
6535 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6536 * a.flatten!(-1) # => [0, 1, 2, 3, 4, 5]
6537 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6538 * a.flatten!(-2) # => [0, 1, 2, 3, 4, 5]
6539 * [0, 1, 2].flatten!(-1) # => nil
6543 static VALUE
6544 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6546 int mod = 0, level = -1;
6547 VALUE result, lv;
6549 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6550 rb_ary_modify_check(ary);
6551 if (!NIL_P(lv)) level = NUM2INT(lv);
6552 if (level == 0) return Qnil;
6554 result = flatten(ary, level);
6555 if (result == ary) {
6556 return Qnil;
6558 if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6559 rb_ary_replace(ary, result);
6560 if (mod) ARY_SET_EMBED_LEN(result, 0);
6562 return ary;
6566 * call-seq:
6567 * array.flatten -> new_array
6568 * array.flatten(level) -> new_array
6570 * Returns a new +Array+ that is a recursive flattening of +self+:
6571 * - Each non-Array element is unchanged.
6572 * - Each +Array+ is replaced by its individual elements.
6574 * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
6576 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6577 * a.flatten(0) # => [0, [1, [2, 3], 4], 5]
6578 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6579 * a.flatten(1) # => [0, 1, [2, 3], 4, 5]
6580 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6581 * a.flatten(2) # => [0, 1, 2, 3, 4, 5]
6582 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6583 * a.flatten(3) # => [0, 1, 2, 3, 4, 5]
6585 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6587 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6588 * a.flatten # => [0, 1, 2, 3, 4, 5]
6589 * [0, 1, 2].flatten # => [0, 1, 2]
6590 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6591 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5]
6592 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6593 * a.flatten(-2) # => [0, 1, 2, 3, 4, 5]
6594 * [0, 1, 2].flatten(-1) # => [0, 1, 2]
6598 static VALUE
6599 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6601 int level = -1;
6602 VALUE result;
6604 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6605 level = NUM2INT(argv[0]);
6606 if (level == 0) return ary_make_shared_copy(ary);
6609 result = flatten(ary, level);
6610 if (result == ary) {
6611 result = ary_make_shared_copy(ary);
6614 return result;
6617 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6619 static VALUE
6620 rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6622 long i, len;
6624 rb_ary_modify(ary);
6625 i = len = RARRAY_LEN(ary);
6626 RARRAY_PTR_USE(ary, ptr, {
6627 while (i) {
6628 long j = RAND_UPTO(i);
6629 VALUE tmp;
6630 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6631 rb_raise(rb_eRuntimeError, "modified during shuffle");
6633 tmp = ptr[--i];
6634 ptr[i] = ptr[j];
6635 ptr[j] = tmp;
6637 }); /* WB: no new reference */
6638 return ary;
6641 static VALUE
6642 rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6644 ary = rb_ary_dup(ary);
6645 rb_ary_shuffle_bang(ec, ary, randgen);
6646 return ary;
6649 static const rb_data_type_t ary_sample_memo_type = {
6650 .wrap_struct_name = "ary_sample_memo",
6651 .function = {
6652 .dfree = (RUBY_DATA_FUNC)st_free_table,
6654 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
6657 static VALUE
6658 ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6660 VALUE result;
6661 long n, len, i, j, k, idx[10];
6662 long rnds[numberof(idx)];
6663 long memo_threshold;
6665 len = RARRAY_LEN(ary);
6666 if (!to_array) {
6667 if (len < 2)
6668 i = 0;
6669 else
6670 i = RAND_UPTO(len);
6672 return rb_ary_elt(ary, i);
6674 n = NUM2LONG(nv);
6675 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
6676 if (n > len) n = len;
6677 if (n <= numberof(idx)) {
6678 for (i = 0; i < n; ++i) {
6679 rnds[i] = RAND_UPTO(len - i);
6682 k = len;
6683 len = RARRAY_LEN(ary);
6684 if (len < k && n <= numberof(idx)) {
6685 for (i = 0; i < n; ++i) {
6686 if (rnds[i] >= len) return rb_ary_new_capa(0);
6689 if (n > len) n = len;
6690 switch (n) {
6691 case 0:
6692 return rb_ary_new_capa(0);
6693 case 1:
6694 i = rnds[0];
6695 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
6696 case 2:
6697 i = rnds[0];
6698 j = rnds[1];
6699 if (j >= i) j++;
6700 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
6701 case 3:
6702 i = rnds[0];
6703 j = rnds[1];
6704 k = rnds[2];
6706 long l = j, g = i;
6707 if (j >= i) l = i, g = ++j;
6708 if (k >= l && (++k >= g)) ++k;
6710 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
6712 memo_threshold =
6713 len < 2560 ? len / 128 :
6714 len < 5120 ? len / 64 :
6715 len < 10240 ? len / 32 :
6716 len / 16;
6717 if (n <= numberof(idx)) {
6718 long sorted[numberof(idx)];
6719 sorted[0] = idx[0] = rnds[0];
6720 for (i=1; i<n; i++) {
6721 k = rnds[i];
6722 for (j = 0; j < i; ++j) {
6723 if (k < sorted[j]) break;
6724 ++k;
6726 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
6727 sorted[j] = idx[i] = k;
6729 result = rb_ary_new_capa(n);
6730 RARRAY_PTR_USE(result, ptr_result, {
6731 for (i=0; i<n; i++) {
6732 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
6736 else if (n <= memo_threshold / 2) {
6737 long max_idx = 0;
6738 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
6739 st_table *memo = st_init_numtable_with_size(n);
6740 RTYPEDDATA_DATA(vmemo) = memo;
6741 result = rb_ary_new_capa(n);
6742 RARRAY_PTR_USE(result, ptr_result, {
6743 for (i=0; i<n; i++) {
6744 long r = RAND_UPTO(len-i) + i;
6745 ptr_result[i] = r;
6746 if (r > max_idx) max_idx = r;
6748 len = RARRAY_LEN(ary);
6749 if (len <= max_idx) n = 0;
6750 else if (n > len) n = len;
6751 RARRAY_PTR_USE(ary, ptr_ary, {
6752 for (i=0; i<n; i++) {
6753 long j2 = j = ptr_result[i];
6754 long i2 = i;
6755 st_data_t value;
6756 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
6757 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
6758 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6759 ptr_result[i] = ptr_ary[j2];
6763 RTYPEDDATA_DATA(vmemo) = 0;
6764 st_free_table(memo);
6765 RB_GC_GUARD(vmemo);
6767 else {
6768 result = rb_ary_dup(ary);
6769 RBASIC_CLEAR_CLASS(result);
6770 RB_GC_GUARD(ary);
6771 RARRAY_PTR_USE(result, ptr_result, {
6772 for (i=0; i<n; i++) {
6773 j = RAND_UPTO(len-i) + i;
6774 nv = ptr_result[j];
6775 ptr_result[j] = ptr_result[i];
6776 ptr_result[i] = nv;
6779 RBASIC_SET_CLASS_RAW(result, rb_cArray);
6781 ARY_SET_LEN(result, n);
6783 return result;
6786 static VALUE
6787 ary_sample0(rb_execution_context_t *ec, VALUE ary)
6789 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
6792 static VALUE
6793 rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
6795 long mul;
6796 VALUE n = Qnil;
6797 if (args && (RARRAY_LEN(args) > 0)) {
6798 n = RARRAY_AREF(args, 0);
6800 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
6801 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
6802 mul = NUM2LONG(n);
6803 if (mul <= 0) return INT2FIX(0);
6804 n = LONG2FIX(mul);
6805 return rb_fix_mul_fix(rb_ary_length(self), n);
6809 * call-seq:
6810 * cycle(count = nil) {|element| ... } -> nil
6811 * cycle(count = nil) -> new_enumerator
6813 * With a block given, may call the block, depending on the value of argument +count+;
6814 * +count+ must be an
6815 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6816 * or +nil+.
6818 * When +count+ is positive,
6819 * calls the block with each element, then does so repeatedly,
6820 * until it has done so +count+ times; returns +nil+:
6822 * output = []
6823 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6824 * output # => [0, 1, 0, 1]
6826 * When +count+ is zero or negative, does not call the block:
6828 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6829 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6831 * When +count+ is +nil+, cycles forever:
6833 * # Prints 0 and 1 forever.
6834 * [0, 1].cycle {|element| puts element }
6835 * [0, 1].cycle(nil) {|element| puts element }
6837 * With no block given, returns a new Enumerator.
6839 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6841 static VALUE
6842 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
6844 long n, i;
6846 rb_check_arity(argc, 0, 1);
6848 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
6849 if (argc == 0 || NIL_P(argv[0])) {
6850 n = -1;
6852 else {
6853 n = NUM2LONG(argv[0]);
6854 if (n <= 0) return Qnil;
6857 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
6858 for (i=0; i<RARRAY_LEN(ary); i++) {
6859 rb_yield(RARRAY_AREF(ary, i));
6862 return Qnil;
6866 * Build a ruby array of the corresponding values and yield it to the
6867 * associated block.
6868 * Return the class of +values+ for reentry check.
6870 static int
6871 yield_indexed_values(const VALUE values, const long r, const long *const p)
6873 const VALUE result = rb_ary_new2(r);
6874 long i;
6876 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
6877 ARY_SET_LEN(result, r);
6878 rb_yield(result);
6879 return !RBASIC(values)->klass;
6883 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6885 * When we have a complete permutation of array indices, copy the values
6886 * at those indices into a new array and yield that array.
6888 * n: the size of the set
6889 * r: the number of elements in each permutation
6890 * p: the array (of size r) that we're filling in
6891 * used: an array of booleans: whether a given index is already used
6892 * values: the Ruby array that holds the actual values to permute
6894 static void
6895 permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
6897 long i = 0, index = 0;
6899 for (;;) {
6900 const char *const unused = memchr(&used[i], 0, n-i);
6901 if (!unused) {
6902 if (!index) break;
6903 i = p[--index]; /* pop index */
6904 used[i++] = 0; /* index unused */
6906 else {
6907 i = unused - used;
6908 p[index] = i;
6909 used[i] = 1; /* mark index used */
6910 ++index;
6911 if (index < r-1) { /* if not done yet */
6912 p[index] = i = 0;
6913 continue;
6915 for (i = 0; i < n; ++i) {
6916 if (used[i]) continue;
6917 p[index] = i;
6918 if (!yield_indexed_values(values, r, p)) {
6919 rb_raise(rb_eRuntimeError, "permute reentered");
6922 i = p[--index]; /* pop index */
6923 used[i] = 0; /* index unused */
6924 p[index] = ++i;
6930 * Returns the product of from, from-1, ..., from - how_many + 1.
6931 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6933 static VALUE
6934 descending_factorial(long from, long how_many)
6936 VALUE cnt;
6937 if (how_many > 0) {
6938 cnt = LONG2FIX(from);
6939 while (--how_many > 0) {
6940 long v = --from;
6941 cnt = rb_int_mul(cnt, LONG2FIX(v));
6944 else {
6945 cnt = LONG2FIX(how_many == 0);
6947 return cnt;
6950 static VALUE
6951 binomial_coefficient(long comb, long size)
6953 VALUE r;
6954 long i;
6955 if (comb > size-comb) {
6956 comb = size-comb;
6958 if (comb < 0) {
6959 return LONG2FIX(0);
6961 else if (comb == 0) {
6962 return LONG2FIX(1);
6964 r = LONG2FIX(size);
6965 for (i = 1; i < comb; ++i) {
6966 r = rb_int_mul(r, LONG2FIX(size - i));
6967 r = rb_int_idiv(r, LONG2FIX(i + 1));
6969 return r;
6972 static VALUE
6973 rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
6975 long n = RARRAY_LEN(ary);
6976 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
6978 return descending_factorial(n, k);
6982 * call-seq:
6983 * array.permutation {|element| ... } -> self
6984 * array.permutation(n) {|element| ... } -> self
6985 * array.permutation -> new_enumerator
6986 * array.permutation(n) -> new_enumerator
6988 * When invoked with a block, yield all permutations of elements of +self+; returns +self+.
6989 * The order of permutations is indeterminate.
6991 * When a block and an in-range positive Integer argument +n+ (<tt>0 < n <= self.size</tt>)
6992 * are given, calls the block with all +n+-tuple permutations of +self+.
6994 * Example:
6996 * a = [0, 1, 2]
6997 * a.permutation(2) {|permutation| p permutation }
6999 * Output:
7001 * [0, 1]
7002 * [0, 2]
7003 * [1, 0]
7004 * [1, 2]
7005 * [2, 0]
7006 * [2, 1]
7008 * Another example:
7010 * a = [0, 1, 2]
7011 * a.permutation(3) {|permutation| p permutation }
7013 * Output:
7015 * [0, 1, 2]
7016 * [0, 2, 1]
7017 * [1, 0, 2]
7018 * [1, 2, 0]
7019 * [2, 0, 1]
7020 * [2, 1, 0]
7022 * When +n+ is zero, calls the block once with a new empty +Array+:
7024 * a = [0, 1, 2]
7025 * a.permutation(0) {|permutation| p permutation }
7027 * Output:
7029 * []
7031 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
7032 * does not call the block:
7034 * a = [0, 1, 2]
7035 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7036 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7038 * When a block given but no argument,
7039 * behaves the same as <tt>a.permutation(a.size)</tt>:
7041 * a = [0, 1, 2]
7042 * a.permutation {|permutation| p permutation }
7044 * Output:
7046 * [0, 1, 2]
7047 * [0, 2, 1]
7048 * [1, 0, 2]
7049 * [1, 2, 0]
7050 * [2, 0, 1]
7051 * [2, 1, 0]
7053 * Returns a new Enumerator if no block given:
7055 * a = [0, 1, 2]
7056 * a.permutation # => #<Enumerator: [0, 1, 2]:permutation>
7057 * a.permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
7061 static VALUE
7062 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
7064 long r, n, i;
7066 n = RARRAY_LEN(ary); /* Array length */
7067 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
7068 r = n;
7069 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
7070 r = NUM2LONG(argv[0]); /* Permutation size from argument */
7072 if (r < 0 || n < r) {
7073 /* no permutations: yield nothing */
7075 else if (r == 0) { /* exactly one permutation: the zero-length array */
7076 rb_yield(rb_ary_new2(0));
7078 else if (r == 1) { /* this is a special, easy case */
7079 for (i = 0; i < RARRAY_LEN(ary); i++) {
7080 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7083 else { /* this is the general case */
7084 volatile VALUE t0;
7085 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
7086 char *used = (char*)(p + r);
7087 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7088 RBASIC_CLEAR_CLASS(ary0);
7090 MEMZERO(used, char, n); /* initialize array */
7092 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7093 ALLOCV_END(t0);
7094 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7096 return ary;
7099 static void
7100 combinate0(const long len, const long n, long *const stack, const VALUE values)
7102 long lev = 0;
7104 MEMZERO(stack+1, long, n);
7105 stack[0] = -1;
7106 for (;;) {
7107 for (lev++; lev < n; lev++) {
7108 stack[lev+1] = stack[lev]+1;
7110 if (!yield_indexed_values(values, n, stack+1)) {
7111 rb_raise(rb_eRuntimeError, "combination reentered");
7113 do {
7114 if (lev == 0) return;
7115 stack[lev--]++;
7116 } while (stack[lev+1]+n == len+lev+1);
7120 static VALUE
7121 rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7123 long n = RARRAY_LEN(ary);
7124 long k = NUM2LONG(RARRAY_AREF(args, 0));
7126 return binomial_coefficient(k, n);
7130 * call-seq:
7131 * combination(n) {|element| ... } -> self
7132 * combination(n) -> new_enumerator
7134 * When a block and a positive
7135 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7136 * argument +n+ (<tt>0 < n <= self.size</tt>)
7137 * are given, calls the block with all +n+-tuple combinations of +self+;
7138 * returns +self+:
7140 * a = %w[a b c] # => ["a", "b", "c"]
7141 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7143 * Output:
7145 * ["a", "b"]
7146 * ["a", "c"]
7147 * ["b", "c"]
7149 * The order of the yielded combinations is not guaranteed.
7151 * When +n+ is zero, calls the block once with a new empty array:
7153 * a.combination(0) {|combination| p combination }
7154 * [].combination(0) {|combination| p combination }
7156 * Output:
7158 * []
7159 * []
7161 * When +n+ is negative or larger than +self.size+ and +self+ is non-empty,
7162 * does not call the block:
7164 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7165 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7167 * With no block given, returns a new Enumerator.
7169 * Related: Array#permutation;
7170 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7173 static VALUE
7174 rb_ary_combination(VALUE ary, VALUE num)
7176 long i, n, len;
7178 n = NUM2LONG(num);
7179 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7180 len = RARRAY_LEN(ary);
7181 if (n < 0 || len < n) {
7182 /* yield nothing */
7184 else if (n == 0) {
7185 rb_yield(rb_ary_new2(0));
7187 else if (n == 1) {
7188 for (i = 0; i < RARRAY_LEN(ary); i++) {
7189 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7192 else {
7193 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7194 volatile VALUE t0;
7195 long *stack = ALLOCV_N(long, t0, n+1);
7197 RBASIC_CLEAR_CLASS(ary0);
7198 combinate0(len, n, stack, ary0);
7199 ALLOCV_END(t0);
7200 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7202 return ary;
7206 * Compute repeated permutations of +r+ elements of the set
7207 * <code>[0..n-1]</code>.
7209 * When we have a complete repeated permutation of array indices, copy the
7210 * values at those indices into a new array and yield that array.
7212 * n: the size of the set
7213 * r: the number of elements in each permutation
7214 * p: the array (of size r) that we're filling in
7215 * values: the Ruby array that holds the actual values to permute
7217 static void
7218 rpermute0(const long n, const long r, long *const p, const VALUE values)
7220 long i = 0, index = 0;
7222 p[index] = i;
7223 for (;;) {
7224 if (++index < r-1) {
7225 p[index] = i = 0;
7226 continue;
7228 for (i = 0; i < n; ++i) {
7229 p[index] = i;
7230 if (!yield_indexed_values(values, r, p)) {
7231 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7234 do {
7235 if (index <= 0) return;
7236 } while ((i = ++p[--index]) >= n);
7240 static VALUE
7241 rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7243 long n = RARRAY_LEN(ary);
7244 long k = NUM2LONG(RARRAY_AREF(args, 0));
7246 if (k < 0) {
7247 return LONG2FIX(0);
7249 if (n <= 0) {
7250 return LONG2FIX(!k);
7252 return rb_int_positive_pow(n, (unsigned long)k);
7256 * call-seq:
7257 * array.repeated_permutation(n) {|permutation| ... } -> self
7258 * array.repeated_permutation(n) -> new_enumerator
7260 * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
7261 * each permutation is an +Array+;
7262 * returns +self+. The order of the permutations is indeterminate.
7264 * When a block and a positive Integer argument +n+ are given, calls the block with each
7265 * +n+-tuple repeated permutation of the elements of +self+.
7266 * The number of permutations is <tt>self.size**n</tt>.
7268 * +n+ = 1:
7270 * a = [0, 1, 2]
7271 * a.repeated_permutation(1) {|permutation| p permutation }
7273 * Output:
7275 * [0]
7276 * [1]
7277 * [2]
7279 * +n+ = 2:
7281 * a.repeated_permutation(2) {|permutation| p permutation }
7283 * Output:
7285 * [0, 0]
7286 * [0, 1]
7287 * [0, 2]
7288 * [1, 0]
7289 * [1, 1]
7290 * [1, 2]
7291 * [2, 0]
7292 * [2, 1]
7293 * [2, 2]
7295 * If +n+ is zero, calls the block once with an empty +Array+.
7297 * If +n+ is negative, does not call the block:
7299 * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7301 * Returns a new Enumerator if no block given:
7303 * a = [0, 1, 2]
7304 * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
7306 * Using Enumerators, it's convenient to show the permutations and counts
7307 * for some values of +n+:
7309 * e = a.repeated_permutation(0)
7310 * e.size # => 1
7311 * e.to_a # => [[]]
7312 * e = a.repeated_permutation(1)
7313 * e.size # => 3
7314 * e.to_a # => [[0], [1], [2]]
7315 * e = a.repeated_permutation(2)
7316 * e.size # => 9
7317 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7320 static VALUE
7321 rb_ary_repeated_permutation(VALUE ary, VALUE num)
7323 long r, n, i;
7325 n = RARRAY_LEN(ary); /* Array length */
7326 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7327 r = NUM2LONG(num); /* Permutation size from argument */
7329 if (r < 0) {
7330 /* no permutations: yield nothing */
7332 else if (r == 0) { /* exactly one permutation: the zero-length array */
7333 rb_yield(rb_ary_new2(0));
7335 else if (r == 1) { /* this is a special, easy case */
7336 for (i = 0; i < RARRAY_LEN(ary); i++) {
7337 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7340 else { /* this is the general case */
7341 volatile VALUE t0;
7342 long *p = ALLOCV_N(long, t0, r);
7343 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7344 RBASIC_CLEAR_CLASS(ary0);
7346 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7347 ALLOCV_END(t0);
7348 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7350 return ary;
7353 static void
7354 rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7356 long i = 0, index = 0;
7358 p[index] = i;
7359 for (;;) {
7360 if (++index < r-1) {
7361 p[index] = i;
7362 continue;
7364 for (; i < n; ++i) {
7365 p[index] = i;
7366 if (!yield_indexed_values(values, r, p)) {
7367 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7370 do {
7371 if (index <= 0) return;
7372 } while ((i = ++p[--index]) >= n);
7376 static VALUE
7377 rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7379 long n = RARRAY_LEN(ary);
7380 long k = NUM2LONG(RARRAY_AREF(args, 0));
7381 if (k == 0) {
7382 return LONG2FIX(1);
7384 return binomial_coefficient(k, n + k - 1);
7388 * call-seq:
7389 * array.repeated_combination(n) {|combination| ... } -> self
7390 * array.repeated_combination(n) -> new_enumerator
7392 * Calls the block with each repeated combination of length +n+ of the elements of +self+;
7393 * each combination is an +Array+;
7394 * returns +self+. The order of the combinations is indeterminate.
7396 * When a block and a positive Integer argument +n+ are given, calls the block with each
7397 * +n+-tuple repeated combination of the elements of +self+.
7398 * The number of combinations is <tt>(n+1)(n+2)/2</tt>.
7400 * +n+ = 1:
7402 * a = [0, 1, 2]
7403 * a.repeated_combination(1) {|combination| p combination }
7405 * Output:
7407 * [0]
7408 * [1]
7409 * [2]
7411 * +n+ = 2:
7413 * a.repeated_combination(2) {|combination| p combination }
7415 * Output:
7417 * [0, 0]
7418 * [0, 1]
7419 * [0, 2]
7420 * [1, 1]
7421 * [1, 2]
7422 * [2, 2]
7424 * If +n+ is zero, calls the block once with an empty +Array+.
7426 * If +n+ is negative, does not call the block:
7428 * a.repeated_combination(-1) {|combination| fail 'Cannot happen' }
7430 * Returns a new Enumerator if no block given:
7432 * a = [0, 1, 2]
7433 * a.repeated_combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
7435 * Using Enumerators, it's convenient to show the combinations and counts
7436 * for some values of +n+:
7438 * e = a.repeated_combination(0)
7439 * e.size # => 1
7440 * e.to_a # => [[]]
7441 * e = a.repeated_combination(1)
7442 * e.size # => 3
7443 * e.to_a # => [[0], [1], [2]]
7444 * e = a.repeated_combination(2)
7445 * e.size # => 6
7446 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7450 static VALUE
7451 rb_ary_repeated_combination(VALUE ary, VALUE num)
7453 long n, i, len;
7455 n = NUM2LONG(num); /* Combination size from argument */
7456 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7457 len = RARRAY_LEN(ary);
7458 if (n < 0) {
7459 /* yield nothing */
7461 else if (n == 0) {
7462 rb_yield(rb_ary_new2(0));
7464 else if (n == 1) {
7465 for (i = 0; i < RARRAY_LEN(ary); i++) {
7466 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7469 else if (len == 0) {
7470 /* yield nothing */
7472 else {
7473 volatile VALUE t0;
7474 long *p = ALLOCV_N(long, t0, n);
7475 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7476 RBASIC_CLEAR_CLASS(ary0);
7478 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7479 ALLOCV_END(t0);
7480 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7482 return ary;
7486 * call-seq:
7487 * array.product(*other_arrays) -> new_array
7488 * array.product(*other_arrays) {|combination| ... } -> self
7490 * Computes and returns or yields all combinations of elements from all the Arrays,
7491 * including both +self+ and +other_arrays+:
7493 * - The number of combinations is the product of the sizes of all the arrays,
7494 * including both +self+ and +other_arrays+.
7495 * - The order of the returned combinations is indeterminate.
7497 * When no block is given, returns the combinations as an +Array+ of Arrays:
7499 * a = [0, 1, 2]
7500 * a1 = [3, 4]
7501 * a2 = [5, 6]
7502 * p = a.product(a1)
7503 * p.size # => 6 # a.size * a1.size
7504 * p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]]
7505 * p = a.product(a1, a2)
7506 * p.size # => 12 # a.size * a1.size * a2.size
7507 * p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
7509 * If any argument is an empty +Array+, returns an empty +Array+.
7511 * If no argument is given, returns an +Array+ of 1-element Arrays,
7512 * each containing an element of +self+:
7514 * a.product # => [[0], [1], [2]]
7516 * When a block is given, yields each combination as an +Array+; returns +self+:
7518 * a.product(a1) {|combination| p combination }
7520 * Output:
7522 * [0, 3]
7523 * [0, 4]
7524 * [1, 3]
7525 * [1, 4]
7526 * [2, 3]
7527 * [2, 4]
7529 * If any argument is an empty +Array+, does not call the block:
7531 * a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
7533 * If no argument is given, yields each element of +self+ as a 1-element +Array+:
7535 * a.product {|combination| p combination }
7537 * Output:
7539 * [0]
7540 * [1]
7541 * [2]
7545 static VALUE
7546 rb_ary_product(int argc, VALUE *argv, VALUE ary)
7548 int n = argc+1; /* How many arrays we're operating on */
7549 volatile VALUE t0 = rb_ary_hidden_new(n);
7550 volatile VALUE t1 = Qundef;
7551 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7552 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7553 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7554 long i,j;
7555 long resultlen = 1;
7557 RBASIC_CLEAR_CLASS(t0);
7559 /* initialize the arrays of arrays */
7560 ARY_SET_LEN(t0, n);
7561 arrays[0] = ary;
7562 for (i = 1; i < n; i++) arrays[i] = Qnil;
7563 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7565 /* initialize the counters for the arrays */
7566 for (i = 0; i < n; i++) counters[i] = 0;
7568 /* Otherwise, allocate and fill in an array of results */
7569 if (rb_block_given_p()) {
7570 /* Make defensive copies of arrays; exit if any is empty */
7571 for (i = 0; i < n; i++) {
7572 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7573 arrays[i] = ary_make_shared_copy(arrays[i]);
7576 else {
7577 /* Compute the length of the result array; return [] if any is empty */
7578 for (i = 0; i < n; i++) {
7579 long k = RARRAY_LEN(arrays[i]);
7580 if (k == 0) {
7581 result = rb_ary_new2(0);
7582 goto done;
7584 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7585 rb_raise(rb_eRangeError, "too big to product");
7586 resultlen *= k;
7588 result = rb_ary_new2(resultlen);
7590 for (;;) {
7591 int m;
7592 /* fill in one subarray */
7593 VALUE subarray = rb_ary_new2(n);
7594 for (j = 0; j < n; j++) {
7595 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7598 /* put it on the result array */
7599 if (NIL_P(result)) {
7600 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7601 rb_yield(subarray);
7602 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7603 rb_raise(rb_eRuntimeError, "product reentered");
7605 else {
7606 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7609 else {
7610 rb_ary_push(result, subarray);
7614 * Increment the last counter. If it overflows, reset to 0
7615 * and increment the one before it.
7617 m = n-1;
7618 counters[m]++;
7619 while (counters[m] == RARRAY_LEN(arrays[m])) {
7620 counters[m] = 0;
7621 /* If the first counter overflows, we are done */
7622 if (--m < 0) goto done;
7623 counters[m]++;
7627 done:
7628 ALLOCV_END(t1);
7630 return NIL_P(result) ? ary : result;
7634 * call-seq:
7635 * array.take(n) -> new_array
7637 * Returns a new +Array+ containing the first +n+ element of +self+,
7638 * where +n+ is a non-negative Integer;
7639 * does not modify +self+.
7641 * Examples:
7643 * a = [0, 1, 2, 3, 4, 5]
7644 * a.take(1) # => [0]
7645 * a.take(2) # => [0, 1]
7646 * a.take(50) # => [0, 1, 2, 3, 4, 5]
7647 * a # => [0, 1, 2, 3, 4, 5]
7651 static VALUE
7652 rb_ary_take(VALUE obj, VALUE n)
7654 long len = NUM2LONG(n);
7655 if (len < 0) {
7656 rb_raise(rb_eArgError, "attempt to take negative size");
7658 return rb_ary_subseq(obj, 0, len);
7662 * call-seq:
7663 * array.take_while {|element| ... } -> new_array
7664 * array.take_while -> new_enumerator
7666 * Returns a new +Array+ containing zero or more leading elements of +self+;
7667 * does not modify +self+.
7669 * With a block given, calls the block with each successive element of +self+;
7670 * stops if the block returns +false+ or +nil+;
7671 * returns a new +Array+ containing those elements for which the block returned a truthy value:
7673 * a = [0, 1, 2, 3, 4, 5]
7674 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7675 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7676 * a # => [0, 1, 2, 3, 4, 5]
7678 * With no block given, returns a new Enumerator:
7680 * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
7684 static VALUE
7685 rb_ary_take_while(VALUE ary)
7687 long i;
7689 RETURN_ENUMERATOR(ary, 0, 0);
7690 for (i = 0; i < RARRAY_LEN(ary); i++) {
7691 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7693 return rb_ary_take(ary, LONG2FIX(i));
7697 * call-seq:
7698 * drop(n) -> new_array
7700 * Returns a new array containing all but the first +n+ element of +self+,
7701 * where +n+ is a non-negative Integer;
7702 * does not modify +self+.
7704 * Examples:
7706 * a = [0, 1, 2, 3, 4, 5]
7707 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7708 * a.drop(1) # => [1, 2, 3, 4, 5]
7709 * a.drop(2) # => [2, 3, 4, 5]
7710 * a.drop(9) # => []
7712 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7715 static VALUE
7716 rb_ary_drop(VALUE ary, VALUE n)
7718 VALUE result;
7719 long pos = NUM2LONG(n);
7720 if (pos < 0) {
7721 rb_raise(rb_eArgError, "attempt to drop negative size");
7724 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7725 if (NIL_P(result)) result = rb_ary_new();
7726 return result;
7730 * call-seq:
7731 * drop_while {|element| ... } -> new_array
7732 * drop_while -> new_enumerator
7734 * With a block given, calls the block with each successive element of +self+;
7735 * stops if the block returns +false+ or +nil+;
7736 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7737 * does not modify +self+:
7739 * a = [0, 1, 2, 3, 4, 5]
7740 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7742 * With no block given, returns a new Enumerator.
7744 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7747 static VALUE
7748 rb_ary_drop_while(VALUE ary)
7750 long i;
7752 RETURN_ENUMERATOR(ary, 0, 0);
7753 for (i = 0; i < RARRAY_LEN(ary); i++) {
7754 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7756 return rb_ary_drop(ary, LONG2FIX(i));
7760 * call-seq:
7761 * any? -> true or false
7762 * any?(object) -> true or false
7763 * any? {|element| ... } -> true or false
7765 * Returns whether for any element of +self+, a given criterion is satisfied.
7767 * With no block and no argument, returns whether any element of +self+ is truthy:
7769 * [nil, false, []].any? # => true # Array object is truthy.
7770 * [nil, false, {}].any? # => true # Hash object is truthy.
7771 * [nil, false, ''].any? # => true # String object is truthy.
7772 * [nil, false].any? # => false # Nil and false are not truthy.
7774 * With argument +object+ given,
7775 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7777 * [nil, false, 0].any?(0) # => true
7778 * [nil, false, 1].any?(0) # => false
7779 * [nil, false, 'food'].any?(/foo/) # => true
7780 * [nil, false, 'food'].any?(/bar/) # => false
7782 * With a block given,
7783 * calls the block with each element in +self+;
7784 * returns whether the block returns any truthy value:
7786 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7787 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7789 * With both a block and argument +object+ given,
7790 * ignores the block and uses +object+ as above.
7792 * <b>Special case</b>: returns +false+ if +self+ is empty
7793 * (regardless of any given argument or block).
7795 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7798 static VALUE
7799 rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
7801 long i, len = RARRAY_LEN(ary);
7803 rb_check_arity(argc, 0, 1);
7804 if (!len) return Qfalse;
7805 if (argc) {
7806 if (rb_block_given_p()) {
7807 rb_warn("given block not used");
7809 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7810 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
7813 else if (!rb_block_given_p()) {
7814 for (i = 0; i < len; ++i) {
7815 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
7818 else {
7819 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7820 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
7823 return Qfalse;
7827 * call-seq:
7828 * all? -> true or false
7829 * all?(object) -> true or false
7830 * all? {|element| ... } -> true or false
7832 * Returns whether for every element of +self+,
7833 * a given criterion is satisfied.
7835 * With no block and no argument,
7836 * returns whether every element of +self+ is truthy:
7838 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7839 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7840 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7842 * With argument +object+ given, returns whether <tt>object === ele</tt>
7843 * for every element +ele+ in +self+:
7845 * [0, 0, 0].all?(0) # => true
7846 * [0, 1, 2].all?(1) # => false
7847 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7848 * ['food', 'drink'].all?(/foo/) # => false
7850 * With a block given, calls the block with each element in +self+;
7851 * returns whether the block returns only truthy values:
7853 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7854 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7856 * With both a block and argument +object+ given,
7857 * ignores the block and uses +object+ as above.
7859 * <b>Special case</b>: returns +true+ if +self+ is empty
7860 * (regardless of any given argument or block).
7862 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7865 static VALUE
7866 rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
7868 long i, len = RARRAY_LEN(ary);
7870 rb_check_arity(argc, 0, 1);
7871 if (!len) return Qtrue;
7872 if (argc) {
7873 if (rb_block_given_p()) {
7874 rb_warn("given block not used");
7876 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7877 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7880 else if (!rb_block_given_p()) {
7881 for (i = 0; i < len; ++i) {
7882 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7885 else {
7886 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7887 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7890 return Qtrue;
7894 * call-seq:
7895 * array.none? -> true or false
7896 * array.none? {|element| ... } -> true or false
7897 * array.none?(obj) -> true or false
7899 * Returns +true+ if no element of +self+ meet a given criterion.
7901 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7902 * +false+ otherwise:
7904 * [nil, false].none? # => true
7905 * [nil, 0, false].none? # => false
7906 * [].none? # => true
7908 * With a block given and no argument, calls the block with each element in +self+;
7909 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7911 * [0, 1, 2].none? {|element| element > 3 } # => true
7912 * [0, 1, 2].none? {|element| element > 1 } # => false
7914 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> no element, +false+ otherwise:
7916 * ['food', 'drink'].none?(/bar/) # => true
7917 * ['food', 'drink'].none?(/foo/) # => false
7918 * [].none?(/foo/) # => true
7919 * [0, 1, 2].none?(3) # => true
7920 * [0, 1, 2].none?(1) # => false
7922 * Related: Enumerable#none?
7925 static VALUE
7926 rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
7928 long i, len = RARRAY_LEN(ary);
7930 rb_check_arity(argc, 0, 1);
7931 if (!len) return Qtrue;
7932 if (argc) {
7933 if (rb_block_given_p()) {
7934 rb_warn("given block not used");
7936 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7937 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7940 else if (!rb_block_given_p()) {
7941 for (i = 0; i < len; ++i) {
7942 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7945 else {
7946 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7947 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7950 return Qtrue;
7954 * call-seq:
7955 * array.one? -> true or false
7956 * array.one? {|element| ... } -> true or false
7957 * array.one?(obj) -> true or false
7959 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7961 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7962 * +false+ otherwise:
7964 * [nil, 0].one? # => true
7965 * [0, 0].one? # => false
7966 * [nil, nil].one? # => false
7967 * [].one? # => false
7969 * With a block given and no argument, calls the block with each element in +self+;
7970 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7972 * [0, 1, 2].one? {|element| element > 0 } # => false
7973 * [0, 1, 2].one? {|element| element > 1 } # => true
7974 * [0, 1, 2].one? {|element| element > 2 } # => false
7976 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> exactly one element,
7977 * +false+ otherwise:
7979 * [0, 1, 2].one?(0) # => true
7980 * [0, 0, 1].one?(0) # => false
7981 * [1, 1, 2].one?(0) # => false
7982 * ['food', 'drink'].one?(/bar/) # => false
7983 * ['food', 'drink'].one?(/foo/) # => true
7984 * [].one?(/foo/) # => false
7986 * Related: Enumerable#one?
7989 static VALUE
7990 rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
7992 long i, len = RARRAY_LEN(ary);
7993 VALUE result = Qfalse;
7995 rb_check_arity(argc, 0, 1);
7996 if (!len) return Qfalse;
7997 if (argc) {
7998 if (rb_block_given_p()) {
7999 rb_warn("given block not used");
8001 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8002 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
8003 if (result) return Qfalse;
8004 result = Qtrue;
8008 else if (!rb_block_given_p()) {
8009 for (i = 0; i < len; ++i) {
8010 if (RTEST(RARRAY_AREF(ary, i))) {
8011 if (result) return Qfalse;
8012 result = Qtrue;
8016 else {
8017 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8018 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
8019 if (result) return Qfalse;
8020 result = Qtrue;
8024 return result;
8028 * call-seq:
8029 * array.dig(index, *identifiers) -> object
8031 * Finds and returns the object in nested object
8032 * specified by +index+ and +identifiers+;
8033 * the nested objects may be instances of various classes.
8034 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8036 * Examples:
8038 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8039 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8040 * a.dig(1, 2) # => [:bat, :bam]
8041 * a.dig(1, 2, 0) # => :bat
8042 * a.dig(1, 2, 3) # => nil
8044 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8047 static VALUE
8048 rb_ary_dig(int argc, VALUE *argv, VALUE self)
8050 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
8051 self = rb_ary_at(self, *argv);
8052 if (!--argc) return self;
8053 ++argv;
8054 return rb_obj_dig(argc, argv, self, Qnil);
8057 static inline VALUE
8058 finish_exact_sum(long n, VALUE r, VALUE v, int z)
8060 if (n != 0)
8061 v = rb_fix_plus(LONG2FIX(n), v);
8062 if (!UNDEF_P(r)) {
8063 v = rb_rational_plus(r, v);
8065 else if (!n && z) {
8066 v = rb_fix_plus(LONG2FIX(0), v);
8068 return v;
8072 * call-seq:
8073 * array.sum(init = 0) -> object
8074 * array.sum(init = 0) {|element| ... } -> object
8076 * When no block is given, returns the object equivalent to:
8078 * sum = init
8079 * array.each {|element| sum += element }
8080 * sum
8082 * For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
8084 * Examples:
8086 * a = [0, 1, 2, 3]
8087 * a.sum # => 6
8088 * a.sum(100) # => 106
8090 * The elements need not be numeric, but must be <tt>+</tt>-compatible
8091 * with each other and with +init+:
8093 * a = ['abc', 'def', 'ghi']
8094 * a.sum('jkl') # => "jklabcdefghi"
8096 * When a block is given, it is called with each element
8097 * and the block's return value (instead of the element itself) is used as the addend:
8099 * a = ['zero', 1, :two]
8100 * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
8101 * s # => "Coerced and concatenated: zero1two"
8103 * Notes:
8105 * - Array#join and Array#flatten may be faster than Array#sum
8106 * for an +Array+ of Strings or an +Array+ of Arrays.
8107 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8111 static VALUE
8112 rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8114 VALUE e, v, r;
8115 long i, n;
8116 int block_given;
8118 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8120 block_given = rb_block_given_p();
8122 if (RARRAY_LEN(ary) == 0)
8123 return v;
8125 n = 0;
8126 r = Qundef;
8128 if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8129 i = 0;
8130 goto init_is_a_value;
8133 for (i = 0; i < RARRAY_LEN(ary); i++) {
8134 e = RARRAY_AREF(ary, i);
8135 if (block_given)
8136 e = rb_yield(e);
8137 if (FIXNUM_P(e)) {
8138 n += FIX2LONG(e); /* should not overflow long type */
8139 if (!FIXABLE(n)) {
8140 v = rb_big_plus(LONG2NUM(n), v);
8141 n = 0;
8144 else if (RB_BIGNUM_TYPE_P(e))
8145 v = rb_big_plus(e, v);
8146 else if (RB_TYPE_P(e, T_RATIONAL)) {
8147 if (UNDEF_P(r))
8148 r = e;
8149 else
8150 r = rb_rational_plus(r, e);
8152 else
8153 goto not_exact;
8155 v = finish_exact_sum(n, r, v, argc!=0);
8156 return v;
8158 not_exact:
8159 v = finish_exact_sum(n, r, v, i!=0);
8161 if (RB_FLOAT_TYPE_P(e)) {
8163 * Kahan-Babuska balancing compensated summation algorithm
8164 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8166 double f, c;
8167 double x, t;
8169 f = NUM2DBL(v);
8170 c = 0.0;
8171 goto has_float_value;
8172 for (; i < RARRAY_LEN(ary); i++) {
8173 e = RARRAY_AREF(ary, i);
8174 if (block_given)
8175 e = rb_yield(e);
8176 if (RB_FLOAT_TYPE_P(e))
8177 has_float_value:
8178 x = RFLOAT_VALUE(e);
8179 else if (FIXNUM_P(e))
8180 x = FIX2LONG(e);
8181 else if (RB_BIGNUM_TYPE_P(e))
8182 x = rb_big2dbl(e);
8183 else if (RB_TYPE_P(e, T_RATIONAL))
8184 x = rb_num2dbl(e);
8185 else
8186 goto not_float;
8188 if (isnan(f)) continue;
8189 if (isnan(x)) {
8190 f = x;
8191 continue;
8193 if (isinf(x)) {
8194 if (isinf(f) && signbit(x) != signbit(f))
8195 f = NAN;
8196 else
8197 f = x;
8198 continue;
8200 if (isinf(f)) continue;
8202 t = f + x;
8203 if (fabs(f) >= fabs(x))
8204 c += ((f - t) + x);
8205 else
8206 c += ((x - t) + f);
8207 f = t;
8209 f += c;
8210 return DBL2NUM(f);
8212 not_float:
8213 v = DBL2NUM(f);
8216 goto has_some_value;
8217 init_is_a_value:
8218 for (; i < RARRAY_LEN(ary); i++) {
8219 e = RARRAY_AREF(ary, i);
8220 if (block_given)
8221 e = rb_yield(e);
8222 has_some_value:
8223 v = rb_funcall(v, idPLUS, 1, e);
8225 return v;
8228 /* :nodoc: */
8229 static VALUE
8230 rb_ary_deconstruct(VALUE ary)
8232 return ary;
8236 * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
8237 * Any object (even another array) may be an array element,
8238 * and an array can contain objects of different types.
8240 * == +Array+ Indexes
8242 * +Array+ indexing starts at 0, as in C or Java.
8244 * A positive index is an offset from the first element:
8246 * - Index 0 indicates the first element.
8247 * - Index 1 indicates the second element.
8248 * - ...
8250 * A negative index is an offset, backwards, from the end of the array:
8252 * - Index -1 indicates the last element.
8253 * - Index -2 indicates the next-to-last element.
8254 * - ...
8256 * A non-negative index is <i>in range</i> if and only if it is smaller than
8257 * the size of the array. For a 3-element array:
8259 * - Indexes 0 through 2 are in range.
8260 * - Index 3 is out of range.
8262 * A negative index is <i>in range</i> if and only if its absolute value is
8263 * not larger than the size of the array. For a 3-element array:
8265 * - Indexes -1 through -3 are in range.
8266 * - Index -4 is out of range.
8268 * Although the effective index into an array is always an integer,
8269 * some methods (both within and outside of class +Array+)
8270 * accept one or more non-integer arguments that are
8271 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8274 * == Creating Arrays
8276 * You can create an +Array+ object explicitly with:
8278 * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
8280 * [1, 'one', :one, [2, 'two', :two]]
8282 * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8284 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8285 * %w[1 % *] # => ["1", "%", "*"]
8287 * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8289 * %i[foo bar baz] # => [:foo, :bar, :baz]
8290 * %i[1 % *] # => [:"1", :%, :*]
8292 * - \Method Kernel#Array:
8294 * Array(["a", "b"]) # => ["a", "b"]
8295 * Array(1..5) # => [1, 2, 3, 4, 5]
8296 * Array(key: :value) # => [[:key, :value]]
8297 * Array(nil) # => []
8298 * Array(1) # => [1]
8299 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8301 * - \Method Array.new:
8303 * Array.new # => []
8304 * Array.new(3) # => [nil, nil, nil]
8305 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8306 * Array.new(3, true) # => [true, true, true]
8308 * Note that the last example above populates the array
8309 * with references to the same object.
8310 * This is recommended only in cases where that object is a natively immutable object
8311 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8313 * Another way to create an array with various objects, using a block;
8314 * this usage is safe for mutable objects such as hashes, strings or
8315 * other arrays:
8317 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8319 * Here is a way to create a multi-dimensional array:
8321 * Array.new(3) {Array.new(3)}
8322 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8324 * A number of Ruby methods, both in the core and in the standard library,
8325 * provide instance method +to_a+, which converts an object to an array.
8327 * - ARGF#to_a
8328 * - Array#to_a
8329 * - Enumerable#to_a
8330 * - Hash#to_a
8331 * - MatchData#to_a
8332 * - NilClass#to_a
8333 * - OptionParser#to_a
8334 * - Range#to_a
8335 * - Set#to_a
8336 * - Struct#to_a
8337 * - Time#to_a
8338 * - Benchmark::Tms#to_a
8339 * - CSV::Table#to_a
8340 * - Enumerator::Lazy#to_a
8341 * - Gem::List#to_a
8342 * - Gem::NameTuple#to_a
8343 * - Gem::Platform#to_a
8344 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8345 * - Gem::SourceList#to_a
8346 * - OpenSSL::X509::Extension#to_a
8347 * - OpenSSL::X509::Name#to_a
8348 * - Racc::ISet#to_a
8349 * - Rinda::RingFinger#to_a
8350 * - Ripper::Lexer::Elem#to_a
8351 * - RubyVM::InstructionSequence#to_a
8352 * - YAML::DBM#to_a
8354 * == Example Usage
8356 * In addition to the methods it mixes in through the Enumerable module, the
8357 * +Array+ class has proprietary methods for accessing, searching and otherwise
8358 * manipulating arrays.
8360 * Some of the more common ones are illustrated below.
8362 * == Accessing Elements
8364 * Elements in an array can be retrieved using the Array#[] method. It can
8365 * take a single integer argument (a numeric index), a pair of arguments
8366 * (start and length) or a range. Negative indices start counting from the end,
8367 * with -1 being the last element.
8369 * arr = [1, 2, 3, 4, 5, 6]
8370 * arr[2] #=> 3
8371 * arr[100] #=> nil
8372 * arr[-3] #=> 4
8373 * arr[2, 3] #=> [3, 4, 5]
8374 * arr[1..4] #=> [2, 3, 4, 5]
8375 * arr[1..-3] #=> [2, 3, 4]
8377 * Another way to access a particular array element is by using the #at method
8379 * arr.at(0) #=> 1
8381 * The #slice method works in an identical manner to Array#[].
8383 * To raise an error for indices outside of the array bounds or else to
8384 * provide a default value when that happens, you can use #fetch.
8386 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8387 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8388 * arr.fetch(100, "oops") #=> "oops"
8390 * The special methods #first and #last will return the first and last
8391 * elements of an array, respectively.
8393 * arr.first #=> 1
8394 * arr.last #=> 6
8396 * To return the first +n+ elements of an array, use #take
8398 * arr.take(3) #=> [1, 2, 3]
8400 * #drop does the opposite of #take, by returning the elements after +n+
8401 * elements have been dropped:
8403 * arr.drop(3) #=> [4, 5, 6]
8405 * == Obtaining Information about an +Array+
8407 * Arrays keep track of their own length at all times. To query an array
8408 * about the number of elements it contains, use #length, #count or #size.
8410 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8411 * browsers.length #=> 5
8412 * browsers.count #=> 5
8414 * To check whether an array contains any elements at all
8416 * browsers.empty? #=> false
8418 * To check whether a particular item is included in the array
8420 * browsers.include?('Konqueror') #=> false
8422 * == Adding Items to Arrays
8424 * Items can be added to the end of an array by using either #push or #<<
8426 * arr = [1, 2, 3, 4]
8427 * arr.push(5) #=> [1, 2, 3, 4, 5]
8428 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8430 * #unshift will add a new item to the beginning of an array.
8432 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8434 * With #insert you can add a new element to an array at any position.
8436 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8438 * Using the #insert method, you can also insert multiple values at once:
8440 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8441 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8443 * == Removing Items from an +Array+
8445 * The method #pop removes the last element in an array and returns it:
8447 * arr = [1, 2, 3, 4, 5, 6]
8448 * arr.pop #=> 6
8449 * arr #=> [1, 2, 3, 4, 5]
8451 * To retrieve and at the same time remove the first item, use #shift:
8453 * arr.shift #=> 1
8454 * arr #=> [2, 3, 4, 5]
8456 * To delete an element at a particular index:
8458 * arr.delete_at(2) #=> 4
8459 * arr #=> [2, 3, 5]
8461 * To delete a particular element anywhere in an array, use #delete:
8463 * arr = [1, 2, 2, 3]
8464 * arr.delete(2) #=> 2
8465 * arr #=> [1,3]
8467 * A useful method if you need to remove +nil+ values from an array is
8468 * #compact:
8470 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8471 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8472 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8473 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8474 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8476 * Another common need is to remove duplicate elements from an array.
8478 * It has the non-destructive #uniq, and destructive method #uniq!
8480 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8481 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8483 * == Iterating over Arrays
8485 * Like all classes that include the Enumerable module, +Array+ has an each
8486 * method, which defines what elements should be iterated over and how. In
8487 * case of Array's #each, all elements in the +Array+ instance are yielded to
8488 * the supplied block in sequence.
8490 * Note that this operation leaves the array unchanged.
8492 * arr = [1, 2, 3, 4, 5]
8493 * arr.each {|a| print a -= 10, " "}
8494 * # prints: -9 -8 -7 -6 -5
8495 * #=> [1, 2, 3, 4, 5]
8497 * Another sometimes useful iterator is #reverse_each which will iterate over
8498 * the elements in the array in reverse order.
8500 * words = %w[first second third fourth fifth sixth]
8501 * str = ""
8502 * words.reverse_each {|word| str += "#{word} "}
8503 * p str #=> "sixth fifth fourth third second first "
8505 * The #map method can be used to create a new array based on the original
8506 * array, but with the values modified by the supplied block:
8508 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8509 * arr #=> [1, 2, 3, 4, 5]
8510 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8511 * arr #=> [1, 4, 9, 16, 25]
8514 * == Selecting Items from an +Array+
8516 * Elements can be selected from an array according to criteria defined in a
8517 * block. The selection can happen in a destructive or a non-destructive
8518 * manner. While the destructive operations will modify the array they were
8519 * called on, the non-destructive methods usually return a new array with the
8520 * selected elements, but leave the original array unchanged.
8522 * === Non-destructive Selection
8524 * arr = [1, 2, 3, 4, 5, 6]
8525 * arr.select {|a| a > 3} #=> [4, 5, 6]
8526 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8527 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8528 * arr #=> [1, 2, 3, 4, 5, 6]
8530 * === Destructive Selection
8532 * #select! and #reject! are the corresponding destructive methods to #select
8533 * and #reject
8535 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8536 * opposite result when supplied with the same block:
8538 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8539 * arr #=> [4, 5, 6]
8541 * arr = [1, 2, 3, 4, 5, 6]
8542 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8543 * arr #=> [1, 2, 3]
8545 * == What's Here
8547 * First, what's elsewhere. \Class +Array+:
8549 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8550 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8551 * which provides dozens of additional methods.
8553 * Here, class +Array+ provides methods that are useful for:
8555 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8556 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8557 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8558 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8559 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8560 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8561 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8562 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8563 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8564 * - {And more....}[rdoc-ref:Array@Other+Methods]
8566 * === Methods for Creating an +Array+
8568 * - ::[]: Returns a new array populated with given objects.
8569 * - ::new: Returns a new array.
8570 * - ::try_convert: Returns a new array created from a given object.
8572 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8574 * === Methods for Querying
8576 * - #length (aliased as #size): Returns the count of elements.
8577 * - #include?: Returns whether any element <tt>==</tt> a given object.
8578 * - #empty?: Returns whether there are no elements.
8579 * - #all?: Returns whether all elements meet a given criterion.
8580 * - #any?: Returns whether any element meets a given criterion.
8581 * - #none?: Returns whether no element <tt>==</tt> a given object.
8582 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8583 * - #count: Returns the count of elements that meet a given criterion.
8584 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8585 * - #rindex: Returns the index of the last element that meets a given criterion.
8586 * - #hash: Returns the integer hash code.
8588 * === Methods for Comparing
8590 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or
8591 * greater than a given object.
8592 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
8593 * in a given object.
8594 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8595 * element in a given object.
8597 * === Methods for Fetching
8599 * These methods do not modify +self+.
8601 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8602 * - #fetch: Returns the element at a given offset.
8603 * - #first: Returns one or more leading elements.
8604 * - #last: Returns one or more trailing elements.
8605 * - #max: Returns one or more maximum-valued elements,
8606 * as determined by <tt><=></tt> or a given block.
8607 * - #min: Returns one or more minimum-valued elements,
8608 * as determined by <tt><=></tt> or a given block.
8609 * - #minmax: Returns the minimum-valued and maximum-valued elements,
8610 * as determined by <tt><=></tt> or a given block.
8611 * - #assoc: Returns the first element that is an array
8612 * whose first element <tt>==</tt> a given object.
8613 * - #rassoc: Returns the first element that is an array
8614 * whose second element <tt>==</tt> a given object.
8615 * - #at: Returns the element at a given offset.
8616 * - #values_at: Returns the elements at given offsets.
8617 * - #dig: Returns the object in nested objects
8618 * that is specified by a given index and additional arguments.
8619 * - #drop: Returns trailing elements as determined by a given index.
8620 * - #take: Returns leading elements as determined by a given index.
8621 * - #drop_while: Returns trailing elements as determined by a given block.
8622 * - #take_while: Returns leading elements as determined by a given block.
8623 * - #sort: Returns all elements in an order determined by <tt><=></tt> or a given block.
8624 * - #reverse: Returns all elements in reverse order.
8625 * - #compact: Returns an array containing all non-+nil+ elements.
8626 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8627 * - #uniq: Returns an array containing non-duplicate elements.
8628 * - #rotate: Returns all elements with some rotated from one end to the other.
8629 * - #bsearch: Returns an element selected via a binary search
8630 * as determined by a given block.
8631 * - #bsearch_index: Returns the index of an element selected via a binary search
8632 * as determined by a given block.
8633 * - #sample: Returns one or more random elements.
8634 * - #shuffle: Returns elements in a random order.
8636 * === Methods for Assigning
8638 * These methods add, replace, or reorder elements in +self+.
8640 * - #[]=: Assigns specified elements with a given object.
8641 * - #<<: Appends an element.
8642 * - #push (aliased as #append): Appends elements.
8643 * - #unshift (aliased as #prepend): Prepends leading elements.
8644 * - #insert: Inserts given objects at a given offset; does not replace elements.
8645 * - #concat: Appends all elements from given arrays.
8646 * - #fill: Replaces specified elements with specified objects.
8647 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8648 * - #reverse!: Replaces +self+ with its elements reversed.
8649 * - #rotate!: Replaces +self+ with its elements rotated.
8650 * - #shuffle!: Replaces +self+ with its elements in random order.
8651 * - #sort!: Replaces +self+ with its elements sorted,
8652 * as determined by <tt><=></tt> or a given block.
8653 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8655 * === Methods for Deleting
8657 * Each of these methods removes elements from +self+:
8659 * - #pop: Removes and returns the last element.
8660 * - #shift: Removes and returns the first element.
8661 * - #compact!: Removes all +nil+ elements.
8662 * - #delete: Removes elements equal to a given object.
8663 * - #delete_at: Removes the element at a given offset.
8664 * - #delete_if: Removes elements specified by a given block.
8665 * - #clear: Removes all elements.
8666 * - #keep_if: Removes elements not specified by a given block.
8667 * - #reject!: Removes elements specified by a given block.
8668 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8669 * - #slice!: Removes and returns a sequence of elements.
8670 * - #uniq!: Removes duplicates.
8672 * === Methods for Combining
8674 * - #&: Returns an array containing elements found both in +self+ and a given array.
8675 * - #intersection: Returns an array containing elements found both in +self+
8676 * and in each given array.
8677 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8678 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8679 * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
8680 * duplicates removed.
8681 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
8682 * duplicates removed.
8683 * - #difference: Returns an array containing all elements of +self+ that are not found
8684 * in any of the given arrays..
8685 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8687 * === Methods for Iterating
8689 * - #each: Passes each element to a given block.
8690 * - #reverse_each: Passes each element, in reverse order, to a given block.
8691 * - #each_index: Passes each element index to a given block.
8692 * - #cycle: Calls a given block with each element, then does so again,
8693 * for a specified number of times, or forever.
8694 * - #combination: Calls a given block with combinations of elements of +self+;
8695 * a combination does not use the same element more than once.
8696 * - #permutation: Calls a given block with permutations of elements of +self+;
8697 * a permutation does not use the same element more than once.
8698 * - #repeated_combination: Calls a given block with combinations of elements of +self+;
8699 * a combination may use the same element more than once.
8700 * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
8701 * a permutation may use the same element more than once.
8703 * === Methods for Converting
8705 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8706 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8707 * - #flatten: Returns an array that is a recursive flattening of +self+.
8708 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8709 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8710 * - #join: Returns a newsString containing the elements joined by the field separator.
8711 * - #to_a: Returns +self+ or a new array containing all elements.
8712 * - #to_ary: Returns +self+.
8713 * - #to_h: Returns a new hash formed from the elements.
8714 * - #transpose: Transposes +self+, which must be an array of arrays.
8715 * - #zip: Returns a new array of arrays containing +self+ and given arrays;
8716 * follow the link for details.
8718 * === Other Methods
8720 * - #*: Returns one of the following:
8722 * - With integer argument +n+, a new array that is the concatenation
8723 * of +n+ copies of +self+.
8724 * - With string argument +field_separator+, a new string that is equivalent to
8725 * <tt>join(field_separator)</tt>.
8727 * - #pack: Packs the elements into a binary sequence.
8728 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8731 void
8732 Init_Array(void)
8734 fake_ary_flags = init_fake_ary_flags();
8736 rb_cArray = rb_define_class("Array", rb_cObject);
8737 rb_include_module(rb_cArray, rb_mEnumerable);
8739 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8740 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
8741 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8742 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8743 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8744 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8746 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
8747 rb_define_alias(rb_cArray, "to_s", "inspect");
8748 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
8749 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
8750 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
8752 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
8753 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
8754 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
8756 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
8757 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
8758 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
8759 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8760 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
8761 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
8762 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
8763 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
8764 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
8765 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
8766 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
8767 rb_define_alias(rb_cArray, "append", "push");
8768 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
8769 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
8770 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
8771 rb_define_alias(rb_cArray, "prepend", "unshift");
8772 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
8773 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
8774 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
8775 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
8776 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
8777 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
8778 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
8779 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
8780 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
8781 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
8782 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
8783 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
8784 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
8785 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
8786 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
8787 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
8788 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
8789 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
8790 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
8791 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
8792 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8793 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
8794 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8795 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
8796 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
8797 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
8798 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
8799 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
8800 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
8801 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
8802 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
8803 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
8804 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
8805 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
8806 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
8807 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
8808 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
8809 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
8810 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
8812 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
8813 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
8815 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
8816 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
8818 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
8819 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
8821 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
8822 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
8823 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
8825 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
8826 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
8827 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
8829 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
8830 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
8831 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
8832 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
8833 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
8834 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
8835 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
8836 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
8837 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
8838 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
8839 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
8840 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
8841 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
8843 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
8844 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
8845 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
8846 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
8847 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
8848 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
8849 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
8850 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
8851 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
8852 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
8853 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
8854 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
8855 rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
8857 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
8859 rb_cArray_empty_frozen = rb_ary_freeze(rb_ary_new());
8860 rb_vm_register_global_object(rb_cArray_empty_frozen);
8863 #include "array.rbinc"