[DOC] Tweaks for Array#repeated_combination (#11839)
[ruby.git] / array.c
blobd28f03cb4c81ea37244505d051dbe426f4691989
1 /**********************************************************************
3 array.c -
5 $Author$
6 created at: Fri Aug 6 09:46:12 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "debug_counter.h"
15 #include "id.h"
16 #include "internal.h"
17 #include "internal/array.h"
18 #include "internal/compar.h"
19 #include "internal/enum.h"
20 #include "internal/gc.h"
21 #include "internal/hash.h"
22 #include "internal/numeric.h"
23 #include "internal/object.h"
24 #include "internal/proc.h"
25 #include "internal/rational.h"
26 #include "internal/vm.h"
27 #include "probes.h"
28 #include "ruby/encoding.h"
29 #include "ruby/st.h"
30 #include "ruby/util.h"
31 #include "vm_core.h"
32 #include "builtin.h"
34 #if !ARRAY_DEBUG
35 # undef NDEBUG
36 # define NDEBUG
37 #endif
38 #include "ruby_assert.h"
40 VALUE rb_cArray;
41 VALUE rb_cArray_empty_frozen;
43 /* Flags of RArray
45 * 1: RARRAY_EMBED_FLAG
46 * The array is embedded (its contents follow the header, rather than
47 * being on a separately allocated buffer).
48 * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
49 * The array is shared. The buffer this array points to is owned by
50 * another array (the shared root).
51 * 3-9: RARRAY_EMBED_LEN
52 * The length of the array when RARRAY_EMBED_FLAG is set.
53 * 12: RARRAY_SHARED_ROOT_FLAG
54 * The array is a shared root that does reference counting. The buffer
55 * this array points to is owned by this array but may be pointed to
56 * by other arrays.
57 * Note: Frozen arrays may be a shared root without this flag being
58 * set. Frozen arrays do not have reference counting because
59 * they cannot be modified. Not updating the reference count
60 * improves copy-on-write performance. Their reference count is
61 * assumed to be infinity.
62 * 14: RARRAY_PTR_IN_USE_FLAG
63 * The buffer of the array is in use. This is only used during
64 * debugging.
67 /* for OPTIMIZED_CMP: */
68 #define id_cmp idCmp
70 #define ARY_DEFAULT_SIZE 16
71 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
72 #define SMALL_ARRAY_LEN 16
74 RBIMPL_ATTR_MAYBE_UNUSED()
75 static int
76 should_be_T_ARRAY(VALUE ary)
78 return RB_TYPE_P(ary, T_ARRAY);
81 #define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
82 #define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
83 #define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
84 RARRAY(a)->as.heap.aux.capa)
86 #define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
87 #define ARY_EMBED_LEN(a) \
88 (RUBY_ASSERT(ARY_EMBED_P(a)), \
89 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
90 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
91 #define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
93 #define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
94 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
96 #define FL_SET_EMBED(a) do { \
97 RUBY_ASSERT(!ARY_SHARED_P(a)); \
98 FL_SET((a), RARRAY_EMBED_FLAG); \
99 ary_verify(a); \
100 } while (0)
102 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
103 #define FL_SET_SHARED(ary) do { \
104 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
105 FL_SET((ary), RARRAY_SHARED_FLAG); \
106 } while (0)
107 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
109 #define ARY_SET_PTR(ary, p) do { \
110 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
111 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
112 RARRAY(ary)->as.heap.ptr = (p); \
113 } while (0)
114 #define ARY_SET_EMBED_LEN(ary, n) do { \
115 long tmp_n = (n); \
116 RUBY_ASSERT(ARY_EMBED_P(ary)); \
117 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
118 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
119 } while (0)
120 #define ARY_SET_HEAP_LEN(ary, n) do { \
121 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
122 RARRAY(ary)->as.heap.len = (n); \
123 } while (0)
124 #define ARY_SET_LEN(ary, n) do { \
125 if (ARY_EMBED_P(ary)) { \
126 ARY_SET_EMBED_LEN((ary), (n)); \
128 else { \
129 ARY_SET_HEAP_LEN((ary), (n)); \
131 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
132 } while (0)
133 #define ARY_INCREASE_PTR(ary, n) do { \
134 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
135 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
136 RARRAY(ary)->as.heap.ptr += (n); \
137 } while (0)
138 #define ARY_INCREASE_LEN(ary, n) do { \
139 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
140 if (ARY_EMBED_P(ary)) { \
141 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
143 else { \
144 RARRAY(ary)->as.heap.len += (n); \
146 } while (0)
148 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
149 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
150 #define ARY_SET_CAPA(ary, n) do { \
151 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
152 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
153 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
154 RARRAY(ary)->as.heap.aux.capa = (n); \
155 } while (0)
157 #define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
158 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
159 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
160 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
161 RUBY_ASSERT((value) >= 0); \
162 RARRAY(ary)->as.heap.aux.capa = (value); \
163 } while (0)
164 #define FL_SET_SHARED_ROOT(ary) do { \
165 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
166 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
167 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
168 } while (0)
170 static inline void
171 ARY_SET(VALUE a, long i, VALUE v)
173 RUBY_ASSERT(!ARY_SHARED_P(a));
174 RUBY_ASSERT(!OBJ_FROZEN(a));
176 RARRAY_ASET(a, i, v);
178 #undef RARRAY_ASET
180 static long
181 ary_embed_capa(VALUE ary)
183 size_t size = rb_gc_obj_slot_size(ary) - offsetof(struct RArray, as.ary);
184 RUBY_ASSERT(size % sizeof(VALUE) == 0);
185 return size / sizeof(VALUE);
188 static size_t
189 ary_embed_size(long capa)
191 return offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
194 static bool
195 ary_embeddable_p(long capa)
197 return rb_gc_size_allocatable_p(ary_embed_size(capa));
200 bool
201 rb_ary_embeddable_p(VALUE ary)
203 /* An array cannot be turned embeddable when the array is:
204 * - Shared root: other objects may point to the buffer of this array
205 * so we cannot make it embedded.
206 * - Frozen: this array may also be a shared root without the shared root
207 * flag.
208 * - Shared: we don't want to re-embed an array that points to a shared
209 * root (to save memory).
211 return !(ARY_SHARED_ROOT_P(ary) || OBJ_FROZEN(ary) || ARY_SHARED_P(ary));
214 size_t
215 rb_ary_size_as_embedded(VALUE ary)
217 size_t real_size;
219 if (ARY_EMBED_P(ary)) {
220 real_size = ary_embed_size(ARY_EMBED_LEN(ary));
222 else if (rb_ary_embeddable_p(ary)) {
223 real_size = ary_embed_size(ARY_HEAP_CAPA(ary));
225 else {
226 real_size = sizeof(struct RArray);
228 return real_size;
232 #if ARRAY_DEBUG
233 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
235 static VALUE
236 ary_verify_(VALUE ary, const char *file, int line)
238 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
240 if (ARY_SHARED_P(ary)) {
241 VALUE root = ARY_SHARED_ROOT(ary);
242 const VALUE *ptr = ARY_HEAP_PTR(ary);
243 const VALUE *root_ptr = RARRAY_CONST_PTR(root);
244 long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
245 RUBY_ASSERT(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
246 RUBY_ASSERT(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
247 ary_verify(root);
249 else if (ARY_EMBED_P(ary)) {
250 RUBY_ASSERT(!ARY_SHARED_P(ary));
251 RUBY_ASSERT(RARRAY_LEN(ary) <= ary_embed_capa(ary));
253 else {
254 const VALUE *ptr = RARRAY_CONST_PTR(ary);
255 long i, len = RARRAY_LEN(ary);
256 volatile VALUE v;
257 if (len > 1) len = 1; /* check only HEAD */
258 for (i=0; i<len; i++) {
259 v = ptr[i]; /* access check */
261 v = v;
264 return ary;
267 void
268 rb_ary_verify(VALUE ary)
270 ary_verify(ary);
272 #else
273 #define ary_verify(ary) ((void)0)
274 #endif
276 VALUE *
277 rb_ary_ptr_use_start(VALUE ary)
279 #if ARRAY_DEBUG
280 FL_SET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
281 #endif
282 return (VALUE *)RARRAY_CONST_PTR(ary);
285 void
286 rb_ary_ptr_use_end(VALUE ary)
288 #if ARRAY_DEBUG
289 FL_UNSET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
290 #endif
293 void
294 rb_mem_clear(VALUE *mem, long size)
296 while (size--) {
297 *mem++ = Qnil;
301 static void
302 ary_mem_clear(VALUE ary, long beg, long size)
304 RARRAY_PTR_USE(ary, ptr, {
305 rb_mem_clear(ptr + beg, size);
309 static inline void
310 memfill(register VALUE *mem, register long size, register VALUE val)
312 while (size--) {
313 *mem++ = val;
317 static void
318 ary_memfill(VALUE ary, long beg, long size, VALUE val)
320 RARRAY_PTR_USE(ary, ptr, {
321 memfill(ptr + beg, size, val);
322 RB_OBJ_WRITTEN(ary, Qundef, val);
326 static void
327 ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
329 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary));
331 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
332 rb_gc_writebarrier_remember(buff_owner_ary);
333 RARRAY_PTR_USE(ary, ptr, {
334 MEMCPY(ptr+beg, argv, VALUE, argc);
337 else {
338 int i;
339 RARRAY_PTR_USE(ary, ptr, {
340 for (i=0; i<argc; i++) {
341 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
347 static void
348 ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
350 ary_memcpy0(ary, beg, argc, argv, ary);
353 static VALUE *
354 ary_heap_alloc_buffer(size_t capa)
356 return ALLOC_N(VALUE, capa);
359 static void
360 ary_heap_free_ptr(VALUE ary, const VALUE *ptr, long size)
362 ruby_sized_xfree((void *)ptr, size);
365 static void
366 ary_heap_free(VALUE ary)
368 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
371 static size_t
372 ary_heap_realloc(VALUE ary, size_t new_capa)
374 RUBY_ASSERT(!OBJ_FROZEN(ary));
375 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, ARY_HEAP_CAPA(ary));
376 ary_verify(ary);
378 return new_capa;
381 void
382 rb_ary_make_embedded(VALUE ary)
384 RUBY_ASSERT(rb_ary_embeddable_p(ary));
385 if (!ARY_EMBED_P(ary)) {
386 const VALUE *buf = ARY_HEAP_PTR(ary);
387 long len = ARY_HEAP_LEN(ary);
389 FL_SET_EMBED(ary);
390 ARY_SET_EMBED_LEN(ary, len);
392 MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
394 ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
398 static void
399 ary_resize_capa(VALUE ary, long capacity)
401 RUBY_ASSERT(RARRAY_LEN(ary) <= capacity);
402 RUBY_ASSERT(!OBJ_FROZEN(ary));
403 RUBY_ASSERT(!ARY_SHARED_P(ary));
405 if (capacity > ary_embed_capa(ary)) {
406 size_t new_capa = capacity;
407 if (ARY_EMBED_P(ary)) {
408 long len = ARY_EMBED_LEN(ary);
409 VALUE *ptr = ary_heap_alloc_buffer(capacity);
411 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
412 FL_UNSET_EMBED(ary);
413 ARY_SET_PTR(ary, ptr);
414 ARY_SET_HEAP_LEN(ary, len);
416 else {
417 new_capa = ary_heap_realloc(ary, capacity);
419 ARY_SET_CAPA(ary, new_capa);
421 else {
422 if (!ARY_EMBED_P(ary)) {
423 long len = ARY_HEAP_LEN(ary);
424 long old_capa = ARY_HEAP_CAPA(ary);
425 const VALUE *ptr = ARY_HEAP_PTR(ary);
427 if (len > capacity) len = capacity;
428 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
429 ary_heap_free_ptr(ary, ptr, old_capa);
431 FL_SET_EMBED(ary);
432 ARY_SET_LEN(ary, len);
436 ary_verify(ary);
439 static inline void
440 ary_shrink_capa(VALUE ary)
442 long capacity = ARY_HEAP_LEN(ary);
443 long old_capa = ARY_HEAP_CAPA(ary);
444 RUBY_ASSERT(!ARY_SHARED_P(ary));
445 RUBY_ASSERT(old_capa >= capacity);
446 if (old_capa > capacity) {
447 size_t new_capa = ary_heap_realloc(ary, capacity);
448 ARY_SET_CAPA(ary, new_capa);
451 ary_verify(ary);
454 static void
455 ary_double_capa(VALUE ary, long min)
457 long new_capa = ARY_CAPA(ary) / 2;
459 if (new_capa < ARY_DEFAULT_SIZE) {
460 new_capa = ARY_DEFAULT_SIZE;
462 if (new_capa >= ARY_MAX_SIZE - min) {
463 new_capa = (ARY_MAX_SIZE - min) / 2;
465 new_capa += min;
466 ary_resize_capa(ary, new_capa);
468 ary_verify(ary);
471 static void
472 rb_ary_decrement_share(VALUE shared_root)
474 if (!OBJ_FROZEN(shared_root)) {
475 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
476 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
480 static void
481 rb_ary_unshare(VALUE ary)
483 VALUE shared_root = ARY_SHARED_ROOT(ary);
484 rb_ary_decrement_share(shared_root);
485 FL_UNSET_SHARED(ary);
488 static void
489 rb_ary_reset(VALUE ary)
491 if (ARY_OWNS_HEAP_P(ary)) {
492 ary_heap_free(ary);
494 else if (ARY_SHARED_P(ary)) {
495 rb_ary_unshare(ary);
498 FL_SET_EMBED(ary);
499 ARY_SET_EMBED_LEN(ary, 0);
502 static VALUE
503 rb_ary_increment_share(VALUE shared_root)
505 if (!OBJ_FROZEN(shared_root)) {
506 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
507 RUBY_ASSERT(num >= 0);
508 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
510 return shared_root;
513 static void
514 rb_ary_set_shared(VALUE ary, VALUE shared_root)
516 RUBY_ASSERT(!ARY_EMBED_P(ary));
517 RUBY_ASSERT(!OBJ_FROZEN(ary));
518 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root));
520 rb_ary_increment_share(shared_root);
521 FL_SET_SHARED(ary);
522 RB_OBJ_WRITE(ary, &RARRAY(ary)->as.heap.aux.shared_root, shared_root);
524 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
527 static inline void
528 rb_ary_modify_check(VALUE ary)
530 rb_check_frozen(ary);
531 ary_verify(ary);
534 void
535 rb_ary_cancel_sharing(VALUE ary)
537 if (ARY_SHARED_P(ary)) {
538 long shared_len, len = RARRAY_LEN(ary);
539 VALUE shared_root = ARY_SHARED_ROOT(ary);
541 ary_verify(shared_root);
543 if (len <= ary_embed_capa(ary)) {
544 const VALUE *ptr = ARY_HEAP_PTR(ary);
545 FL_UNSET_SHARED(ary);
546 FL_SET_EMBED(ary);
547 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
548 rb_ary_decrement_share(shared_root);
549 ARY_SET_EMBED_LEN(ary, len);
551 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
552 long shift = RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared_root);
553 FL_UNSET_SHARED(ary);
554 ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared_root));
555 ARY_SET_CAPA(ary, shared_len);
556 RARRAY_PTR_USE(ary, ptr, {
557 MEMMOVE(ptr, ptr+shift, VALUE, len);
559 FL_SET_EMBED(shared_root);
560 rb_ary_decrement_share(shared_root);
562 else {
563 VALUE *ptr = ary_heap_alloc_buffer(len);
564 MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
565 rb_ary_unshare(ary);
566 ARY_SET_CAPA(ary, len);
567 ARY_SET_PTR(ary, ptr);
570 rb_gc_writebarrier_remember(ary);
572 ary_verify(ary);
575 void
576 rb_ary_modify(VALUE ary)
578 rb_ary_modify_check(ary);
579 rb_ary_cancel_sharing(ary);
582 static VALUE
583 ary_ensure_room_for_push(VALUE ary, long add_len)
585 long old_len = RARRAY_LEN(ary);
586 long new_len = old_len + add_len;
587 long capa;
589 if (old_len > ARY_MAX_SIZE - add_len) {
590 rb_raise(rb_eIndexError, "index %ld too big", new_len);
592 if (ARY_SHARED_P(ary)) {
593 if (new_len > ary_embed_capa(ary)) {
594 VALUE shared_root = ARY_SHARED_ROOT(ary);
595 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
596 if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
597 rb_ary_modify_check(ary);
599 ary_verify(ary);
600 ary_verify(shared_root);
601 return shared_root;
603 else {
604 /* if array is shared, then it is likely it participate in push/shift pattern */
605 rb_ary_modify(ary);
606 capa = ARY_CAPA(ary);
607 if (new_len > capa - (capa >> 6)) {
608 ary_double_capa(ary, new_len);
610 ary_verify(ary);
611 return ary;
615 ary_verify(ary);
616 rb_ary_modify(ary);
618 else {
619 rb_ary_modify_check(ary);
621 capa = ARY_CAPA(ary);
622 if (new_len > capa) {
623 ary_double_capa(ary, new_len);
626 ary_verify(ary);
627 return ary;
631 * call-seq:
632 * freeze -> self
634 * Freezes +self+ (if not already frozen); returns +self+:
636 * a = []
637 * a.frozen? # => false
638 * a.freeze
639 * a.frozen? # => true
641 * No further changes may be made to +self+;
642 * raises FrozenError if a change is attempted.
644 * Related: Kernel#frozen?.
647 VALUE
648 rb_ary_freeze(VALUE ary)
650 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
652 if (OBJ_FROZEN(ary)) return ary;
654 if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) {
655 ary_shrink_capa(ary);
658 return rb_obj_freeze(ary);
661 /* This can be used to take a snapshot of an array (with
662 e.g. rb_ary_replace) and check later whether the array has been
663 modified from the snapshot. The snapshot is cheap, though if
664 something does modify the array it will pay the cost of copying
665 it. If Array#pop or Array#shift has been called, the array will
666 be still shared with the snapshot, but the array length will
667 differ. */
668 VALUE
669 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
671 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
672 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
673 ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
674 ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
675 return Qtrue;
677 return Qfalse;
680 static VALUE
681 ary_alloc_embed(VALUE klass, long capa)
683 size_t size = ary_embed_size(capa);
684 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
685 NEWOBJ_OF(ary, struct RArray, klass,
686 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
687 size, 0);
688 /* Created array is:
689 * FL_SET_EMBED((VALUE)ary);
690 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
692 return (VALUE)ary;
695 static VALUE
696 ary_alloc_heap(VALUE klass)
698 NEWOBJ_OF(ary, struct RArray, klass,
699 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
700 sizeof(struct RArray), 0);
701 return (VALUE)ary;
704 static VALUE
705 empty_ary_alloc(VALUE klass)
707 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
708 return ary_alloc_embed(klass, 0);
711 static VALUE
712 ary_new(VALUE klass, long capa)
714 VALUE ary;
716 if (capa < 0) {
717 rb_raise(rb_eArgError, "negative array size (or size too big)");
719 if (capa > ARY_MAX_SIZE) {
720 rb_raise(rb_eArgError, "array size too big");
723 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
725 if (ary_embeddable_p(capa)) {
726 ary = ary_alloc_embed(klass, capa);
728 else {
729 ary = ary_alloc_heap(klass);
730 ARY_SET_CAPA(ary, capa);
731 RUBY_ASSERT(!ARY_EMBED_P(ary));
733 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
734 ARY_SET_HEAP_LEN(ary, 0);
737 return ary;
740 VALUE
741 rb_ary_new_capa(long capa)
743 return ary_new(rb_cArray, capa);
746 VALUE
747 rb_ary_new(void)
749 return rb_ary_new_capa(0);
752 VALUE
753 (rb_ary_new_from_args)(long n, ...)
755 va_list ar;
756 VALUE ary;
757 long i;
759 ary = rb_ary_new2(n);
761 va_start(ar, n);
762 for (i=0; i<n; i++) {
763 ARY_SET(ary, i, va_arg(ar, VALUE));
765 va_end(ar);
767 ARY_SET_LEN(ary, n);
768 return ary;
771 VALUE
772 rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
774 VALUE ary;
776 ary = ary_new(klass, n);
777 if (n > 0 && elts) {
778 ary_memcpy(ary, 0, n, elts);
779 ARY_SET_LEN(ary, n);
782 return ary;
785 VALUE
786 rb_ary_new_from_values(long n, const VALUE *elts)
788 return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
791 static VALUE
792 ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
794 size_t size = ary_embed_size(capa);
795 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
796 NEWOBJ_OF(ary, struct RArray, klass,
797 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
798 size, ec);
799 /* Created array is:
800 * FL_SET_EMBED((VALUE)ary);
801 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
803 return (VALUE)ary;
806 static VALUE
807 ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
809 NEWOBJ_OF(ary, struct RArray, klass,
810 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
811 sizeof(struct RArray), ec);
812 return (VALUE)ary;
815 static VALUE
816 ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
818 VALUE ary;
820 if (capa < 0) {
821 rb_raise(rb_eArgError, "negative array size (or size too big)");
823 if (capa > ARY_MAX_SIZE) {
824 rb_raise(rb_eArgError, "array size too big");
827 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
829 if (ary_embeddable_p(capa)) {
830 ary = ec_ary_alloc_embed(ec, klass, capa);
832 else {
833 ary = ec_ary_alloc_heap(ec, klass);
834 ARY_SET_CAPA(ary, capa);
835 RUBY_ASSERT(!ARY_EMBED_P(ary));
837 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
838 ARY_SET_HEAP_LEN(ary, 0);
841 return ary;
844 VALUE
845 rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
847 VALUE ary;
849 ary = ec_ary_new(ec, rb_cArray, n);
850 if (n > 0 && elts) {
851 ary_memcpy(ary, 0, n, elts);
852 ARY_SET_LEN(ary, n);
855 return ary;
858 VALUE
859 rb_ary_hidden_new(long capa)
861 VALUE ary = ary_new(0, capa);
862 return ary;
865 VALUE
866 rb_ary_hidden_new_fill(long capa)
868 VALUE ary = rb_ary_hidden_new(capa);
869 ary_memfill(ary, 0, capa, Qnil);
870 ARY_SET_LEN(ary, capa);
871 return ary;
874 void
875 rb_ary_free(VALUE ary)
877 if (ARY_OWNS_HEAP_P(ary)) {
878 if (USE_DEBUG_COUNTER &&
879 !ARY_SHARED_ROOT_P(ary) &&
880 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
881 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
884 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
885 ary_heap_free(ary);
887 else {
888 RB_DEBUG_COUNTER_INC(obj_ary_embed);
891 if (ARY_SHARED_P(ary)) {
892 RB_DEBUG_COUNTER_INC(obj_ary_shared);
894 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
895 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
899 static VALUE fake_ary_flags;
901 static VALUE
902 init_fake_ary_flags(void)
904 struct RArray fake_ary = {0};
905 fake_ary.basic.flags = T_ARRAY;
906 VALUE ary = (VALUE)&fake_ary;
907 rb_ary_freeze(ary);
908 return fake_ary.basic.flags;
911 VALUE
912 rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len)
914 fake_ary->basic.flags = fake_ary_flags;
915 RBASIC_CLEAR_CLASS((VALUE)fake_ary);
917 // bypass frozen checks
918 fake_ary->as.heap.ptr = list;
919 fake_ary->as.heap.len = len;
920 fake_ary->as.heap.aux.capa = len;
921 return (VALUE)fake_ary;
924 size_t
925 rb_ary_memsize(VALUE ary)
927 if (ARY_OWNS_HEAP_P(ary)) {
928 return ARY_CAPA(ary) * sizeof(VALUE);
930 else {
931 return 0;
935 static VALUE
936 ary_make_shared(VALUE ary)
938 ary_verify(ary);
940 if (ARY_SHARED_P(ary)) {
941 return ARY_SHARED_ROOT(ary);
943 else if (ARY_SHARED_ROOT_P(ary)) {
944 return ary;
946 else if (OBJ_FROZEN(ary)) {
947 return ary;
949 else {
950 long capa = ARY_CAPA(ary);
951 long len = RARRAY_LEN(ary);
953 /* Shared roots cannot be embedded because the reference count
954 * (refcnt) is stored in as.heap.aux.capa. */
955 VALUE shared = ary_alloc_heap(0);
956 FL_SET_SHARED_ROOT(shared);
958 if (ARY_EMBED_P(ary)) {
959 VALUE *ptr = ary_heap_alloc_buffer(capa);
960 ARY_SET_PTR(shared, ptr);
961 ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary));
963 FL_UNSET_EMBED(ary);
964 ARY_SET_HEAP_LEN(ary, len);
965 ARY_SET_PTR(ary, ptr);
967 else {
968 ARY_SET_PTR(shared, RARRAY_CONST_PTR(ary));
971 ARY_SET_LEN(shared, capa);
972 ary_mem_clear(shared, len, capa - len);
973 rb_ary_set_shared(ary, shared);
975 ary_verify(shared);
976 ary_verify(ary);
978 return shared;
982 static VALUE
983 ary_make_substitution(VALUE ary)
985 long len = RARRAY_LEN(ary);
987 if (ary_embeddable_p(len)) {
988 VALUE subst = rb_ary_new_capa(len);
989 RUBY_ASSERT(ARY_EMBED_P(subst));
991 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
992 ARY_SET_EMBED_LEN(subst, len);
993 return subst;
995 else {
996 return rb_ary_increment_share(ary_make_shared(ary));
1000 VALUE
1001 rb_assoc_new(VALUE car, VALUE cdr)
1003 return rb_ary_new3(2, car, cdr);
1006 VALUE
1007 rb_to_array_type(VALUE ary)
1009 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1011 #define to_ary rb_to_array_type
1013 VALUE
1014 rb_check_array_type(VALUE ary)
1016 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1019 VALUE
1020 rb_check_to_array(VALUE ary)
1022 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1025 VALUE
1026 rb_to_array(VALUE ary)
1028 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1032 * call-seq:
1033 * Array.try_convert(object) -> object, new_array, or nil
1035 * Attempts to return an array, based on the given +object+.
1037 * If +object+ is an array, returns +object+.
1039 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1040 * calls <tt>object.to_ary</tt>:
1041 * if the return value is an array or +nil+, returns that value;
1042 * if not, raises TypeError.
1044 * Otherwise returns +nil+.
1046 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1049 static VALUE
1050 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
1052 return rb_check_array_type(ary);
1055 /* :nodoc: */
1056 static VALUE
1057 rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
1059 VALUE ary;
1061 if (klass == rb_cArray) {
1062 long size = 0;
1063 if (argc > 0 && FIXNUM_P(argv[0])) {
1064 size = FIX2LONG(argv[0]);
1065 if (size < 0) size = 0;
1068 ary = ary_new(klass, size);
1070 rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
1072 else {
1073 ary = rb_class_new_instance_pass_kw(argc, argv, klass);
1076 return ary;
1080 * call-seq:
1081 * Array.new -> new_empty_array
1082 * Array.new(array) -> new_array
1083 * Array.new(size, default_value = nil) -> new_array
1084 * Array.new(size = 0) {|index| ... } -> new_array
1086 * Returns a new array.
1088 * With no block and no argument given, returns a new empty array:
1090 * Array.new # => []
1092 * With no block and array argument given, returns a new array with the same elements:
1094 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1096 * With no block and integer argument given, returns a new array containing
1097 * that many instances of the given +default_value+:
1099 * Array.new(0) # => []
1100 * Array.new(3) # => [nil, nil, nil]
1101 * Array.new(2, 3) # => [3, 3]
1103 * With a block given, returns an array of the given +size+;
1104 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1105 * the element at that +index+ in the returned array is the blocks return value:
1107 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1109 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1111 * array = Array.new(2, {})
1112 * array # => [{}, {}]
1113 * array[0][:a] = 1
1114 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1116 * If you want the elements of the array to be distinct, you should pass a block:
1118 * array = Array.new(2) { {} }
1119 * array # => [{}, {}]
1120 * array[0][:a] = 1
1121 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1123 * Raises TypeError if the first argument is not either an array
1124 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1125 * Raises ArgumentError if the first argument is a negative integer.
1127 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1130 static VALUE
1131 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1133 long len;
1134 VALUE size, val;
1136 rb_ary_modify(ary);
1137 if (argc == 0) {
1138 rb_ary_reset(ary);
1139 RUBY_ASSERT(ARY_EMBED_P(ary));
1140 RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
1141 if (rb_block_given_p()) {
1142 rb_warning("given block not used");
1144 return ary;
1146 rb_scan_args(argc, argv, "02", &size, &val);
1147 if (argc == 1 && !FIXNUM_P(size)) {
1148 val = rb_check_array_type(size);
1149 if (!NIL_P(val)) {
1150 rb_ary_replace(ary, val);
1151 return ary;
1155 len = NUM2LONG(size);
1156 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1157 if (len < 0) {
1158 rb_raise(rb_eArgError, "negative array size");
1160 if (len > ARY_MAX_SIZE) {
1161 rb_raise(rb_eArgError, "array size too big");
1163 /* recheck after argument conversion */
1164 rb_ary_modify(ary);
1165 ary_resize_capa(ary, len);
1166 if (rb_block_given_p()) {
1167 long i;
1169 if (argc == 2) {
1170 rb_warn("block supersedes default value argument");
1172 for (i=0; i<len; i++) {
1173 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
1174 ARY_SET_LEN(ary, i + 1);
1177 else {
1178 ary_memfill(ary, 0, len, val);
1179 ARY_SET_LEN(ary, len);
1181 return ary;
1185 * Returns a new array, populated with the given objects:
1187 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1188 * Array[] # => []
1189 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1191 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1194 static VALUE
1195 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1197 VALUE ary = ary_new(klass, argc);
1198 if (argc > 0 && argv) {
1199 ary_memcpy(ary, 0, argc, argv);
1200 ARY_SET_LEN(ary, argc);
1203 return ary;
1206 void
1207 rb_ary_store(VALUE ary, long idx, VALUE val)
1209 long len = RARRAY_LEN(ary);
1211 if (idx < 0) {
1212 idx += len;
1213 if (idx < 0) {
1214 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1215 idx - len, -len);
1218 else if (idx >= ARY_MAX_SIZE) {
1219 rb_raise(rb_eIndexError, "index %ld too big", idx);
1222 rb_ary_modify(ary);
1223 if (idx >= ARY_CAPA(ary)) {
1224 ary_double_capa(ary, idx);
1226 if (idx > len) {
1227 ary_mem_clear(ary, len, idx - len + 1);
1230 if (idx >= len) {
1231 ARY_SET_LEN(ary, idx + 1);
1233 ARY_SET(ary, idx, val);
1236 static VALUE
1237 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1239 RUBY_ASSERT(offset >= 0);
1240 RUBY_ASSERT(len >= 0);
1241 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1243 VALUE result = ary_alloc_heap(klass);
1244 size_t embed_capa = ary_embed_capa(result);
1245 if ((size_t)len <= embed_capa) {
1246 FL_SET_EMBED(result);
1247 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
1248 ARY_SET_EMBED_LEN(result, len);
1250 else {
1251 VALUE shared = ary_make_shared(ary);
1253 /* The ary_make_shared call may allocate, which can trigger a GC
1254 * compaction. This can cause the array to be embedded because it has
1255 * a length of 0. */
1256 FL_UNSET_EMBED(result);
1258 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
1259 ARY_SET_LEN(result, RARRAY_LEN(ary));
1260 rb_ary_set_shared(result, shared);
1262 ARY_INCREASE_PTR(result, offset);
1263 ARY_SET_LEN(result, len);
1265 ary_verify(shared);
1268 ary_verify(result);
1269 return result;
1272 static VALUE
1273 ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
1275 RUBY_ASSERT(offset >= 0);
1276 RUBY_ASSERT(len >= 0);
1277 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1278 RUBY_ASSERT(step != 0);
1280 const long orig_len = len;
1282 if (step > 0 && step >= len) {
1283 VALUE result = ary_new(klass, 1);
1284 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1285 const VALUE *values = RARRAY_CONST_PTR(ary);
1287 RB_OBJ_WRITE(result, ptr, values[offset]);
1288 ARY_SET_EMBED_LEN(result, 1);
1289 return result;
1291 else if (step < 0 && step < -len) {
1292 step = -len;
1295 long ustep = (step < 0) ? -step : step;
1296 len = roomof(len, ustep);
1298 long i;
1299 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1301 VALUE result = ary_new(klass, len);
1302 if (ARY_EMBED_P(result)) {
1303 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1304 const VALUE *values = RARRAY_CONST_PTR(ary);
1306 for (i = 0; i < len; ++i) {
1307 RB_OBJ_WRITE(result, ptr+i, values[j]);
1308 j += step;
1310 ARY_SET_EMBED_LEN(result, len);
1312 else {
1313 const VALUE *values = RARRAY_CONST_PTR(ary);
1315 RARRAY_PTR_USE(result, ptr, {
1316 for (i = 0; i < len; ++i) {
1317 RB_OBJ_WRITE(result, ptr+i, values[j]);
1318 j += step;
1321 ARY_SET_LEN(result, len);
1324 return result;
1327 static VALUE
1328 ary_make_shared_copy(VALUE ary)
1330 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
1333 enum ary_take_pos_flags
1335 ARY_TAKE_FIRST = 0,
1336 ARY_TAKE_LAST = 1
1339 static VALUE
1340 ary_take_first_or_last_n(VALUE ary, long n, enum ary_take_pos_flags last)
1342 long len = RARRAY_LEN(ary);
1343 long offset = 0;
1345 if (n > len) {
1346 n = len;
1348 else if (n < 0) {
1349 rb_raise(rb_eArgError, "negative array size");
1351 if (last) {
1352 offset = len - n;
1354 return ary_make_partial(ary, rb_cArray, offset, n);
1357 static VALUE
1358 ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1360 argc = rb_check_arity(argc, 0, 1);
1361 /* the case optional argument is omitted should be handled in
1362 * callers of this function. if another arity case is added,
1363 * this arity check needs to rewrite. */
1364 RUBY_ASSERT_ALWAYS(argc == 1);
1365 return ary_take_first_or_last_n(ary, NUM2LONG(argv[0]), last);
1369 * call-seq:
1370 * self << object -> self
1372 * Appends +object+ as the last element in +self+; returns +self+:
1374 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1376 * Appends +object+ as a single element, even if it is another array:
1378 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1380 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1383 VALUE
1384 rb_ary_push(VALUE ary, VALUE item)
1386 long idx = RARRAY_LEN((ary_verify(ary), ary));
1387 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1388 RARRAY_PTR_USE(ary, ptr, {
1389 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1391 ARY_SET_LEN(ary, idx + 1);
1392 ary_verify(ary);
1393 return ary;
1396 VALUE
1397 rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1399 long oldlen = RARRAY_LEN(ary);
1400 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1401 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1402 ARY_SET_LEN(ary, oldlen + len);
1403 return ary;
1407 * call-seq:
1408 * push(*objects) -> self
1409 * append(*objects) -> self
1411 * Appends each argument in +objects+ to +self+; returns +self+:
1413 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1414 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1416 * Appends each argument as a single element, even if it is another array:
1418 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1419 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1421 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1424 static VALUE
1425 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1427 return rb_ary_cat(ary, argv, argc);
1430 VALUE
1431 rb_ary_pop(VALUE ary)
1433 long n;
1434 rb_ary_modify_check(ary);
1435 n = RARRAY_LEN(ary);
1436 if (n == 0) return Qnil;
1437 if (ARY_OWNS_HEAP_P(ary) &&
1438 n * 3 < ARY_CAPA(ary) &&
1439 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1441 ary_resize_capa(ary, n * 2);
1443 --n;
1444 ARY_SET_LEN(ary, n);
1445 ary_verify(ary);
1446 return RARRAY_AREF(ary, n);
1450 * call-seq:
1451 * pop -> object or nil
1452 * pop(count) -> new_array
1454 * Removes and returns trailing elements of +self+.
1456 * With no argument given, removes and returns the last element, if available;
1457 * otherwise returns +nil+:
1459 * a = [:foo, 'bar', 2]
1460 * a.pop # => 2
1461 * a # => [:foo, "bar"]
1462 * [].pop # => nil
1464 * With non-negative integer argument +count+ given,
1465 * returns a new array containing the trailing +count+ elements of +self+, as available:
1467 * a = [:foo, 'bar', 2]
1468 * a.pop(2) # => ["bar", 2]
1469 * a # => [:foo]
1471 * a = [:foo, 'bar', 2]
1472 * a.pop(50) # => [:foo, "bar", 2]
1473 * a # => []
1475 * Related: Array#push;
1476 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1479 static VALUE
1480 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1482 VALUE result;
1484 if (argc == 0) {
1485 return rb_ary_pop(ary);
1488 rb_ary_modify_check(ary);
1489 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1490 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1491 ary_verify(ary);
1492 return result;
1495 VALUE
1496 rb_ary_shift(VALUE ary)
1498 VALUE top;
1499 long len = RARRAY_LEN(ary);
1501 if (len == 0) {
1502 rb_ary_modify_check(ary);
1503 return Qnil;
1506 top = RARRAY_AREF(ary, 0);
1508 rb_ary_behead(ary, 1);
1510 return top;
1514 * call-seq:
1515 * array.shift -> object or nil
1516 * array.shift(n) -> new_array
1518 * Removes and returns leading elements.
1520 * When no argument is given, removes and returns the first element:
1522 * a = [:foo, 'bar', 2]
1523 * a.shift # => :foo
1524 * a # => ['bar', 2]
1526 * Returns +nil+ if +self+ is empty.
1528 * When positive Integer argument +n+ is given, removes the first +n+ elements;
1529 * returns those elements in a new +Array+:
1531 * a = [:foo, 'bar', 2]
1532 * a.shift(2) # => [:foo, 'bar']
1533 * a # => [2]
1535 * If +n+ is as large as or larger than <tt>self.length</tt>,
1536 * removes all elements; returns those elements in a new +Array+:
1538 * a = [:foo, 'bar', 2]
1539 * a.shift(3) # => [:foo, 'bar', 2]
1541 * If +n+ is zero, returns a new empty +Array+; +self+ is unmodified.
1543 * Related: #push, #pop, #unshift.
1546 static VALUE
1547 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1549 VALUE result;
1550 long n;
1552 if (argc == 0) {
1553 return rb_ary_shift(ary);
1556 rb_ary_modify_check(ary);
1557 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1558 n = RARRAY_LEN(result);
1559 rb_ary_behead(ary,n);
1561 return result;
1564 VALUE
1565 rb_ary_behead(VALUE ary, long n)
1567 if (n <= 0) {
1568 return ary;
1571 rb_ary_modify_check(ary);
1573 if (!ARY_SHARED_P(ary)) {
1574 if (ARY_EMBED_P(ary) || RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
1575 RARRAY_PTR_USE(ary, ptr, {
1576 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary) - n);
1577 }); /* WB: no new reference */
1578 ARY_INCREASE_LEN(ary, -n);
1579 ary_verify(ary);
1580 return ary;
1583 ary_mem_clear(ary, 0, n);
1584 ary_make_shared(ary);
1586 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1587 ary_mem_clear(ary, 0, n);
1590 ARY_INCREASE_PTR(ary, n);
1591 ARY_INCREASE_LEN(ary, -n);
1592 ary_verify(ary);
1594 return ary;
1597 static VALUE
1598 make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
1600 if (head - sharedp < argc) {
1601 long room = capa - len - argc;
1603 room -= room >> 4;
1604 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1605 head = sharedp + argc + room;
1607 ARY_SET_PTR(ary, head - argc);
1608 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1610 ary_verify(ary);
1611 return ARY_SHARED_ROOT(ary);
1614 static VALUE
1615 ary_modify_for_unshift(VALUE ary, int argc)
1617 long len = RARRAY_LEN(ary);
1618 long new_len = len + argc;
1619 long capa;
1620 const VALUE *head, *sharedp;
1622 rb_ary_modify(ary);
1623 capa = ARY_CAPA(ary);
1624 if (capa - (capa >> 6) <= new_len) {
1625 ary_double_capa(ary, new_len);
1628 /* use shared array for big "queues" */
1629 if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
1630 ary_verify(ary);
1632 /* make a room for unshifted items */
1633 capa = ARY_CAPA(ary);
1634 ary_make_shared(ary);
1636 head = sharedp = RARRAY_CONST_PTR(ary);
1637 return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
1639 else {
1640 /* sliding items */
1641 RARRAY_PTR_USE(ary, ptr, {
1642 MEMMOVE(ptr + argc, ptr, VALUE, len);
1645 ary_verify(ary);
1646 return ary;
1650 static VALUE
1651 ary_ensure_room_for_unshift(VALUE ary, int argc)
1653 long len = RARRAY_LEN(ary);
1654 long new_len = len + argc;
1656 if (len > ARY_MAX_SIZE - argc) {
1657 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1659 else if (! ARY_SHARED_P(ary)) {
1660 return ary_modify_for_unshift(ary, argc);
1662 else {
1663 VALUE shared_root = ARY_SHARED_ROOT(ary);
1664 long capa = RARRAY_LEN(shared_root);
1666 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1667 return ary_modify_for_unshift(ary, argc);
1669 else if (new_len > capa) {
1670 return ary_modify_for_unshift(ary, argc);
1672 else {
1673 const VALUE * head = RARRAY_CONST_PTR(ary);
1674 void *sharedp = (void *)RARRAY_CONST_PTR(shared_root);
1676 rb_ary_modify_check(ary);
1677 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1683 * call-seq:
1684 * unshift(*objects) -> self
1685 * prepend(*objects) -> self
1687 * Prepends the given +objects+ to +self+:
1689 * a = [:foo, 'bar', 2]
1690 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1692 * Related: Array#shift;
1693 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1696 VALUE
1697 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1699 long len = RARRAY_LEN(ary);
1700 VALUE target_ary;
1702 if (argc == 0) {
1703 rb_ary_modify_check(ary);
1704 return ary;
1707 target_ary = ary_ensure_room_for_unshift(ary, argc);
1708 ary_memcpy0(ary, 0, argc, argv, target_ary);
1709 ARY_SET_LEN(ary, len + argc);
1710 return ary;
1713 VALUE
1714 rb_ary_unshift(VALUE ary, VALUE item)
1716 return rb_ary_unshift_m(1, &item, ary);
1719 /* faster version - use this if you don't need to treat negative offset */
1720 static inline VALUE
1721 rb_ary_elt(VALUE ary, long offset)
1723 long len = RARRAY_LEN(ary);
1724 if (len == 0) return Qnil;
1725 if (offset < 0 || len <= offset) {
1726 return Qnil;
1728 return RARRAY_AREF(ary, offset);
1731 VALUE
1732 rb_ary_entry(VALUE ary, long offset)
1734 return rb_ary_entry_internal(ary, offset);
1737 VALUE
1738 rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
1740 VALUE klass;
1741 long alen = RARRAY_LEN(ary);
1743 if (beg > alen) return Qnil;
1744 if (beg < 0 || len < 0) return Qnil;
1746 if (alen < len || alen < beg + len) {
1747 len = alen - beg;
1749 klass = rb_cArray;
1750 if (len == 0) return ary_new(klass, 0);
1751 if (step == 0)
1752 rb_raise(rb_eArgError, "slice step cannot be zero");
1753 if (step == 1)
1754 return ary_make_partial(ary, klass, beg, len);
1755 else
1756 return ary_make_partial_step(ary, klass, beg, len, step);
1759 VALUE
1760 rb_ary_subseq(VALUE ary, long beg, long len)
1762 return rb_ary_subseq_step(ary, beg, len, 1);
1765 static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1768 * call-seq:
1769 * self[index] -> object or nil
1770 * self[start, length] -> object or nil
1771 * self[range] -> object or nil
1772 * self[aseq] -> object or nil
1773 * slice(index) -> object or nil
1774 * slice(start, length) -> object or nil
1775 * slice(range) -> object or nil
1776 * slice(aseq) -> object or nil
1778 * Returns elements from +self+; does not modify +self+.
1780 * In brief:
1782 * a = [:foo, 'bar', 2]
1784 * # Single argument index: returns one element.
1785 * a[0] # => :foo # Zero-based index.
1786 * a[-1] # => 2 # Negative index counts backwards from end.
1788 * # Arguments start and length: returns an array.
1789 * a[1, 2] # => ["bar", 2]
1790 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1792 * # Single argument range: returns an array.
1793 * a[0..1] # => [:foo, "bar"]
1794 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1795 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1797 * When a single integer argument +index+ is given, returns the element at offset +index+:
1799 * a = [:foo, 'bar', 2]
1800 * a[0] # => :foo
1801 * a[2] # => 2
1802 * a # => [:foo, "bar", 2]
1804 * If +index+ is negative, counts backwards from the end of +self+:
1806 * a = [:foo, 'bar', 2]
1807 * a[-1] # => 2
1808 * a[-2] # => "bar"
1810 * If +index+ is out of range, returns +nil+.
1812 * When two Integer arguments +start+ and +length+ are given,
1813 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1815 * a = [:foo, 'bar', 2]
1816 * a[0, 2] # => [:foo, "bar"]
1817 * a[1, 2] # => ["bar", 2]
1819 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1820 * returns all elements from offset +start+ to the end:
1822 * a = [:foo, 'bar', 2]
1823 * a[0, 4] # => [:foo, "bar", 2]
1824 * a[1, 3] # => ["bar", 2]
1825 * a[2, 2] # => [2]
1827 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1828 * returns a new empty +Array+.
1830 * If +length+ is negative, returns +nil+.
1832 * When a single Range argument +range+ is given,
1833 * treats <tt>range.min</tt> as +start+ above
1834 * and <tt>range.size</tt> as +length+ above:
1836 * a = [:foo, 'bar', 2]
1837 * a[0..1] # => [:foo, "bar"]
1838 * a[1..2] # => ["bar", 2]
1840 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1842 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1844 * a = [:foo, 'bar', 2]
1845 * a[0..-1] # => [:foo, "bar", 2]
1846 * a[0..-2] # => [:foo, "bar"]
1847 * a[0..-3] # => [:foo]
1849 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1851 * a = [:foo, 'bar', 2]
1852 * a[-1..2] # => [2]
1853 * a[-2..2] # => ["bar", 2]
1854 * a[-3..2] # => [:foo, "bar", 2]
1856 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1858 * a = [:foo, 'bar', 2]
1859 * a[4..1] # => nil
1860 * a[4..0] # => nil
1861 * a[4..-1] # => nil
1863 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1864 * returns an +Array+ of elements corresponding to the indexes produced by
1865 * the sequence.
1867 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1868 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1870 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1871 * is larger than array size, throws RangeError.
1873 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1874 * a[(1..11).step(2)]
1875 * # RangeError (((1..11).step(2)) out of range)
1876 * a[(7..).step(2)]
1877 * # RangeError (((7..).step(2)) out of range)
1879 * If given a single argument, and its type is not one of the listed, tries to
1880 * convert it to Integer, and raises if it is impossible:
1882 * a = [:foo, 'bar', 2]
1883 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1884 * a[:foo]
1886 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1889 VALUE
1890 rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
1892 rb_check_arity(argc, 1, 2);
1893 if (argc == 2) {
1894 return rb_ary_aref2(ary, argv[0], argv[1]);
1896 return rb_ary_aref1(ary, argv[0]);
1899 static VALUE
1900 rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1902 long beg = NUM2LONG(b);
1903 long len = NUM2LONG(e);
1904 if (beg < 0) {
1905 beg += RARRAY_LEN(ary);
1907 return rb_ary_subseq(ary, beg, len);
1910 VALUE
1911 rb_ary_aref1(VALUE ary, VALUE arg)
1913 long beg, len, step;
1915 /* special case - speeding up */
1916 if (FIXNUM_P(arg)) {
1917 return rb_ary_entry(ary, FIX2LONG(arg));
1919 /* check if idx is Range or ArithmeticSequence */
1920 switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
1921 case Qfalse:
1922 break;
1923 case Qnil:
1924 return Qnil;
1925 default:
1926 return rb_ary_subseq_step(ary, beg, len, step);
1929 return rb_ary_entry(ary, NUM2LONG(arg));
1933 * call-seq:
1934 * at(index) -> object or nil
1936 * Returns the element of +self+ specified by the given +index+
1937 * or +nil+ if there is no such element;
1938 * +index+ must be an
1939 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1941 * For non-negative +index+, returns the element of +self+ at offset +index+:
1943 * a = [:foo, 'bar', 2]
1944 * a.at(0) # => :foo
1945 * a.at(2) # => 2
1946 * a.at(2.0) # => 2
1948 * For negative +index+, counts backwards from the end of +self+:
1950 * a.at(-2) # => "bar"
1952 * Related: Array#[];
1953 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1956 VALUE
1957 rb_ary_at(VALUE ary, VALUE pos)
1959 return rb_ary_entry(ary, NUM2LONG(pos));
1962 #if 0
1963 static VALUE
1964 rb_ary_first(int argc, VALUE *argv, VALUE ary)
1966 if (argc == 0) {
1967 if (RARRAY_LEN(ary) == 0) return Qnil;
1968 return RARRAY_AREF(ary, 0);
1970 else {
1971 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1974 #endif
1976 static VALUE
1977 ary_first(VALUE self)
1979 return (RARRAY_LEN(self) == 0) ? Qnil : RARRAY_AREF(self, 0);
1982 static VALUE
1983 ary_last(VALUE self)
1985 long len = RARRAY_LEN(self);
1986 return (len == 0) ? Qnil : RARRAY_AREF(self, len-1);
1989 VALUE
1990 rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
1992 if (argc == 0) {
1993 return ary_last(ary);
1995 else {
1996 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
2001 * call-seq:
2002 * fetch(index) -> element
2003 * fetch(index, default_value) -> element or default_value
2004 * fetch(index) {|index| ... } -> element or block_return_value
2006 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2007 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2009 * With the single argument +index+ and no block,
2010 * returns the element at offset +index+:
2012 * a = [:foo, 'bar', 2]
2013 * a.fetch(1) # => "bar"
2014 * a.fetch(1.1) # => "bar"
2016 * If +index+ is negative, counts from the end of the array:
2018 * a = [:foo, 'bar', 2]
2019 * a.fetch(-1) # => 2
2020 * a.fetch(-2) # => "bar"
2022 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2023 * returns +default_value+ if +index+ is out-of-range:
2025 * a = [:foo, 'bar', 2]
2026 * a.fetch(1, nil) # => "bar"
2027 * a.fetch(3, :foo) # => :foo
2029 * With argument +index+ and a block,
2030 * returns the element at offset +index+ if index is in range
2031 * (and the block is not called); otherwise calls the block with index and returns its return value:
2033 * a = [:foo, 'bar', 2]
2034 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2035 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2037 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2040 static VALUE
2041 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
2043 VALUE pos, ifnone;
2044 long block_given;
2045 long idx;
2047 rb_scan_args(argc, argv, "11", &pos, &ifnone);
2048 block_given = rb_block_given_p();
2049 if (block_given && argc == 2) {
2050 rb_warn("block supersedes default value argument");
2052 idx = NUM2LONG(pos);
2054 if (idx < 0) {
2055 idx += RARRAY_LEN(ary);
2057 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
2058 if (block_given) return rb_yield(pos);
2059 if (argc == 1) {
2060 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
2061 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
2063 return ifnone;
2065 return RARRAY_AREF(ary, idx);
2069 * call-seq:
2070 * find_index(object) -> integer or nil
2071 * find_index {|element| ... } -> integer or nil
2072 * find_index -> new_enumerator
2073 * index(object) -> integer or nil
2074 * index {|element| ... } -> integer or nil
2075 * index -> new_enumerator
2077 * Returns the zero-based integer index of a specified element, or +nil+.
2079 * With only argument +object+ given,
2080 * returns the index of the first element +element+
2081 * for which <tt>object == element</tt>:
2083 * a = [:foo, 'bar', 2, 'bar']
2084 * a.index('bar') # => 1
2086 * Returns +nil+ if no such element found.
2088 * With only a block given,
2089 * calls the block with each successive element;
2090 * returns the index of the first element for which the block returns a truthy value:
2092 * a = [:foo, 'bar', 2, 'bar']
2093 * a.index {|element| element == 'bar' } # => 1
2095 * Returns +nil+ if the block never returns a truthy value.
2097 * With neither an argument nor a block given, returns a new Enumerator.
2099 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2102 static VALUE
2103 rb_ary_index(int argc, VALUE *argv, VALUE ary)
2105 VALUE val;
2106 long i;
2108 if (argc == 0) {
2109 RETURN_ENUMERATOR(ary, 0, 0);
2110 for (i=0; i<RARRAY_LEN(ary); i++) {
2111 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2112 return LONG2NUM(i);
2115 return Qnil;
2117 rb_check_arity(argc, 0, 1);
2118 val = argv[0];
2119 if (rb_block_given_p())
2120 rb_warn("given block not used");
2121 for (i=0; i<RARRAY_LEN(ary); i++) {
2122 VALUE e = RARRAY_AREF(ary, i);
2123 if (rb_equal(e, val)) {
2124 return LONG2NUM(i);
2127 return Qnil;
2131 * call-seq:
2132 * rindex(object) -> integer or nil
2133 * rindex {|element| ... } -> integer or nil
2134 * rindex -> new_enumerator
2136 * Returns the index of the last element for which <tt>object == element</tt>.
2138 * With argument +object+ given, returns the index of the last such element found:
2140 * a = [:foo, 'bar', 2, 'bar']
2141 * a.rindex('bar') # => 3
2143 * Returns +nil+ if no such object found.
2145 * With a block given, calls the block with each successive element;
2146 * returns the index of the last element for which the block returns a truthy value:
2148 * a = [:foo, 'bar', 2, 'bar']
2149 * a.rindex {|element| element == 'bar' } # => 3
2151 * Returns +nil+ if the block never returns a truthy value.
2153 * When neither an argument nor a block is given, returns a new Enumerator.
2155 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2158 static VALUE
2159 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
2161 VALUE val;
2162 long i = RARRAY_LEN(ary), len;
2164 if (argc == 0) {
2165 RETURN_ENUMERATOR(ary, 0, 0);
2166 while (i--) {
2167 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
2168 return LONG2NUM(i);
2169 if (i > (len = RARRAY_LEN(ary))) {
2170 i = len;
2173 return Qnil;
2175 rb_check_arity(argc, 0, 1);
2176 val = argv[0];
2177 if (rb_block_given_p())
2178 rb_warn("given block not used");
2179 while (i--) {
2180 VALUE e = RARRAY_AREF(ary, i);
2181 if (rb_equal(e, val)) {
2182 return LONG2NUM(i);
2184 if (i > RARRAY_LEN(ary)) {
2185 break;
2188 return Qnil;
2191 VALUE
2192 rb_ary_to_ary(VALUE obj)
2194 VALUE tmp = rb_check_array_type(obj);
2196 if (!NIL_P(tmp)) return tmp;
2197 return rb_ary_new3(1, obj);
2200 static void
2201 rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
2203 long olen;
2204 long rofs;
2206 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2207 olen = RARRAY_LEN(ary);
2208 if (beg < 0) {
2209 beg += olen;
2210 if (beg < 0) {
2211 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2212 beg - olen, -olen);
2215 if (olen < len || olen < beg + len) {
2216 len = olen - beg;
2220 const VALUE *optr = RARRAY_CONST_PTR(ary);
2221 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2224 if (beg >= olen) {
2225 VALUE target_ary;
2226 if (beg > ARY_MAX_SIZE - rlen) {
2227 rb_raise(rb_eIndexError, "index %ld too big", beg);
2229 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2230 len = beg + rlen;
2231 ary_mem_clear(ary, olen, beg - olen);
2232 if (rlen > 0) {
2233 if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
2234 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2236 ARY_SET_LEN(ary, len);
2238 else {
2239 long alen;
2241 if (olen - len > ARY_MAX_SIZE - rlen) {
2242 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2244 rb_ary_modify(ary);
2245 alen = olen + rlen - len;
2246 if (alen >= ARY_CAPA(ary)) {
2247 ary_double_capa(ary, alen);
2250 if (len != rlen) {
2251 RARRAY_PTR_USE(ary, ptr,
2252 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2253 VALUE, olen - (beg + len)));
2254 ARY_SET_LEN(ary, alen);
2256 if (rlen > 0) {
2257 if (rofs == -1) {
2258 rb_gc_writebarrier_remember(ary);
2260 else {
2261 /* In this case, we're copying from a region in this array, so
2262 * we don't need to fire the write barrier. */
2263 rptr = RARRAY_CONST_PTR(ary) + rofs;
2266 /* do not use RARRAY_PTR() because it can causes GC.
2267 * ary can contain T_NONE object because it is not cleared.
2269 RARRAY_PTR_USE(ary, ptr,
2270 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2275 void
2276 rb_ary_set_len(VALUE ary, long len)
2278 long capa;
2280 rb_ary_modify_check(ary);
2281 if (ARY_SHARED_P(ary)) {
2282 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2284 if (len > (capa = (long)ARY_CAPA(ary))) {
2285 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2287 ARY_SET_LEN(ary, len);
2290 VALUE
2291 rb_ary_resize(VALUE ary, long len)
2293 long olen;
2295 rb_ary_modify(ary);
2296 olen = RARRAY_LEN(ary);
2297 if (len == olen) return ary;
2298 if (len > ARY_MAX_SIZE) {
2299 rb_raise(rb_eIndexError, "index %ld too big", len);
2301 if (len > olen) {
2302 if (len >= ARY_CAPA(ary)) {
2303 ary_double_capa(ary, len);
2305 ary_mem_clear(ary, olen, len - olen);
2306 ARY_SET_LEN(ary, len);
2308 else if (ARY_EMBED_P(ary)) {
2309 ARY_SET_EMBED_LEN(ary, len);
2311 else if (len <= ary_embed_capa(ary)) {
2312 const VALUE *ptr = ARY_HEAP_PTR(ary);
2313 long ptr_capa = ARY_HEAP_SIZE(ary);
2314 bool is_malloc_ptr = !ARY_SHARED_P(ary);
2316 FL_SET_EMBED(ary);
2318 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
2319 ARY_SET_EMBED_LEN(ary, len);
2321 if (is_malloc_ptr) ruby_sized_xfree((void *)ptr, ptr_capa);
2323 else {
2324 if (olen > len + ARY_DEFAULT_SIZE) {
2325 size_t new_capa = ary_heap_realloc(ary, len);
2326 ARY_SET_CAPA(ary, new_capa);
2328 ARY_SET_HEAP_LEN(ary, len);
2330 ary_verify(ary);
2331 return ary;
2334 static VALUE
2335 ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2337 rb_ary_store(ary, key, val);
2338 return val;
2341 static VALUE
2342 ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2344 VALUE rpl = rb_ary_to_ary(val);
2345 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl));
2346 RB_GC_GUARD(rpl);
2347 return val;
2351 * call-seq:
2352 * self[index] = object -> object
2353 * self[start, length] = object -> object
2354 * self[range] = object -> object
2356 * Assigns elements in +self+, based on the given +object+; returns +object+.
2358 * In brief:
2360 * a_orig = [:foo, 'bar', 2]
2362 * # With argument index.
2363 * a = a_orig.dup
2364 * a[0] = 'foo' # => "foo"
2365 * a # => ["foo", "bar", 2]
2366 * a = a_orig.dup
2367 * a[7] = 'foo' # => "foo"
2368 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2370 * # With arguments start and length.
2371 * a = a_orig.dup
2372 * a[0, 2] = 'foo' # => "foo"
2373 * a # => ["foo", 2]
2374 * a = a_orig.dup
2375 * a[6, 50] = 'foo' # => "foo"
2376 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2378 * # With argument range.
2379 * a = a_orig.dup
2380 * a[0..1] = 'foo' # => "foo"
2381 * a # => ["foo", 2]
2382 * a = a_orig.dup
2383 * a[6..50] = 'foo' # => "foo"
2384 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2386 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2388 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2390 * a = [:foo, 'bar', 2]
2391 * a[0] = 'foo' # => "foo"
2392 * a # => ["foo", "bar", 2]
2394 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2396 * a = [:foo, 'bar', 2]
2397 * a[7] = 'foo' # => "foo"
2398 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2400 * If +index+ is negative, counts backwards from the end of the array:
2402 * a = [:foo, 'bar', 2]
2403 * a[-1] = 'two' # => "two"
2404 * a # => [:foo, "bar", "two"]
2406 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2407 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2408 * and assigns +object+ at offset +start+:
2410 * a = [:foo, 'bar', 2]
2411 * a[0, 2] = 'foo' # => "foo"
2412 * a # => ["foo", 2]
2414 * If +start+ is negative, counts backwards from the end of the array:
2416 * a = [:foo, 'bar', 2]
2417 * a[-2, 2] = 'foo' # => "foo"
2418 * a # => [:foo, "foo"]
2420 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2421 * extends the array with +nil+, assigns +object+ at offset +start+,
2422 * and ignores +length+:
2424 * a = [:foo, 'bar', 2]
2425 * a[6, 50] = 'foo' # => "foo"
2426 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2428 * If +length+ is zero, shifts elements at and following offset +start+
2429 * and assigns +object+ at offset +start+:
2431 * a = [:foo, 'bar', 2]
2432 * a[1, 0] = 'foo' # => "foo"
2433 * a # => [:foo, "foo", "bar", 2]
2435 * If +length+ is too large for the existing array, does not extend the array:
2437 * a = [:foo, 'bar', 2]
2438 * a[1, 5] = 'foo' # => "foo"
2439 * a # => [:foo, "foo"]
2441 * When Range argument +range+ is given and +object+ is not an +Array+,
2442 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2443 * and assigns +object+ at offset +start+:
2445 * a = [:foo, 'bar', 2]
2446 * a[0..1] = 'foo' # => "foo"
2447 * a # => ["foo", 2]
2449 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2451 * a = [:foo, 'bar', 2]
2452 * a[-2..2] = 'foo' # => "foo"
2453 * a # => [:foo, "foo"]
2455 * If the array length is less than <tt>range.begin</tt>,
2456 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2457 * and ignores +length+:
2459 * a = [:foo, 'bar', 2]
2460 * a[6..50] = 'foo' # => "foo"
2461 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2463 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2464 * and assigns +object+ at offset +start+:
2466 * a = [:foo, 'bar', 2]
2467 * a[1..0] = 'foo' # => "foo"
2468 * a # => [:foo, "foo", "bar", 2]
2470 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2471 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2473 * a = [:foo, 'bar', 2]
2474 * a[1..-1] = 'foo' # => "foo"
2475 * a # => [:foo, "foo"]
2476 * a = [:foo, 'bar', 2]
2477 * a[1..-2] = 'foo' # => "foo"
2478 * a # => [:foo, "foo", 2]
2479 * a = [:foo, 'bar', 2]
2480 * a[1..-3] = 'foo' # => "foo"
2481 * a # => [:foo, "foo", "bar", 2]
2482 * a = [:foo, 'bar', 2]
2484 * If <tt>range.end</tt> is too large for the existing array,
2485 * replaces array elements, but does not extend the array with +nil+ values:
2487 * a = [:foo, 'bar', 2]
2488 * a[1..5] = 'foo' # => "foo"
2489 * a # => [:foo, "foo"]
2491 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2494 static VALUE
2495 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2497 long offset, beg, len;
2499 rb_check_arity(argc, 2, 3);
2500 rb_ary_modify_check(ary);
2501 if (argc == 3) {
2502 beg = NUM2LONG(argv[0]);
2503 len = NUM2LONG(argv[1]);
2504 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2506 if (FIXNUM_P(argv[0])) {
2507 offset = FIX2LONG(argv[0]);
2508 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2510 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2511 /* check if idx is Range */
2512 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2515 offset = NUM2LONG(argv[0]);
2516 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2520 * call-seq:
2521 * insert(index, *objects) -> self
2523 * Inserts the given +objects+ as elements of +self+;
2524 * returns +self+.
2526 * When +index+ is non-negative, inserts +objects+
2527 * _before_ the element at offset +index+:
2529 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2530 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2532 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2534 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2535 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2537 * When +index+ is negative, inserts +objects+
2538 * _after_ the element at offset <tt>index + self.size</tt>:
2540 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2541 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2543 * With no +objects+ given, does nothing:
2545 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2546 * a.insert(1) # => ["a", "b", "c"]
2547 * a.insert(50) # => ["a", "b", "c"]
2548 * a.insert(-50) # => ["a", "b", "c"]
2550 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2552 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2555 static VALUE
2556 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2558 long pos;
2560 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
2561 rb_ary_modify_check(ary);
2562 pos = NUM2LONG(argv[0]);
2563 if (argc == 1) return ary;
2564 if (pos == -1) {
2565 pos = RARRAY_LEN(ary);
2567 else if (pos < 0) {
2568 long minpos = -RARRAY_LEN(ary) - 1;
2569 if (pos < minpos) {
2570 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2571 pos, minpos);
2573 pos++;
2575 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2576 return ary;
2579 static VALUE
2580 rb_ary_length(VALUE ary);
2582 static VALUE
2583 ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2585 return rb_ary_length(ary);
2588 // Primitive to avoid a race condition in Array#each.
2589 // Return `true` and write `value` and `index` if the element exists.
2590 static VALUE
2591 ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
2593 long i = NUM2LONG(*index);
2594 if (i >= RARRAY_LEN(self)) {
2595 return Qfalse;
2597 *value = RARRAY_AREF(self, i);
2598 *index = LONG2NUM(i + 1);
2599 return Qtrue;
2602 VALUE
2603 rb_ary_each(VALUE ary)
2605 long i;
2606 ary_verify(ary);
2607 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2608 for (i=0; i<RARRAY_LEN(ary); i++) {
2609 rb_yield(RARRAY_AREF(ary, i));
2611 return ary;
2615 * call-seq:
2616 * each_index {|index| ... } -> self
2617 * each_index -> new_enumerator
2619 * With a block given, iterates over the elements of +self+,
2620 * passing each <i>array index</i> to the block;
2621 * returns +self+:
2623 * a = [:foo, 'bar', 2]
2624 * a.each_index {|index| puts "#{index} #{a[index]}" }
2626 * Output:
2628 * 0 foo
2629 * 1 bar
2630 * 2 2
2632 * Allows the array to be modified during iteration:
2634 * a = [:foo, 'bar', 2]
2635 * a.each_index {|index| puts index; a.clear if index > 0 }
2637 * Output:
2642 * With no block given, returns a new Enumerator.
2644 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2647 static VALUE
2648 rb_ary_each_index(VALUE ary)
2650 long i;
2651 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2653 for (i=0; i<RARRAY_LEN(ary); i++) {
2654 rb_yield(LONG2NUM(i));
2656 return ary;
2660 * call-seq:
2661 * array.reverse_each {|element| ... } -> self
2662 * array.reverse_each -> Enumerator
2664 * Iterates backwards over array elements.
2666 * When a block given, passes, in reverse order, each element to the block;
2667 * returns +self+:
2669 * a = [:foo, 'bar', 2]
2670 * a.reverse_each {|element| puts "#{element.class} #{element}" }
2672 * Output:
2674 * Integer 2
2675 * String bar
2676 * Symbol foo
2678 * Allows the array to be modified during iteration:
2680 * a = [:foo, 'bar', 2]
2681 * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2683 * Output:
2686 * bar
2688 * When no block given, returns a new Enumerator:
2690 * a = [:foo, 'bar', 2]
2691 * e = a.reverse_each
2692 * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
2693 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2695 * Output:
2697 * Integer 2
2698 * String bar
2699 * Symbol foo
2701 * Related: #each, #each_index.
2704 static VALUE
2705 rb_ary_reverse_each(VALUE ary)
2707 long len;
2709 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2710 len = RARRAY_LEN(ary);
2711 while (len--) {
2712 long nlen;
2713 rb_yield(RARRAY_AREF(ary, len));
2714 nlen = RARRAY_LEN(ary);
2715 if (nlen < len) {
2716 len = nlen;
2719 return ary;
2723 * call-seq:
2724 * length -> integer
2725 * size -> integer
2727 * Returns the count of elements in +self+:
2729 * [0, 1, 2].length # => 3
2730 * [].length # => 0
2732 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2735 static VALUE
2736 rb_ary_length(VALUE ary)
2738 long len = RARRAY_LEN(ary);
2739 return LONG2NUM(len);
2743 * call-seq:
2744 * array.empty? -> true or false
2746 * Returns +true+ if the count of elements in +self+ is zero,
2747 * +false+ otherwise.
2749 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2752 static VALUE
2753 rb_ary_empty_p(VALUE ary)
2755 return RBOOL(RARRAY_LEN(ary) == 0);
2758 VALUE
2759 rb_ary_dup(VALUE ary)
2761 long len = RARRAY_LEN(ary);
2762 VALUE dup = rb_ary_new2(len);
2763 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2764 ARY_SET_LEN(dup, len);
2766 ary_verify(ary);
2767 ary_verify(dup);
2768 return dup;
2771 VALUE
2772 rb_ary_resurrect(VALUE ary)
2774 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2777 extern VALUE rb_output_fs;
2779 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2781 static VALUE
2782 recursive_join(VALUE obj, VALUE argp, int recur)
2784 VALUE *arg = (VALUE *)argp;
2785 VALUE ary = arg[0];
2786 VALUE sep = arg[1];
2787 VALUE result = arg[2];
2788 int *first = (int *)arg[3];
2790 if (recur) {
2791 rb_raise(rb_eArgError, "recursive array join");
2793 else {
2794 ary_join_1(obj, ary, sep, 0, result, first);
2796 return Qnil;
2799 static long
2800 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2802 long i;
2803 VALUE val;
2805 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2806 for (i=0; i<max; i++) {
2807 val = RARRAY_AREF(ary, i);
2808 if (!RB_TYPE_P(val, T_STRING)) break;
2809 if (i > 0 && !NIL_P(sep))
2810 rb_str_buf_append(result, sep);
2811 rb_str_buf_append(result, val);
2813 return i;
2816 static void
2817 ary_join_1_str(VALUE dst, VALUE src, int *first)
2819 rb_str_buf_append(dst, src);
2820 if (*first) {
2821 rb_enc_copy(dst, src);
2822 *first = FALSE;
2826 static void
2827 ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
2829 if (val == ary) {
2830 rb_raise(rb_eArgError, "recursive array join");
2832 else {
2833 VALUE args[4];
2835 *first = FALSE;
2836 args[0] = val;
2837 args[1] = sep;
2838 args[2] = result;
2839 args[3] = (VALUE)first;
2840 rb_exec_recursive(recursive_join, obj, (VALUE)args);
2844 static void
2845 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
2847 VALUE val, tmp;
2849 for (; i<RARRAY_LEN(ary); i++) {
2850 if (i > 0 && !NIL_P(sep))
2851 rb_str_buf_append(result, sep);
2853 val = RARRAY_AREF(ary, i);
2854 if (RB_TYPE_P(val, T_STRING)) {
2855 ary_join_1_str(result, val, first);
2857 else if (RB_TYPE_P(val, T_ARRAY)) {
2858 ary_join_1_ary(val, ary, sep, result, val, first);
2860 else if (!NIL_P(tmp = rb_check_string_type(val))) {
2861 ary_join_1_str(result, tmp, first);
2863 else if (!NIL_P(tmp = rb_check_array_type(val))) {
2864 ary_join_1_ary(val, ary, sep, result, tmp, first);
2866 else {
2867 ary_join_1_str(result, rb_obj_as_string(val), first);
2872 VALUE
2873 rb_ary_join(VALUE ary, VALUE sep)
2875 long len = 1, i;
2876 VALUE val, tmp, result;
2878 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
2880 if (!NIL_P(sep)) {
2881 StringValue(sep);
2882 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
2884 for (i=0; i<RARRAY_LEN(ary); i++) {
2885 val = RARRAY_AREF(ary, i);
2886 tmp = rb_check_string_type(val);
2888 if (NIL_P(tmp) || tmp != val) {
2889 int first;
2890 long n = RARRAY_LEN(ary);
2891 if (i > n) i = n;
2892 result = rb_str_buf_new(len + (n-i)*10);
2893 rb_enc_associate(result, rb_usascii_encoding());
2894 i = ary_join_0(ary, sep, i, result);
2895 first = i == 0;
2896 ary_join_1(ary, ary, sep, i, result, &first);
2897 return result;
2900 len += RSTRING_LEN(tmp);
2903 result = rb_str_new(0, len);
2904 rb_str_set_len(result, 0);
2906 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
2908 return result;
2912 * call-seq:
2913 * array.join(separator = $,) -> new_string
2915 * Returns the new string formed by joining the converted elements of +self+;
2916 * for each element +element+:
2918 * - Converts recursively using <tt>element.join(separator)</tt>
2919 * if +element+ is a <tt>kind_of?(Array)</tt>.
2920 * - Otherwise, converts using <tt>element.to_s</tt>.
2922 * With no argument given, joins using the output field separator, <tt>$,</tt>:
2924 * a = [:foo, 'bar', 2]
2925 * $, # => nil
2926 * a.join # => "foobar2"
2928 * With string argument +separator+ given, joins using that separator:
2930 * a = [:foo, 'bar', 2]
2931 * a.join("\n") # => "foo\nbar\n2"
2933 * Joins recursively for nested arrays:
2935 * a = [:foo, [:bar, [:baz, :bat]]]
2936 * a.join # => "foobarbazbat"
2938 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2940 static VALUE
2941 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
2943 VALUE sep;
2945 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
2946 sep = rb_output_fs;
2947 if (!NIL_P(sep)) {
2948 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
2952 return rb_ary_join(ary, sep);
2955 static VALUE
2956 inspect_ary(VALUE ary, VALUE dummy, int recur)
2958 long i;
2959 VALUE s, str;
2961 if (recur) return rb_usascii_str_new_cstr("[...]");
2962 str = rb_str_buf_new2("[");
2963 for (i=0; i<RARRAY_LEN(ary); i++) {
2964 s = rb_inspect(RARRAY_AREF(ary, i));
2965 if (i > 0) rb_str_buf_cat2(str, ", ");
2966 else rb_enc_copy(str, s);
2967 rb_str_buf_append(str, s);
2969 rb_str_buf_cat2(str, "]");
2970 return str;
2974 * call-seq:
2975 * inspect -> new_string
2977 * Returns the new string formed by calling method <tt>#inspect</tt>
2978 * on each array element:
2980 * a = [:foo, 'bar', 2]
2981 * a.inspect # => "[:foo, \"bar\", 2]"
2983 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2986 static VALUE
2987 rb_ary_inspect(VALUE ary)
2989 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
2990 return rb_exec_recursive(inspect_ary, ary, 0);
2993 VALUE
2994 rb_ary_to_s(VALUE ary)
2996 return rb_ary_inspect(ary);
3000 * call-seq:
3001 * to_a -> self or new_array
3003 * When +self+ is an instance of +Array+, returns +self+:
3005 * a = [:foo, 'bar', 2]
3006 * a.to_a # => [:foo, "bar", 2]
3008 * Otherwise, returns a new +Array+ containing the elements of +self+:
3010 * class MyArray < Array; end
3011 * a = MyArray.new(['foo', 'bar', 'two'])
3012 * a.instance_of?(Array) # => false
3013 * a.kind_of?(Array) # => true
3014 * a1 = a.to_a
3015 * a1 # => ["foo", "bar", "two"]
3016 * a1.class # => Array # Not MyArray
3020 static VALUE
3021 rb_ary_to_a(VALUE ary)
3023 if (rb_obj_class(ary) != rb_cArray) {
3024 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
3025 rb_ary_replace(dup, ary);
3026 return dup;
3028 return ary;
3032 * call-seq:
3033 * array.to_h -> new_hash
3034 * array.to_h {|item| ... } -> new_hash
3036 * Returns a new Hash formed from +self+.
3038 * When a block is given, calls the block with each array element;
3039 * the block must return a 2-element +Array+ whose two elements
3040 * form a key-value pair in the returned Hash:
3042 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3043 * h = a.to_h {|item| [item, item] }
3044 * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
3046 * When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
3047 * each sub-array is formed into a key-value pair in the new Hash:
3049 * [].to_h # => {}
3050 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3051 * h = a.to_h
3052 * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3056 static VALUE
3057 rb_ary_to_h(VALUE ary)
3059 long i;
3060 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
3061 int block_given = rb_block_given_p();
3063 for (i=0; i<RARRAY_LEN(ary); i++) {
3064 const VALUE e = rb_ary_elt(ary, i);
3065 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3066 const VALUE key_value_pair = rb_check_array_type(elt);
3067 if (NIL_P(key_value_pair)) {
3068 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
3069 rb_obj_class(elt), i);
3071 if (RARRAY_LEN(key_value_pair) != 2) {
3072 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
3073 i, RARRAY_LEN(key_value_pair));
3075 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3077 return hash;
3081 * call-seq:
3082 * array.to_ary -> self
3084 * Returns +self+.
3087 static VALUE
3088 rb_ary_to_ary_m(VALUE ary)
3090 return ary;
3093 static void
3094 ary_reverse(VALUE *p1, VALUE *p2)
3096 while (p1 < p2) {
3097 VALUE tmp = *p1;
3098 *p1++ = *p2;
3099 *p2-- = tmp;
3103 VALUE
3104 rb_ary_reverse(VALUE ary)
3106 VALUE *p2;
3107 long len = RARRAY_LEN(ary);
3109 rb_ary_modify(ary);
3110 if (len > 1) {
3111 RARRAY_PTR_USE(ary, p1, {
3112 p2 = p1 + len - 1; /* points last item */
3113 ary_reverse(p1, p2);
3114 }); /* WB: no new reference */
3116 return ary;
3120 * call-seq:
3121 * reverse! -> self
3123 * Reverses the order of the elements of +self+;
3124 * returns +self+:
3126 * a = [0, 1, 2]
3127 * a.reverse! # => [2, 1, 0]
3128 * a # => [2, 1, 0]
3130 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3133 static VALUE
3134 rb_ary_reverse_bang(VALUE ary)
3136 return rb_ary_reverse(ary);
3140 * call-seq:
3141 * reverse -> new_array
3143 * Returns a new array containing the elements of +self+ in reverse order:
3145 * [0, 1, 2].reverse # => [2, 1, 0]
3147 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3150 static VALUE
3151 rb_ary_reverse_m(VALUE ary)
3153 long len = RARRAY_LEN(ary);
3154 VALUE dup = rb_ary_new2(len);
3156 if (len > 0) {
3157 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3158 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3159 do *p2-- = *p1++; while (--len > 0);
3161 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3162 return dup;
3165 static inline long
3166 rotate_count(long cnt, long len)
3168 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3171 static void
3172 ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3174 if (cnt == 1) {
3175 VALUE tmp = *ptr;
3176 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3177 *(ptr + len - 1) = tmp;
3179 else if (cnt == len - 1) {
3180 VALUE tmp = *(ptr + len - 1);
3181 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3182 *ptr = tmp;
3184 else {
3185 --len;
3186 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3187 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3188 if (len > 0) ary_reverse(ptr, ptr + len);
3192 VALUE
3193 rb_ary_rotate(VALUE ary, long cnt)
3195 rb_ary_modify(ary);
3197 if (cnt != 0) {
3198 long len = RARRAY_LEN(ary);
3199 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3200 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3201 return ary;
3204 return Qnil;
3208 * call-seq:
3209 * array.rotate! -> self
3210 * array.rotate!(count) -> self
3212 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3214 * When no argument given, rotates the first element to the last position:
3216 * a = [:foo, 'bar', 2, 'bar']
3217 * a.rotate! # => ["bar", 2, "bar", :foo]
3219 * When given a non-negative Integer +count+,
3220 * rotates +count+ elements from the beginning to the end:
3222 * a = [:foo, 'bar', 2]
3223 * a.rotate!(2)
3224 * a # => [2, :foo, "bar"]
3226 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3228 * a = [:foo, 'bar', 2]
3229 * a.rotate!(20)
3230 * a # => [2, :foo, "bar"]
3232 * If +count+ is zero, returns +self+ unmodified:
3234 * a = [:foo, 'bar', 2]
3235 * a.rotate!(0)
3236 * a # => [:foo, "bar", 2]
3238 * When given a negative Integer +count+, rotates in the opposite direction,
3239 * from end to beginning:
3241 * a = [:foo, 'bar', 2]
3242 * a.rotate!(-2)
3243 * a # => ["bar", 2, :foo]
3245 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3247 * a = [:foo, 'bar', 2]
3248 * a.rotate!(-5)
3249 * a # => ["bar", 2, :foo]
3253 static VALUE
3254 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3256 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3257 rb_ary_rotate(ary, n);
3258 return ary;
3262 * call-seq:
3263 * array.rotate -> new_array
3264 * array.rotate(count) -> new_array
3266 * Returns a new +Array+ formed from +self+ with elements
3267 * rotated from one end to the other.
3269 * When no argument given, returns a new +Array+ that is like +self+,
3270 * except that the first element has been rotated to the last position:
3272 * a = [:foo, 'bar', 2, 'bar']
3273 * a1 = a.rotate
3274 * a1 # => ["bar", 2, "bar", :foo]
3276 * When given a non-negative Integer +count+,
3277 * returns a new +Array+ with +count+ elements rotated from the beginning to the end:
3279 * a = [:foo, 'bar', 2]
3280 * a1 = a.rotate(2)
3281 * a1 # => [2, :foo, "bar"]
3283 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3285 * a = [:foo, 'bar', 2]
3286 * a1 = a.rotate(20)
3287 * a1 # => [2, :foo, "bar"]
3289 * If +count+ is zero, returns a copy of +self+, unmodified:
3291 * a = [:foo, 'bar', 2]
3292 * a1 = a.rotate(0)
3293 * a1 # => [:foo, "bar", 2]
3295 * When given a negative Integer +count+, rotates in the opposite direction,
3296 * from end to beginning:
3298 * a = [:foo, 'bar', 2]
3299 * a1 = a.rotate(-2)
3300 * a1 # => ["bar", 2, :foo]
3302 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3304 * a = [:foo, 'bar', 2]
3305 * a1 = a.rotate(-5)
3306 * a1 # => ["bar", 2, :foo]
3310 static VALUE
3311 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3313 VALUE rotated;
3314 const VALUE *ptr;
3315 long len;
3316 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3318 len = RARRAY_LEN(ary);
3319 rotated = rb_ary_new2(len);
3320 if (len > 0) {
3321 cnt = rotate_count(cnt, len);
3322 ptr = RARRAY_CONST_PTR(ary);
3323 len -= cnt;
3324 ary_memcpy(rotated, 0, len, ptr + cnt);
3325 ary_memcpy(rotated, len, cnt, ptr);
3327 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3328 return rotated;
3331 struct ary_sort_data {
3332 VALUE ary;
3333 VALUE receiver;
3336 static VALUE
3337 sort_reentered(VALUE ary)
3339 if (RBASIC(ary)->klass) {
3340 rb_raise(rb_eRuntimeError, "sort reentered");
3342 return Qnil;
3345 static void
3346 sort_returned(struct ary_sort_data *data)
3348 if (rb_obj_frozen_p(data->receiver)) {
3349 rb_raise(rb_eFrozenError, "array frozen during sort");
3351 sort_reentered(data->ary);
3354 static int
3355 sort_1(const void *ap, const void *bp, void *dummy)
3357 struct ary_sort_data *data = dummy;
3358 VALUE retval = sort_reentered(data->ary);
3359 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3360 VALUE args[2];
3361 int n;
3363 args[0] = a;
3364 args[1] = b;
3365 retval = rb_yield_values2(2, args);
3366 n = rb_cmpint(retval, a, b);
3367 sort_returned(data);
3368 return n;
3371 static int
3372 sort_2(const void *ap, const void *bp, void *dummy)
3374 struct ary_sort_data *data = dummy;
3375 VALUE retval = sort_reentered(data->ary);
3376 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3377 int n;
3379 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3380 if ((long)a > (long)b) return 1;
3381 if ((long)a < (long)b) return -1;
3382 return 0;
3384 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3385 return rb_str_cmp(a, b);
3387 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3388 return rb_float_cmp(a, b);
3391 retval = rb_funcallv(a, id_cmp, 1, &b);
3392 n = rb_cmpint(retval, a, b);
3393 sort_returned(data);
3395 return n;
3399 * call-seq:
3400 * array.sort! -> self
3401 * array.sort! {|a, b| ... } -> self
3403 * Returns +self+ with its elements sorted in place.
3405 * With no block, compares elements using operator <tt>#<=></tt>
3406 * (see Comparable):
3408 * a = 'abcde'.split('').shuffle
3409 * a # => ["e", "b", "d", "a", "c"]
3410 * a.sort!
3411 * a # => ["a", "b", "c", "d", "e"]
3413 * With a block, calls the block with each element pair;
3414 * for each element pair +a+ and +b+, the block should return an integer:
3416 * - Negative when +b+ is to follow +a+.
3417 * - Zero when +a+ and +b+ are equivalent.
3418 * - Positive when +a+ is to follow +b+.
3420 * Example:
3422 * a = 'abcde'.split('').shuffle
3423 * a # => ["e", "b", "d", "a", "c"]
3424 * a.sort! {|a, b| a <=> b }
3425 * a # => ["a", "b", "c", "d", "e"]
3426 * a.sort! {|a, b| b <=> a }
3427 * a # => ["e", "d", "c", "b", "a"]
3429 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3430 * and may be unstable:
3432 * a = 'abcde'.split('').shuffle
3433 * a # => ["e", "b", "d", "a", "c"]
3434 * a.sort! {|a, b| 0 }
3435 * a # => ["d", "e", "c", "a", "b"]
3439 VALUE
3440 rb_ary_sort_bang(VALUE ary)
3442 rb_ary_modify(ary);
3443 RUBY_ASSERT(!ARY_SHARED_P(ary));
3444 if (RARRAY_LEN(ary) > 1) {
3445 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3446 struct ary_sort_data data;
3447 long len = RARRAY_LEN(ary);
3448 RBASIC_CLEAR_CLASS(tmp);
3449 data.ary = tmp;
3450 data.receiver = ary;
3451 RARRAY_PTR_USE(tmp, ptr, {
3452 ruby_qsort(ptr, len, sizeof(VALUE),
3453 rb_block_given_p()?sort_1:sort_2, &data);
3454 }); /* WB: no new reference */
3455 rb_ary_modify(ary);
3456 if (ARY_EMBED_P(tmp)) {
3457 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3458 rb_ary_unshare(ary);
3459 FL_SET_EMBED(ary);
3461 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3462 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3464 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3465 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3467 else {
3468 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3469 FL_UNSET_SHARED(ary);
3470 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3472 else {
3473 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3474 if (ARY_EMBED_P(ary)) {
3475 FL_UNSET_EMBED(ary);
3477 else if (ARY_SHARED_P(ary)) {
3478 /* ary might be destructively operated in the given block */
3479 rb_ary_unshare(ary);
3481 else {
3482 ary_heap_free(ary);
3484 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3485 ARY_SET_HEAP_LEN(ary, len);
3486 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3488 /* tmp was lost ownership for the ptr */
3489 FL_UNSET(tmp, FL_FREEZE);
3490 FL_SET_EMBED(tmp);
3491 ARY_SET_EMBED_LEN(tmp, 0);
3492 FL_SET(tmp, FL_FREEZE);
3494 /* tmp will be GC'ed. */
3495 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3497 ary_verify(ary);
3498 return ary;
3502 * call-seq:
3503 * array.sort -> new_array
3504 * array.sort {|a, b| ... } -> new_array
3506 * Returns a new +Array+ whose elements are those from +self+, sorted.
3508 * With no block, compares elements using operator <tt>#<=></tt>
3509 * (see Comparable):
3511 * a = 'abcde'.split('').shuffle
3512 * a # => ["e", "b", "d", "a", "c"]
3513 * a1 = a.sort
3514 * a1 # => ["a", "b", "c", "d", "e"]
3516 * With a block, calls the block with each element pair;
3517 * for each element pair +a+ and +b+, the block should return an integer:
3519 * - Negative when +b+ is to follow +a+.
3520 * - Zero when +a+ and +b+ are equivalent.
3521 * - Positive when +a+ is to follow +b+.
3523 * Example:
3525 * a = 'abcde'.split('').shuffle
3526 * a # => ["e", "b", "d", "a", "c"]
3527 * a1 = a.sort {|a, b| a <=> b }
3528 * a1 # => ["a", "b", "c", "d", "e"]
3529 * a2 = a.sort {|a, b| b <=> a }
3530 * a2 # => ["e", "d", "c", "b", "a"]
3532 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3533 * and may be unstable:
3535 * a = 'abcde'.split('').shuffle
3536 * a # => ["e", "b", "d", "a", "c"]
3537 * a1 = a.sort {|a, b| 0 }
3538 * a1 # => ["c", "e", "b", "d", "a"]
3540 * Related: Enumerable#sort_by.
3543 VALUE
3544 rb_ary_sort(VALUE ary)
3546 ary = rb_ary_dup(ary);
3547 rb_ary_sort_bang(ary);
3548 return ary;
3551 static VALUE rb_ary_bsearch_index(VALUE ary);
3554 * call-seq:
3555 * bsearch {|element| ... } -> found_element or nil
3556 * bsearch -> new_enumerator
3558 * Returns the element from +self+ found by a binary search,
3559 * or +nil+ if the search found no suitable element.
3561 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3563 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3566 static VALUE
3567 rb_ary_bsearch(VALUE ary)
3569 VALUE index_result = rb_ary_bsearch_index(ary);
3571 if (FIXNUM_P(index_result)) {
3572 return rb_ary_entry(ary, FIX2LONG(index_result));
3574 return index_result;
3578 * call-seq:
3579 * bsearch_index {|element| ... } -> integer or nil
3580 * bsearch_index -> new_enumerator
3582 * Returns the integer index of the element from +self+ found by a binary search,
3583 * or +nil+ if the search found no suitable element.
3585 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3587 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3590 static VALUE
3591 rb_ary_bsearch_index(VALUE ary)
3593 long low = 0, high = RARRAY_LEN(ary), mid;
3594 int smaller = 0, satisfied = 0;
3595 VALUE v, val;
3597 RETURN_ENUMERATOR(ary, 0, 0);
3598 while (low < high) {
3599 mid = low + ((high - low) / 2);
3600 val = rb_ary_entry(ary, mid);
3601 v = rb_yield(val);
3602 if (FIXNUM_P(v)) {
3603 if (v == INT2FIX(0)) return INT2FIX(mid);
3604 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3606 else if (v == Qtrue) {
3607 satisfied = 1;
3608 smaller = 1;
3610 else if (!RTEST(v)) {
3611 smaller = 0;
3613 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3614 const VALUE zero = INT2FIX(0);
3615 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3616 case 0: return INT2FIX(mid);
3617 case 1: smaller = 0; break;
3618 case -1: smaller = 1;
3621 else {
3622 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3623 " (must be numeric, true, false or nil)",
3624 rb_obj_class(v));
3626 if (smaller) {
3627 high = mid;
3629 else {
3630 low = mid + 1;
3633 if (!satisfied) return Qnil;
3634 return INT2FIX(low);
3638 static VALUE
3639 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3641 return rb_yield(i);
3645 * call-seq:
3646 * array.sort_by! {|element| ... } -> self
3647 * array.sort_by! -> new_enumerator
3649 * Sorts the elements of +self+ in place,
3650 * using an ordering determined by the block; returns self.
3652 * Calls the block with each successive element;
3653 * sorts elements based on the values returned from the block.
3655 * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
3657 * This example sorts strings based on their sizes:
3659 * a = ['aaaa', 'bbb', 'cc', 'd']
3660 * a.sort_by! {|element| element.size }
3661 * a # => ["d", "cc", "bbb", "aaaa"]
3663 * Returns a new Enumerator if no block given:
3665 * a = ['aaaa', 'bbb', 'cc', 'd']
3666 * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
3670 static VALUE
3671 rb_ary_sort_by_bang(VALUE ary)
3673 VALUE sorted;
3675 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3676 rb_ary_modify(ary);
3677 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3678 rb_ary_replace(ary, sorted);
3679 return ary;
3684 * call-seq:
3685 * collect {|element| ... } -> new_array
3686 * collect -> new_enumerator
3687 * map {|element| ... } -> new_array
3688 * map -> new_enumerator
3690 * With a block given, calls the block with each element of +self+;
3691 * returns a new array whose elements are the return values from the block:
3693 * a = [:foo, 'bar', 2]
3694 * a1 = a.map {|element| element.class }
3695 * a1 # => [Symbol, String, Integer]
3697 * With no block given, returns a new Enumerator.
3699 * Related: #collect!;
3700 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3703 static VALUE
3704 rb_ary_collect(VALUE ary)
3706 long i;
3707 VALUE collect;
3709 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3710 collect = rb_ary_new2(RARRAY_LEN(ary));
3711 for (i = 0; i < RARRAY_LEN(ary); i++) {
3712 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3714 return collect;
3719 * call-seq:
3720 * collect! {|element| ... } -> new_array
3721 * collect! -> new_enumerator
3722 * map! {|element| ... } -> new_array
3723 * map! -> new_enumerator
3725 * With a block given, calls the block with each element of +self+
3726 * and replaces the element with the block's return value;
3727 * returns +self+:
3729 * a = [:foo, 'bar', 2]
3730 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3732 * With no block given, returns a new Enumerator.
3734 * Related: #collect;
3735 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3738 static VALUE
3739 rb_ary_collect_bang(VALUE ary)
3741 long i;
3743 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3744 rb_ary_modify(ary);
3745 for (i = 0; i < RARRAY_LEN(ary); i++) {
3746 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3748 return ary;
3751 VALUE
3752 rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3754 VALUE result = rb_ary_new2(argc);
3755 long beg, len, i, j;
3757 for (i=0; i<argc; i++) {
3758 if (FIXNUM_P(argv[i])) {
3759 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3760 continue;
3762 /* check if idx is Range */
3763 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3764 long end = olen < beg+len ? olen : beg+len;
3765 for (j = beg; j < end; j++) {
3766 rb_ary_push(result, (*func)(obj, j));
3768 if (beg + len > j)
3769 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3770 continue;
3772 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3774 return result;
3777 static VALUE
3778 append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3780 long beg, len;
3781 if (FIXNUM_P(idx)) {
3782 beg = FIX2LONG(idx);
3784 /* check if idx is Range */
3785 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3786 if (len > 0) {
3787 const VALUE *const src = RARRAY_CONST_PTR(ary);
3788 const long end = beg + len;
3789 const long prevlen = RARRAY_LEN(result);
3790 if (beg < olen) {
3791 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3793 if (end > olen) {
3794 rb_ary_store(result, prevlen + len - 1, Qnil);
3797 return result;
3799 else {
3800 beg = NUM2LONG(idx);
3802 return rb_ary_push(result, rb_ary_entry(ary, beg));
3806 * call-seq:
3807 * array.values_at(*indexes) -> new_array
3809 * Returns a new +Array+ whose elements are the elements
3810 * of +self+ at the given Integer or Range +indexes+.
3812 * For each positive +index+, returns the element at offset +index+:
3814 * a = [:foo, 'bar', 2]
3815 * a.values_at(0, 2) # => [:foo, 2]
3816 * a.values_at(0..1) # => [:foo, "bar"]
3818 * The given +indexes+ may be in any order, and may repeat:
3820 * a = [:foo, 'bar', 2]
3821 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3822 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3824 * Assigns +nil+ for an +index+ that is too large:
3826 * a = [:foo, 'bar', 2]
3827 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3829 * Returns a new empty +Array+ if no arguments given.
3831 * For each negative +index+, counts backward from the end of the array:
3833 * a = [:foo, 'bar', 2]
3834 * a.values_at(-1, -3) # => [2, :foo]
3836 * Assigns +nil+ for an +index+ that is too small:
3838 * a = [:foo, 'bar', 2]
3839 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3841 * The given +indexes+ may have a mixture of signs:
3843 * a = [:foo, 'bar', 2]
3844 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3848 static VALUE
3849 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
3851 long i, olen = RARRAY_LEN(ary);
3852 VALUE result = rb_ary_new_capa(argc);
3853 for (i = 0; i < argc; ++i) {
3854 append_values_at_single(result, ary, olen, argv[i]);
3856 RB_GC_GUARD(ary);
3857 return result;
3862 * call-seq:
3863 * select {|element| ... } -> new_array
3864 * select -> new_enumerator
3865 * filter {|element| ... } -> new_array
3866 * filter -> new_enumerator
3868 * With a block given, calls the block with each element of +self+;
3869 * returns a new array containing those elements of +self+
3870 * for which the block returns a truthy value:
3872 * a = [:foo, 'bar', 2, :bam]
3873 * a.select {|element| element.to_s.start_with?('b') }
3874 * # => ["bar", :bam]
3876 * With no block given, returns a new Enumerator.
3878 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3881 static VALUE
3882 rb_ary_select(VALUE ary)
3884 VALUE result;
3885 long i;
3887 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3888 result = rb_ary_new2(RARRAY_LEN(ary));
3889 for (i = 0; i < RARRAY_LEN(ary); i++) {
3890 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
3891 rb_ary_push(result, rb_ary_elt(ary, i));
3894 return result;
3897 struct select_bang_arg {
3898 VALUE ary;
3899 long len[2];
3902 static VALUE
3903 select_bang_i(VALUE a)
3905 volatile struct select_bang_arg *arg = (void *)a;
3906 VALUE ary = arg->ary;
3907 long i1, i2;
3909 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
3910 VALUE v = RARRAY_AREF(ary, i1);
3911 if (!RTEST(rb_yield(v))) continue;
3912 if (i1 != i2) {
3913 rb_ary_store(ary, i2, v);
3915 arg->len[1] = ++i2;
3917 return (i1 == i2) ? Qnil : ary;
3920 static VALUE
3921 select_bang_ensure(VALUE a)
3923 volatile struct select_bang_arg *arg = (void *)a;
3924 VALUE ary = arg->ary;
3925 long len = RARRAY_LEN(ary);
3926 long i1 = arg->len[0], i2 = arg->len[1];
3928 if (i2 < len && i2 < i1) {
3929 long tail = 0;
3930 rb_ary_modify(ary);
3931 if (i1 < len) {
3932 tail = len - i1;
3933 RARRAY_PTR_USE(ary, ptr, {
3934 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
3937 ARY_SET_LEN(ary, i2 + tail);
3939 return ary;
3943 * call-seq:
3944 * select! {|element| ... } -> self or nil
3945 * select! -> new_enumerator
3946 * filter! {|element| ... } -> self or nil
3947 * filter! -> new_enumerator
3949 * With a block given, calls the block with each element of +self+;
3950 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3952 * Returns +self+ if any elements were removed:
3954 * a = [:foo, 'bar', 2, :bam]
3955 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3957 * Returns +nil+ if no elements were removed.
3959 * With no block given, returns a new Enumerator.
3961 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3964 static VALUE
3965 rb_ary_select_bang(VALUE ary)
3967 struct select_bang_arg args;
3969 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3970 rb_ary_modify(ary);
3972 args.ary = ary;
3973 args.len[0] = args.len[1] = 0;
3974 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
3978 * call-seq:
3979 * keep_if {|element| ... } -> self
3980 * keep_if -> new_enumerator
3982 * With a block given, calls the block with each element of +self+;
3983 * removes the element from +self+ if the block does not return a truthy value:
3985 * a = [:foo, 'bar', 2, :bam]
3986 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3988 * With no block given, returns a new Enumerator.
3990 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3993 static VALUE
3994 rb_ary_keep_if(VALUE ary)
3996 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3997 rb_ary_select_bang(ary);
3998 return ary;
4001 static void
4002 ary_resize_smaller(VALUE ary, long len)
4004 rb_ary_modify(ary);
4005 if (RARRAY_LEN(ary) > len) {
4006 ARY_SET_LEN(ary, len);
4007 if (len * 2 < ARY_CAPA(ary) &&
4008 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
4009 ary_resize_capa(ary, len * 2);
4015 * call-seq:
4016 * delete(object) -> last_removed_object
4017 * delete(object) {|element| ... } -> last_removed_object or block_return
4019 * Removes zero or more elements from +self+.
4021 * With no block given,
4022 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4023 * returns the last removed element:
4025 * a = [0, 1, 2, 2.0]
4026 * a.delete(2) # => 2.0
4027 * a # => [0, 1]
4029 * Returns +nil+ if no elements removed:
4031 * a.delete(2) # => nil
4033 * With a block given,
4034 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4036 * If any such elements are found, ignores the block
4037 * and returns the last removed element:
4039 * a = [0, 1, 2, 2.0]
4040 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4041 * a # => [0, 1]
4043 * If no such element is found, returns the block's return value:
4045 * a.delete(2) {|element| "Element #{element} not found." }
4046 * # => "Element 2 not found."
4048 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4051 VALUE
4052 rb_ary_delete(VALUE ary, VALUE item)
4054 VALUE v = item;
4055 long i1, i2;
4057 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4058 VALUE e = RARRAY_AREF(ary, i1);
4060 if (rb_equal(e, item)) {
4061 v = e;
4062 continue;
4064 if (i1 != i2) {
4065 rb_ary_store(ary, i2, e);
4067 i2++;
4069 if (RARRAY_LEN(ary) == i2) {
4070 if (rb_block_given_p()) {
4071 return rb_yield(item);
4073 return Qnil;
4076 ary_resize_smaller(ary, i2);
4078 ary_verify(ary);
4079 return v;
4082 void
4083 rb_ary_delete_same(VALUE ary, VALUE item)
4085 long i1, i2;
4087 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4088 VALUE e = RARRAY_AREF(ary, i1);
4090 if (e == item) {
4091 continue;
4093 if (i1 != i2) {
4094 rb_ary_store(ary, i2, e);
4096 i2++;
4098 if (RARRAY_LEN(ary) == i2) {
4099 return;
4102 ary_resize_smaller(ary, i2);
4105 VALUE
4106 rb_ary_delete_at(VALUE ary, long pos)
4108 long len = RARRAY_LEN(ary);
4109 VALUE del;
4111 if (pos >= len) return Qnil;
4112 if (pos < 0) {
4113 pos += len;
4114 if (pos < 0) return Qnil;
4117 rb_ary_modify(ary);
4118 del = RARRAY_AREF(ary, pos);
4119 RARRAY_PTR_USE(ary, ptr, {
4120 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4122 ARY_INCREASE_LEN(ary, -1);
4123 ary_verify(ary);
4124 return del;
4128 * call-seq:
4129 * delete_at(index) -> removed_object or nil
4131 * Removes the element of +self+ at the given +index+, which must be an
4132 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4134 * When +index+ is non-negative, deletes the element at offset +index+:
4136 * a = [:foo, 'bar', 2]
4137 * a.delete_at(1) # => "bar"
4138 * a # => [:foo, 2]
4140 * When +index+ is negative, counts backward from the end of the array:
4142 * a = [:foo, 'bar', 2]
4143 * a.delete_at(-2) # => "bar"
4144 * a # => [:foo, 2]
4146 * When +index+ is out of range, returns +nil+.
4148 * a = [:foo, 'bar', 2]
4149 * a.delete_at(3) # => nil
4150 * a.delete_at(-4) # => nil
4152 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4155 static VALUE
4156 rb_ary_delete_at_m(VALUE ary, VALUE pos)
4158 return rb_ary_delete_at(ary, NUM2LONG(pos));
4161 static VALUE
4162 ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
4164 const long orig_len = RARRAY_LEN(ary);
4166 if (len < 0) {
4167 return Qnil;
4169 else if (pos < -orig_len) {
4170 return Qnil;
4172 else if (pos < 0) {
4173 pos += orig_len;
4175 else if (orig_len < pos) {
4176 return Qnil;
4178 if (orig_len < pos + len) {
4179 len = orig_len - pos;
4181 if (len == 0) {
4182 return rb_ary_new2(0);
4184 else {
4185 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4186 rb_ary_splice(ary, pos, len, 0, 0);
4187 return arg2;
4192 * call-seq:
4193 * array.slice!(n) -> object or nil
4194 * array.slice!(start, length) -> new_array or nil
4195 * array.slice!(range) -> new_array or nil
4197 * Removes and returns elements from +self+.
4199 * When the only argument is an Integer +n+,
4200 * removes and returns the _nth_ element in +self+:
4202 * a = [:foo, 'bar', 2]
4203 * a.slice!(1) # => "bar"
4204 * a # => [:foo, 2]
4206 * If +n+ is negative, counts backwards from the end of +self+:
4208 * a = [:foo, 'bar', 2]
4209 * a.slice!(-1) # => 2
4210 * a # => [:foo, "bar"]
4212 * If +n+ is out of range, returns +nil+.
4214 * When the only arguments are Integers +start+ and +length+,
4215 * removes +length+ elements from +self+ beginning at offset +start+;
4216 * returns the deleted objects in a new +Array+:
4218 * a = [:foo, 'bar', 2]
4219 * a.slice!(0, 2) # => [:foo, "bar"]
4220 * a # => [2]
4222 * If <tt>start + length</tt> exceeds the array size,
4223 * removes and returns all elements from offset +start+ to the end:
4225 * a = [:foo, 'bar', 2]
4226 * a.slice!(1, 50) # => ["bar", 2]
4227 * a # => [:foo]
4229 * If <tt>start == a.size</tt> and +length+ is non-negative,
4230 * returns a new empty +Array+.
4232 * If +length+ is negative, returns +nil+.
4234 * When the only argument is a Range object +range+,
4235 * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
4237 * a = [:foo, 'bar', 2]
4238 * a.slice!(1..2) # => ["bar", 2]
4239 * a # => [:foo]
4241 * If <tt>range.start == a.size</tt>, returns a new empty +Array+.
4243 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
4245 * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
4247 * a = [:foo, 'bar', 2]
4248 * a.slice!(0..-2) # => [:foo, "bar"]
4249 * a # => [2]
4251 * If <tt>range.start</tt> is negative,
4252 * calculates the start index backwards from the end of the array:
4254 * a = [:foo, 'bar', 2]
4255 * a.slice!(-2..2) # => ["bar", 2]
4256 * a # => [:foo]
4260 static VALUE
4261 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4263 VALUE arg1;
4264 long pos, len;
4266 rb_ary_modify_check(ary);
4267 rb_check_arity(argc, 1, 2);
4268 arg1 = argv[0];
4270 if (argc == 2) {
4271 pos = NUM2LONG(argv[0]);
4272 len = NUM2LONG(argv[1]);
4273 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4276 if (!FIXNUM_P(arg1)) {
4277 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4278 case Qtrue:
4279 /* valid range */
4280 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4281 case Qnil:
4282 /* invalid range */
4283 return Qnil;
4284 default:
4285 /* not a range */
4286 break;
4290 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4293 static VALUE
4294 ary_reject(VALUE orig, VALUE result)
4296 long i;
4298 for (i = 0; i < RARRAY_LEN(orig); i++) {
4299 VALUE v = RARRAY_AREF(orig, i);
4301 if (!RTEST(rb_yield(v))) {
4302 rb_ary_push(result, v);
4305 return result;
4308 static VALUE
4309 reject_bang_i(VALUE a)
4311 volatile struct select_bang_arg *arg = (void *)a;
4312 VALUE ary = arg->ary;
4313 long i1, i2;
4315 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4316 VALUE v = RARRAY_AREF(ary, i1);
4317 if (RTEST(rb_yield(v))) continue;
4318 if (i1 != i2) {
4319 rb_ary_store(ary, i2, v);
4321 arg->len[1] = ++i2;
4323 return (i1 == i2) ? Qnil : ary;
4326 static VALUE
4327 ary_reject_bang(VALUE ary)
4329 struct select_bang_arg args;
4330 rb_ary_modify_check(ary);
4331 args.ary = ary;
4332 args.len[0] = args.len[1] = 0;
4333 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4337 * call-seq:
4338 * reject! {|element| ... } -> self or nil
4339 * reject! -> new_enumerator
4341 * With a block given, calls the block with each element of +self+;
4342 * removes each element for which the block returns a truthy value.
4344 * Returns +self+ if any elements removed:
4346 * a = [:foo, 'bar', 2, 'bat']
4347 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4349 * Returns +nil+ if no elements removed.
4351 * With no block given, returns a new Enumerator.
4353 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4356 static VALUE
4357 rb_ary_reject_bang(VALUE ary)
4359 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4360 rb_ary_modify(ary);
4361 return ary_reject_bang(ary);
4365 * call-seq:
4366 * reject {|element| ... } -> new_array
4367 * reject -> new_enumerator
4369 * With a block given, returns a new array whose elements are all those from +self+
4370 * for which the block returns +false+ or +nil+:
4372 * a = [:foo, 'bar', 2, 'bat']
4373 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4374 * a1 # => [:foo, 2]
4376 * With no block given, returns a new Enumerator.
4378 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4381 static VALUE
4382 rb_ary_reject(VALUE ary)
4384 VALUE rejected_ary;
4386 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4387 rejected_ary = rb_ary_new();
4388 ary_reject(ary, rejected_ary);
4389 return rejected_ary;
4393 * call-seq:
4394 * delete_if {|element| ... } -> self
4395 * delete_if -> new_numerator
4397 * With a block given, calls the block with each element of +self+;
4398 * removes the element if the block returns a truthy value;
4399 * returns +self+:
4401 * a = [:foo, 'bar', 2, 'bat']
4402 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4404 * With no block given, returns a new Enumerator.
4406 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4409 static VALUE
4410 rb_ary_delete_if(VALUE ary)
4412 ary_verify(ary);
4413 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4414 ary_reject_bang(ary);
4415 return ary;
4418 static VALUE
4419 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4421 VALUE *args = (VALUE *)cbarg;
4422 if (argc > 1) val = rb_ary_new4(argc, argv);
4423 rb_ary_push(args[0], val);
4424 if (--args[1] == 0) rb_iter_break();
4425 return Qnil;
4428 static VALUE
4429 take_items(VALUE obj, long n)
4431 VALUE result = rb_check_array_type(obj);
4432 VALUE args[2];
4434 if (n == 0) return result;
4435 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4436 result = rb_ary_new2(n);
4437 args[0] = result; args[1] = (VALUE)n;
4438 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4439 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4440 rb_obj_class(obj));
4441 return result;
4446 * call-seq:
4447 * array.zip(*other_arrays) -> new_array
4448 * array.zip(*other_arrays) {|other_array| ... } -> nil
4450 * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
4451 * whose elements are Arrays.
4453 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4454 * and contains:
4456 * - The _nth_ element of +self+.
4457 * - The _nth_ element of each of the +other_arrays+.
4459 * If all +other_arrays+ and +self+ are the same size:
4461 * a = [:a0, :a1, :a2, :a3]
4462 * b = [:b0, :b1, :b2, :b3]
4463 * c = [:c0, :c1, :c2, :c3]
4464 * d = a.zip(b, c)
4465 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4467 * If any array in +other_arrays+ is smaller than +self+,
4468 * fills to <tt>self.size</tt> with +nil+:
4470 * a = [:a0, :a1, :a2, :a3]
4471 * b = [:b0, :b1, :b2]
4472 * c = [:c0, :c1]
4473 * d = a.zip(b, c)
4474 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4476 * If any array in +other_arrays+ is larger than +self+,
4477 * its trailing elements are ignored:
4479 * a = [:a0, :a1, :a2, :a3]
4480 * b = [:b0, :b1, :b2, :b3, :b4]
4481 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4482 * d = a.zip(b, c)
4483 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4485 * If an argument is not an array, it extracts the values by calling #each:
4487 * a = [:a0, :a1, :a2, :a2]
4488 * b = 1..4
4489 * c = a.zip(b)
4490 * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
4492 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
4494 * a = [:a0, :a1, :a2, :a3]
4495 * b = [:b0, :b1, :b2, :b3]
4496 * c = [:c0, :c1, :c2, :c3]
4497 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4499 * Output:
4501 * [:a0, :b0, :c0]
4502 * [:a1, :b1, :c1]
4503 * [:a2, :b2, :c2]
4504 * [:a3, :b3, :c3]
4508 static VALUE
4509 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4511 int i, j;
4512 long len = RARRAY_LEN(ary);
4513 VALUE result = Qnil;
4515 for (i=0; i<argc; i++) {
4516 argv[i] = take_items(argv[i], len);
4519 if (rb_block_given_p()) {
4520 int arity = rb_block_arity();
4522 if (arity > 1) {
4523 VALUE work, *tmp;
4525 tmp = ALLOCV_N(VALUE, work, argc+1);
4527 for (i=0; i<RARRAY_LEN(ary); i++) {
4528 tmp[0] = RARRAY_AREF(ary, i);
4529 for (j=0; j<argc; j++) {
4530 tmp[j+1] = rb_ary_elt(argv[j], i);
4532 rb_yield_values2(argc+1, tmp);
4535 if (work) ALLOCV_END(work);
4537 else {
4538 for (i=0; i<RARRAY_LEN(ary); i++) {
4539 VALUE tmp = rb_ary_new2(argc+1);
4541 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4542 for (j=0; j<argc; j++) {
4543 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4545 rb_yield(tmp);
4549 else {
4550 result = rb_ary_new_capa(len);
4552 for (i=0; i<len; i++) {
4553 VALUE tmp = rb_ary_new_capa(argc+1);
4555 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4556 for (j=0; j<argc; j++) {
4557 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4559 rb_ary_push(result, tmp);
4563 return result;
4567 * call-seq:
4568 * array.transpose -> new_array
4570 * Transposes the rows and columns in an +Array+ of Arrays;
4571 * the nested Arrays must all be the same size:
4573 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4574 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4578 static VALUE
4579 rb_ary_transpose(VALUE ary)
4581 long elen = -1, alen, i, j;
4582 VALUE tmp, result = 0;
4584 alen = RARRAY_LEN(ary);
4585 if (alen == 0) return rb_ary_dup(ary);
4586 for (i=0; i<alen; i++) {
4587 tmp = to_ary(rb_ary_elt(ary, i));
4588 if (elen < 0) { /* first element */
4589 elen = RARRAY_LEN(tmp);
4590 result = rb_ary_new2(elen);
4591 for (j=0; j<elen; j++) {
4592 rb_ary_store(result, j, rb_ary_new2(alen));
4595 else if (elen != RARRAY_LEN(tmp)) {
4596 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4597 RARRAY_LEN(tmp), elen);
4599 for (j=0; j<elen; j++) {
4600 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4603 return result;
4607 * call-seq:
4608 * initialize_copy(other_array) -> self
4609 * replace(other_array) -> self
4611 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4612 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4613 * returns +self+:
4615 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4616 * a.replace(['d', 'e']) # => ["d", "e"]
4618 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4621 VALUE
4622 rb_ary_replace(VALUE copy, VALUE orig)
4624 rb_ary_modify_check(copy);
4625 orig = to_ary(orig);
4626 if (copy == orig) return copy;
4628 rb_ary_reset(copy);
4630 /* orig has enough space to embed the contents of orig. */
4631 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4632 RUBY_ASSERT(ARY_EMBED_P(copy));
4633 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4634 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4636 /* orig is embedded but copy does not have enough space to embed the
4637 * contents of orig. */
4638 else if (ARY_EMBED_P(orig)) {
4639 long len = ARY_EMBED_LEN(orig);
4640 VALUE *ptr = ary_heap_alloc_buffer(len);
4642 FL_UNSET_EMBED(copy);
4643 ARY_SET_PTR(copy, ptr);
4644 ARY_SET_LEN(copy, len);
4645 ARY_SET_CAPA(copy, len);
4647 // No allocation and exception expected that could leave `copy` in a
4648 // bad state from the edits above.
4649 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
4651 /* Otherwise, orig is on heap and copy does not have enough space to embed
4652 * the contents of orig. */
4653 else {
4654 VALUE shared_root = ary_make_shared(orig);
4655 FL_UNSET_EMBED(copy);
4656 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4657 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4658 rb_ary_set_shared(copy, shared_root);
4660 ary_verify(copy);
4661 return copy;
4665 * call-seq:
4666 * clear -> self
4668 * Removes all elements from +self+; returns +self+:
4670 * a = [:foo, 'bar', 2]
4671 * a.clear # => []
4673 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4676 VALUE
4677 rb_ary_clear(VALUE ary)
4679 rb_ary_modify_check(ary);
4680 if (ARY_SHARED_P(ary)) {
4681 rb_ary_unshare(ary);
4682 FL_SET_EMBED(ary);
4683 ARY_SET_EMBED_LEN(ary, 0);
4685 else {
4686 ARY_SET_LEN(ary, 0);
4687 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4688 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4691 ary_verify(ary);
4692 return ary;
4696 * call-seq:
4697 * fill(object, start = nil, count = nil) -> new_array
4698 * fill(object, range) -> new_array
4699 * fill(start = nil, count = nil) {|element| ... } -> new_array
4700 * fill(range) {|element| ... } -> new_array
4702 * Replaces selected elements in +self+;
4703 * may add elements to +self+;
4704 * always returns +self+ (never a new array).
4706 * In brief:
4708 * # Non-negative start.
4709 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4710 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4712 * # Extends with specified values if necessary.
4713 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4714 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4716 * # Fills with nils if necessary.
4717 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4718 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4720 * # For negative start, counts backwards from the end.
4721 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4722 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4724 * # Range.
4725 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4726 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4728 * When arguments +start+ and +count+ are given,
4729 * they select the elements of +self+ to be replaced;
4730 * each must be an
4731 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
4732 * (or +nil+):
4734 * - +start+ specifies the zero-based offset of the first element to be replaced;
4735 * +nil+ means zero.
4736 * - +count+ is the number of consecutive elements to be replaced;
4737 * +nil+ means "all the rest."
4739 * With argument +object+ given,
4740 * that one object is used for all replacements:
4742 * o = Object.new # => #<Object:0x0000014e7bff7600>
4743 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4744 * a.fill(o, 1, 2)
4745 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
4747 * With a block given, the block is called once for each element to be replaced;
4748 * the value passed to the block is the _index_ of the element to be replaced
4749 * (not the element itself);
4750 * the block's return value replaces the element:
4752 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4753 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
4755 * For arguments +start+ and +count+:
4757 * - If +start+ is non-negative,
4758 * replaces +count+ elements beginning at offset +start+:
4760 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
4761 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4762 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
4764 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4765 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4766 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
4768 * Extends +self+ if necessary:
4770 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4771 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
4773 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4774 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
4776 * Fills with +nil+ if necessary:
4778 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
4779 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4781 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
4782 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4784 * Does nothing if +count+ is non-positive:
4786 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
4787 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
4788 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
4790 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4791 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4792 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4794 * - If +start+ is negative, counts backwards from the end of +self+:
4796 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
4797 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4799 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
4800 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4802 * Extends +self+ if necessary:
4804 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
4805 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
4807 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
4808 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
4810 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
4812 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
4813 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
4815 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4816 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4818 * Does nothing if +count+ is non-positive:
4820 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
4821 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
4823 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4824 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4826 * When argument +range+ is given,
4827 * it must be a Range object whose members are numeric;
4828 * its +begin+ and +end+ values determine the elements of +self+
4829 * to be replaced:
4831 * - If both +begin+ and +end+ are positive, they specify the first and last elements
4832 * to be replaced:
4834 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4835 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4837 * If +end+ is smaller than +begin+, replaces no elements:
4839 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
4840 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
4842 * - If either is negative (or both are negative), counts backwards from the end of +self+:
4844 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
4845 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
4846 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
4848 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4849 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4850 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4852 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
4854 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
4855 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
4857 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4858 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4860 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
4861 * replaces elements to the end of +self+:
4863 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
4864 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
4866 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
4867 * replaces elements from the beginning of +self+:
4869 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
4870 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
4872 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4875 static VALUE
4876 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
4878 VALUE item = Qundef, arg1, arg2;
4879 long beg = 0, end = 0, len = 0;
4881 if (rb_block_given_p()) {
4882 rb_scan_args(argc, argv, "02", &arg1, &arg2);
4883 argc += 1; /* hackish */
4885 else {
4886 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
4888 switch (argc) {
4889 case 1:
4890 beg = 0;
4891 len = RARRAY_LEN(ary);
4892 break;
4893 case 2:
4894 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
4895 break;
4897 /* fall through */
4898 case 3:
4899 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
4900 if (beg < 0) {
4901 beg = RARRAY_LEN(ary) + beg;
4902 if (beg < 0) beg = 0;
4904 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
4905 break;
4907 rb_ary_modify(ary);
4908 if (len < 0) {
4909 return ary;
4911 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
4912 rb_raise(rb_eArgError, "argument too big");
4914 end = beg + len;
4915 if (RARRAY_LEN(ary) < end) {
4916 if (end >= ARY_CAPA(ary)) {
4917 ary_resize_capa(ary, end);
4919 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
4920 ARY_SET_LEN(ary, end);
4923 if (UNDEF_P(item)) {
4924 VALUE v;
4925 long i;
4927 for (i=beg; i<end; i++) {
4928 v = rb_yield(LONG2NUM(i));
4929 if (i>=RARRAY_LEN(ary)) break;
4930 ARY_SET(ary, i, v);
4933 else {
4934 ary_memfill(ary, beg, len, item);
4936 return ary;
4940 * call-seq:
4941 * self + other_array -> new_array
4943 * Returns a new array containing all elements of +self+
4944 * followed by all elements of +other_array+:
4946 * a = [0, 1] + [2, 3]
4947 * a # => [0, 1, 2, 3]
4949 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
4952 VALUE
4953 rb_ary_plus(VALUE x, VALUE y)
4955 VALUE z;
4956 long len, xlen, ylen;
4958 y = to_ary(y);
4959 xlen = RARRAY_LEN(x);
4960 ylen = RARRAY_LEN(y);
4961 len = xlen + ylen;
4962 z = rb_ary_new2(len);
4964 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
4965 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
4966 ARY_SET_LEN(z, len);
4967 return z;
4970 static VALUE
4971 ary_append(VALUE x, VALUE y)
4973 long n = RARRAY_LEN(y);
4974 if (n > 0) {
4975 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
4977 RB_GC_GUARD(y);
4978 return x;
4982 * call-seq:
4983 * concat(*other_arrays) -> self
4985 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
4987 * a = [0, 1]
4988 * a.concat(['two', 'three'], [:four, :five], a)
4989 * # => [0, 1, "two", "three", :four, :five, 0, 1]
4991 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4994 static VALUE
4995 rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
4997 rb_ary_modify_check(ary);
4999 if (argc == 1) {
5000 rb_ary_concat(ary, argv[0]);
5002 else if (argc > 1) {
5003 int i;
5004 VALUE args = rb_ary_hidden_new(argc);
5005 for (i = 0; i < argc; i++) {
5006 rb_ary_concat(args, argv[i]);
5008 ary_append(ary, args);
5011 ary_verify(ary);
5012 return ary;
5015 VALUE
5016 rb_ary_concat(VALUE x, VALUE y)
5018 return ary_append(x, to_ary(y));
5022 * call-seq:
5023 * self * n -> new_array
5024 * self * string_separator -> new_string
5026 * When non-negative integer argument +n+ is given,
5027 * returns a new array built by concatenating +n+ copies of +self+:
5029 * a = ['x', 'y']
5030 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5032 * When string argument +string_separator+ is given,
5033 * equivalent to <tt>self.join(string_separator)</tt>:
5035 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
5039 static VALUE
5040 rb_ary_times(VALUE ary, VALUE times)
5042 VALUE ary2, tmp;
5043 const VALUE *ptr;
5044 long t, len;
5046 tmp = rb_check_string_type(times);
5047 if (!NIL_P(tmp)) {
5048 return rb_ary_join(ary, tmp);
5051 len = NUM2LONG(times);
5052 if (len == 0) {
5053 ary2 = ary_new(rb_cArray, 0);
5054 goto out;
5056 if (len < 0) {
5057 rb_raise(rb_eArgError, "negative argument");
5059 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
5060 rb_raise(rb_eArgError, "argument too big");
5062 len *= RARRAY_LEN(ary);
5064 ary2 = ary_new(rb_cArray, len);
5065 ARY_SET_LEN(ary2, len);
5067 ptr = RARRAY_CONST_PTR(ary);
5068 t = RARRAY_LEN(ary);
5069 if (0 < t) {
5070 ary_memcpy(ary2, 0, t, ptr);
5071 while (t <= len/2) {
5072 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5073 t *= 2;
5075 if (t < len) {
5076 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5079 out:
5080 return ary2;
5084 * call-seq:
5085 * assoc(object) -> found_array or nil
5087 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5088 * and <tt>ele[0] == object</tt>:
5090 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5091 * a.assoc(4) # => [4, 5, 6]
5093 * Returns +nil+ if no such element is found.
5095 * Related: Array#rassoc;
5096 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5099 VALUE
5100 rb_ary_assoc(VALUE ary, VALUE key)
5102 long i;
5103 VALUE v;
5105 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5106 v = rb_check_array_type(RARRAY_AREF(ary, i));
5107 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5108 rb_equal(RARRAY_AREF(v, 0), key))
5109 return v;
5111 return Qnil;
5115 * call-seq:
5116 * rassoc(object) -> found_array or nil
5118 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5119 * and <tt>ele[1] == object</tt>:
5121 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5122 * a.rassoc(4) # => [2, 4]
5123 * a.rassoc(5) # => [4, 5, 6]
5125 * Returns +nil+ if no such element is found.
5127 * Related: Array#assoc;
5128 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5131 VALUE
5132 rb_ary_rassoc(VALUE ary, VALUE value)
5134 long i;
5135 VALUE v;
5137 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5138 v = rb_check_array_type(RARRAY_AREF(ary, i));
5139 if (RB_TYPE_P(v, T_ARRAY) &&
5140 RARRAY_LEN(v) > 1 &&
5141 rb_equal(RARRAY_AREF(v, 1), value))
5142 return v;
5144 return Qnil;
5147 static VALUE
5148 recursive_equal(VALUE ary1, VALUE ary2, int recur)
5150 long i, len1;
5151 const VALUE *p1, *p2;
5153 if (recur) return Qtrue; /* Subtle! */
5155 /* rb_equal() can evacuate ptrs */
5156 p1 = RARRAY_CONST_PTR(ary1);
5157 p2 = RARRAY_CONST_PTR(ary2);
5158 len1 = RARRAY_LEN(ary1);
5160 for (i = 0; i < len1; i++) {
5161 if (*p1 != *p2) {
5162 if (rb_equal(*p1, *p2)) {
5163 len1 = RARRAY_LEN(ary1);
5164 if (len1 != RARRAY_LEN(ary2))
5165 return Qfalse;
5166 if (len1 < i)
5167 return Qtrue;
5168 p1 = RARRAY_CONST_PTR(ary1) + i;
5169 p2 = RARRAY_CONST_PTR(ary2) + i;
5171 else {
5172 return Qfalse;
5175 p1++;
5176 p2++;
5178 return Qtrue;
5182 * call-seq:
5183 * self == other_array -> true or false
5185 * Returns whether both:
5187 * - +self+ and +other_array+ are the same size.
5188 * - Their corresponding elements are the same;
5189 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5190 * <tt>self[i] == other_array[i]</tt>.
5192 * Examples:
5194 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5195 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5196 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5197 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5199 * This method is different from method Array#eql?,
5200 * which compares elements using <tt>Object#eql?</tt>.
5202 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5205 static VALUE
5206 rb_ary_equal(VALUE ary1, VALUE ary2)
5208 if (ary1 == ary2) return Qtrue;
5209 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5210 if (!rb_respond_to(ary2, idTo_ary)) {
5211 return Qfalse;
5213 return rb_equal(ary2, ary1);
5215 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5216 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5217 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5220 static VALUE
5221 recursive_eql(VALUE ary1, VALUE ary2, int recur)
5223 long i;
5225 if (recur) return Qtrue; /* Subtle! */
5226 for (i=0; i<RARRAY_LEN(ary1); i++) {
5227 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5228 return Qfalse;
5230 return Qtrue;
5234 * call-seq:
5235 * eql?(other_array) -> true or false
5237 * Returns +true+ if +self+ and +other_array+ are the same size,
5238 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5240 * a0 = [:foo, 'bar', 2]
5241 * a1 = [:foo, 'bar', 2]
5242 * a1.eql?(a0) # => true
5244 * Otherwise, returns +false+.
5246 * This method is different from method Array#==,
5247 * which compares using method <tt>Object#==</tt>.
5249 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5252 static VALUE
5253 rb_ary_eql(VALUE ary1, VALUE ary2)
5255 if (ary1 == ary2) return Qtrue;
5256 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5257 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5258 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5259 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5262 VALUE
5263 rb_ary_hash_values(long len, const VALUE *elements)
5265 long i;
5266 st_index_t h;
5267 VALUE n;
5269 h = rb_hash_start(len);
5270 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5271 for (i=0; i<len; i++) {
5272 n = rb_hash(elements[i]);
5273 h = rb_hash_uint(h, NUM2LONG(n));
5275 h = rb_hash_end(h);
5276 return ST2FIX(h);
5280 * call-seq:
5281 * hash -> integer
5283 * Returns the integer hash value for +self+.
5285 * Two arrays with the same content will have the same hash value
5286 * (and will compare using eql?):
5288 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5289 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5290 * ['a', 'b'].hash == ['a'].hash # => false
5294 static VALUE
5295 rb_ary_hash(VALUE ary)
5297 return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
5301 * call-seq:
5302 * include?(object) -> true or false
5304 * Returns whether for some element +element+ in +self+,
5305 * <tt>object == element</tt>:
5307 * [0, 1, 2].include?(2) # => true
5308 * [0, 1, 2].include?(2.0) # => true
5309 * [0, 1, 2].include?(2.1) # => false
5311 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5314 VALUE
5315 rb_ary_includes(VALUE ary, VALUE item)
5317 long i;
5318 VALUE e;
5320 for (i=0; i<RARRAY_LEN(ary); i++) {
5321 e = RARRAY_AREF(ary, i);
5322 if (rb_equal(e, item)) {
5323 return Qtrue;
5326 return Qfalse;
5329 static VALUE
5330 rb_ary_includes_by_eql(VALUE ary, VALUE item)
5332 long i;
5333 VALUE e;
5335 for (i=0; i<RARRAY_LEN(ary); i++) {
5336 e = RARRAY_AREF(ary, i);
5337 if (rb_eql(item, e)) {
5338 return Qtrue;
5341 return Qfalse;
5344 static VALUE
5345 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5347 long i, len;
5349 if (recur) return Qundef; /* Subtle! */
5350 len = RARRAY_LEN(ary1);
5351 if (len > RARRAY_LEN(ary2)) {
5352 len = RARRAY_LEN(ary2);
5354 for (i=0; i<len; i++) {
5355 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5356 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5357 if (v != INT2FIX(0)) {
5358 return v;
5361 return Qundef;
5365 * call-seq:
5366 * self <=> other_array -> -1, 0, or 1
5368 * Returns -1, 0, or 1 as +self+ is determined
5369 * to be less than, equal to, or greater than +other_array+.
5371 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5373 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5374 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5376 * [0, 1, 2] <=> [0, 0, 2] # => 1
5378 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5380 * [0, 1, 2] <=> [0, 2, 2] # => -1
5382 * - Continues if <tt>result[i]</tt> is 0.
5384 * When every +result+ is 0,
5385 * returns <tt>self.size <=> other_array.size</tt>
5386 * (see Integer#<=>):
5388 * [0, 1, 2] <=> [0, 1] # => 1
5389 * [0, 1, 2] <=> [0, 1, 2] # => 0
5390 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5392 * Note that when +other_array+ is larger than +self+,
5393 * its trailing elements do not affect the result:
5395 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5396 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5397 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5399 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5402 VALUE
5403 rb_ary_cmp(VALUE ary1, VALUE ary2)
5405 long len;
5406 VALUE v;
5408 ary2 = rb_check_array_type(ary2);
5409 if (NIL_P(ary2)) return Qnil;
5410 if (ary1 == ary2) return INT2FIX(0);
5411 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5412 if (!UNDEF_P(v)) return v;
5413 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5414 if (len == 0) return INT2FIX(0);
5415 if (len > 0) return INT2FIX(1);
5416 return INT2FIX(-1);
5419 static VALUE
5420 ary_add_hash(VALUE hash, VALUE ary)
5422 long i;
5424 for (i=0; i<RARRAY_LEN(ary); i++) {
5425 VALUE elt = RARRAY_AREF(ary, i);
5426 rb_hash_add_new_element(hash, elt, elt);
5428 return hash;
5431 static inline VALUE
5432 ary_tmp_hash_new(VALUE ary)
5434 long size = RARRAY_LEN(ary);
5435 VALUE hash = rb_hash_new_with_size(size);
5437 RBASIC_CLEAR_CLASS(hash);
5438 return hash;
5441 static VALUE
5442 ary_make_hash(VALUE ary)
5444 VALUE hash = ary_tmp_hash_new(ary);
5445 return ary_add_hash(hash, ary);
5448 static VALUE
5449 ary_add_hash_by(VALUE hash, VALUE ary)
5451 long i;
5453 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5454 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5455 rb_hash_add_new_element(hash, k, v);
5457 return hash;
5460 static VALUE
5461 ary_make_hash_by(VALUE ary)
5463 VALUE hash = ary_tmp_hash_new(ary);
5464 return ary_add_hash_by(hash, ary);
5468 * call-seq:
5469 * self - other_array -> new_array
5471 * Returns a new array containing only those elements of +self+
5472 * that are not found in +other_array+;
5473 * the order from +self+ is preserved:
5475 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5476 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5477 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5479 * Element are compared using method <tt>#eql?</tt>
5480 * (as defined in each element of +self+).
5482 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5485 VALUE
5486 rb_ary_diff(VALUE ary1, VALUE ary2)
5488 VALUE ary3;
5489 VALUE hash;
5490 long i;
5492 ary2 = to_ary(ary2);
5493 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5494 ary3 = rb_ary_new();
5496 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5497 for (i=0; i<RARRAY_LEN(ary1); i++) {
5498 VALUE elt = rb_ary_elt(ary1, i);
5499 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5500 rb_ary_push(ary3, elt);
5502 return ary3;
5505 hash = ary_make_hash(ary2);
5506 for (i=0; i<RARRAY_LEN(ary1); i++) {
5507 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5508 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5511 return ary3;
5515 * call-seq:
5516 * difference(*other_arrays = []) -> new_array
5518 * Returns a new array containing only those elements from +self+
5519 * that are not found in any of the given +other_arrays+;
5520 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5522 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5523 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5524 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5525 * [0, 1, 2].difference # => [0, 1, 2]
5527 * Returns a copy of +self+ if no arguments are given.
5529 * Related: Array#-;
5530 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5533 static VALUE
5534 rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5536 VALUE ary_diff;
5537 long i, length;
5538 volatile VALUE t0;
5539 bool *is_hash = ALLOCV_N(bool, t0, argc);
5540 ary_diff = rb_ary_new();
5541 length = RARRAY_LEN(ary);
5543 for (i = 0; i < argc; i++) {
5544 argv[i] = to_ary(argv[i]);
5545 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5546 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5549 for (i = 0; i < RARRAY_LEN(ary); i++) {
5550 int j;
5551 VALUE elt = rb_ary_elt(ary, i);
5552 for (j = 0; j < argc; j++) {
5553 if (is_hash[j]) {
5554 if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
5555 break;
5557 else {
5558 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5561 if (j == argc) rb_ary_push(ary_diff, elt);
5564 ALLOCV_END(t0);
5566 return ary_diff;
5571 * call-seq:
5572 * self & other_array -> new_array
5574 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5575 * that is, containing those elements found in both +self+ and +other_array+:
5577 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5579 * Omits duplicates:
5581 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5583 * Preserves order from +self+:
5585 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5587 * Identifies common elements using method <tt>#eql?</tt>
5588 * (as defined in each element of +self+).
5590 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5594 static VALUE
5595 rb_ary_and(VALUE ary1, VALUE ary2)
5597 VALUE hash, ary3, v;
5598 st_data_t vv;
5599 long i;
5601 ary2 = to_ary(ary2);
5602 ary3 = rb_ary_new();
5603 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5605 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5606 for (i=0; i<RARRAY_LEN(ary1); i++) {
5607 v = RARRAY_AREF(ary1, i);
5608 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5609 if (rb_ary_includes_by_eql(ary3, v)) continue;
5610 rb_ary_push(ary3, v);
5612 return ary3;
5615 hash = ary_make_hash(ary2);
5617 for (i=0; i<RARRAY_LEN(ary1); i++) {
5618 v = RARRAY_AREF(ary1, i);
5619 vv = (st_data_t)v;
5620 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5621 rb_ary_push(ary3, v);
5625 return ary3;
5629 * call-seq:
5630 * intersection(*other_arrays) -> new_array
5632 * Returns a new array containing each element in +self+ that is +#eql?+
5633 * to at least one element in each of the given +other_arrays+;
5634 * duplicates are omitted:
5636 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5638 * Each element must correctly implement method <tt>#hash</tt>.
5640 * Order from +self+ is preserved:
5642 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5644 * Returns a copy of +self+ if no arguments are given.
5646 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5649 static VALUE
5650 rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5652 VALUE result = rb_ary_dup(ary);
5653 int i;
5655 for (i = 0; i < argc; i++) {
5656 result = rb_ary_and(result, argv[i]);
5659 return result;
5662 static int
5663 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5665 if (existing) return ST_STOP;
5666 *key = *value = (VALUE)arg;
5667 return ST_CONTINUE;
5670 static void
5671 rb_ary_union(VALUE ary_union, VALUE ary)
5673 long i;
5674 for (i = 0; i < RARRAY_LEN(ary); i++) {
5675 VALUE elt = rb_ary_elt(ary, i);
5676 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5677 rb_ary_push(ary_union, elt);
5681 static void
5682 rb_ary_union_hash(VALUE hash, VALUE ary2)
5684 long i;
5685 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5686 VALUE elt = RARRAY_AREF(ary2, i);
5687 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5688 RB_OBJ_WRITTEN(hash, Qundef, elt);
5694 * call-seq:
5695 * array | other_array -> new_array
5697 * Returns the union of +array+ and +Array+ +other_array+;
5698 * duplicates are removed; order is preserved;
5699 * items are compared using <tt>eql?</tt>:
5701 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5702 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5703 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5705 * Related: Array#union.
5708 static VALUE
5709 rb_ary_or(VALUE ary1, VALUE ary2)
5711 VALUE hash;
5713 ary2 = to_ary(ary2);
5714 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5715 VALUE ary3 = rb_ary_new();
5716 rb_ary_union(ary3, ary1);
5717 rb_ary_union(ary3, ary2);
5718 return ary3;
5721 hash = ary_make_hash(ary1);
5722 rb_ary_union_hash(hash, ary2);
5724 return rb_hash_values(hash);
5728 * call-seq:
5729 * array.union(*other_arrays) -> new_array
5731 * Returns a new +Array+ that is the union of +self+ and all given Arrays +other_arrays+;
5732 * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
5734 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5735 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5736 * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
5738 * Returns a copy of +self+ if no arguments given.
5740 * Related: Array#|.
5743 static VALUE
5744 rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
5746 int i;
5747 long sum;
5748 VALUE hash;
5750 sum = RARRAY_LEN(ary);
5751 for (i = 0; i < argc; i++) {
5752 argv[i] = to_ary(argv[i]);
5753 sum += RARRAY_LEN(argv[i]);
5756 if (sum <= SMALL_ARRAY_LEN) {
5757 VALUE ary_union = rb_ary_new();
5759 rb_ary_union(ary_union, ary);
5760 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5762 return ary_union;
5765 hash = ary_make_hash(ary);
5766 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5768 return rb_hash_values(hash);
5772 * call-seq:
5773 * intersect?(other_array) -> true or false
5775 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5777 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5778 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5780 * Each element must correctly implement method <tt>#hash</tt>.
5782 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5785 static VALUE
5786 rb_ary_intersect_p(VALUE ary1, VALUE ary2)
5788 VALUE hash, v, result, shorter, longer;
5789 st_data_t vv;
5790 long i;
5792 ary2 = to_ary(ary2);
5793 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
5795 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5796 for (i=0; i<RARRAY_LEN(ary1); i++) {
5797 v = RARRAY_AREF(ary1, i);
5798 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
5800 return Qfalse;
5803 shorter = ary1;
5804 longer = ary2;
5805 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
5806 longer = ary1;
5807 shorter = ary2;
5810 hash = ary_make_hash(shorter);
5811 result = Qfalse;
5813 for (i=0; i<RARRAY_LEN(longer); i++) {
5814 v = RARRAY_AREF(longer, i);
5815 vv = (st_data_t)v;
5816 if (rb_hash_stlike_lookup(hash, vv, 0)) {
5817 result = Qtrue;
5818 break;
5822 return result;
5825 static VALUE
5826 ary_max_generic(VALUE ary, long i, VALUE vmax)
5828 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5830 VALUE v;
5831 for (; i < RARRAY_LEN(ary); ++i) {
5832 v = RARRAY_AREF(ary, i);
5834 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
5835 vmax = v;
5839 return vmax;
5842 static VALUE
5843 ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
5845 const long n = RARRAY_LEN(ary);
5846 RUBY_ASSERT(i > 0 && i < n);
5847 RUBY_ASSERT(FIXNUM_P(vmax));
5849 VALUE v;
5850 for (; i < n; ++i) {
5851 v = RARRAY_AREF(ary, i);
5853 if (FIXNUM_P(v)) {
5854 if ((long)vmax < (long)v) {
5855 vmax = v;
5858 else {
5859 return ary_max_generic(ary, i, vmax);
5863 return vmax;
5866 static VALUE
5867 ary_max_opt_float(VALUE ary, long i, VALUE vmax)
5869 const long n = RARRAY_LEN(ary);
5870 RUBY_ASSERT(i > 0 && i < n);
5871 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax));
5873 VALUE v;
5874 for (; i < n; ++i) {
5875 v = RARRAY_AREF(ary, i);
5877 if (RB_FLOAT_TYPE_P(v)) {
5878 if (rb_float_cmp(vmax, v) < 0) {
5879 vmax = v;
5882 else {
5883 return ary_max_generic(ary, i, vmax);
5887 return vmax;
5890 static VALUE
5891 ary_max_opt_string(VALUE ary, long i, VALUE vmax)
5893 const long n = RARRAY_LEN(ary);
5894 RUBY_ASSERT(i > 0 && i < n);
5895 RUBY_ASSERT(STRING_P(vmax));
5897 VALUE v;
5898 for (; i < n; ++i) {
5899 v = RARRAY_AREF(ary, i);
5901 if (STRING_P(v)) {
5902 if (rb_str_cmp(vmax, v) < 0) {
5903 vmax = v;
5906 else {
5907 return ary_max_generic(ary, i, vmax);
5911 return vmax;
5915 * call-seq:
5916 * max -> element
5917 * max(n) -> new_array
5918 * max {|a, b| ... } -> element
5919 * max(n) {|a, b| ... } -> new_array
5921 * Returns one of the following:
5923 * - The maximum-valued element from +self+.
5924 * - A new array of maximum-valued elements from +self+.
5926 * Does not modify +self+.
5928 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
5929 * with a numeric.
5931 * With no argument and no block, returns the element in +self+
5932 * having the maximum value per method <tt>#<=></tt>:
5934 * [1, 0, 3, 2].max # => 3
5936 * With non-negative numeric argument +n+ and no block,
5937 * returns a new array with at most +n+ elements,
5938 * in descending order, per method <tt>#<=></tt>:
5940 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
5941 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
5942 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
5943 * [1, 0, 3, 2].max(0) # => []
5945 * With a block given, the block must return a numeric.
5947 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
5948 * returns the element having the maximum value per the block:
5950 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
5951 * # => "000"
5953 * With non-negative numeric argument +n+ and a block,
5954 * returns a new array with at most +n+ elements,
5955 * in descending order, per the block:
5957 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
5958 * # => ["000", "00"]
5960 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5962 static VALUE
5963 rb_ary_max(int argc, VALUE *argv, VALUE ary)
5965 VALUE result = Qundef, v;
5966 VALUE num;
5967 long i;
5969 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
5970 return rb_nmin_run(ary, num, 0, 1, 1);
5972 const long n = RARRAY_LEN(ary);
5973 if (rb_block_given_p()) {
5974 for (i = 0; i < RARRAY_LEN(ary); i++) {
5975 v = RARRAY_AREF(ary, i);
5976 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
5977 result = v;
5981 else if (n > 0) {
5982 result = RARRAY_AREF(ary, 0);
5983 if (n > 1) {
5984 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
5985 return ary_max_opt_fixnum(ary, 1, result);
5987 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
5988 return ary_max_opt_string(ary, 1, result);
5990 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
5991 return ary_max_opt_float(ary, 1, result);
5993 else {
5994 return ary_max_generic(ary, 1, result);
5998 if (UNDEF_P(result)) return Qnil;
5999 return result;
6002 static VALUE
6003 ary_min_generic(VALUE ary, long i, VALUE vmin)
6005 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6007 VALUE v;
6008 for (; i < RARRAY_LEN(ary); ++i) {
6009 v = RARRAY_AREF(ary, i);
6011 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
6012 vmin = v;
6016 return vmin;
6019 static VALUE
6020 ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
6022 const long n = RARRAY_LEN(ary);
6023 RUBY_ASSERT(i > 0 && i < n);
6024 RUBY_ASSERT(FIXNUM_P(vmin));
6026 VALUE a;
6027 for (; i < n; ++i) {
6028 a = RARRAY_AREF(ary, i);
6030 if (FIXNUM_P(a)) {
6031 if ((long)vmin > (long)a) {
6032 vmin = a;
6035 else {
6036 return ary_min_generic(ary, i, vmin);
6040 return vmin;
6043 static VALUE
6044 ary_min_opt_float(VALUE ary, long i, VALUE vmin)
6046 const long n = RARRAY_LEN(ary);
6047 RUBY_ASSERT(i > 0 && i < n);
6048 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin));
6050 VALUE a;
6051 for (; i < n; ++i) {
6052 a = RARRAY_AREF(ary, i);
6054 if (RB_FLOAT_TYPE_P(a)) {
6055 if (rb_float_cmp(vmin, a) > 0) {
6056 vmin = a;
6059 else {
6060 return ary_min_generic(ary, i, vmin);
6064 return vmin;
6067 static VALUE
6068 ary_min_opt_string(VALUE ary, long i, VALUE vmin)
6070 const long n = RARRAY_LEN(ary);
6071 RUBY_ASSERT(i > 0 && i < n);
6072 RUBY_ASSERT(STRING_P(vmin));
6074 VALUE a;
6075 for (; i < n; ++i) {
6076 a = RARRAY_AREF(ary, i);
6078 if (STRING_P(a)) {
6079 if (rb_str_cmp(vmin, a) > 0) {
6080 vmin = a;
6083 else {
6084 return ary_min_generic(ary, i, vmin);
6088 return vmin;
6092 * call-seq:
6093 * min -> element
6094 * min(n) -> new_array
6095 * min {|a, b| ... } -> element
6096 * min(n) {|a, b| ... } -> new_array
6098 * Returns one of the following:
6100 * - The minimum-valued element from +self+.
6101 * - A new array of minimum-valued elements from +self+.
6103 * Does not modify +self+.
6105 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6106 * with a numeric.
6108 * With no argument and no block, returns the element in +self+
6109 * having the minimum value per method <tt>#<=></tt>:
6111 * [1, 0, 3, 2].min # => 0
6113 * With non-negative numeric argument +n+ and no block,
6114 * returns a new array with at most +n+ elements,
6115 * in ascending order, per method <tt>#<=></tt>:
6117 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6118 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6119 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6120 * [1, 0, 3, 2].min(0) # => []
6122 * With a block given, the block must return a numeric.
6124 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6125 * returns the element having the minimum value per the block:
6127 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6128 * # => ""
6130 * With non-negative numeric argument +n+ and a block,
6131 * returns a new array with at most +n+ elements,
6132 * in ascending order, per the block:
6134 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6135 * # => ["", "0"]
6137 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6139 static VALUE
6140 rb_ary_min(int argc, VALUE *argv, VALUE ary)
6142 VALUE result = Qundef, v;
6143 VALUE num;
6144 long i;
6146 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6147 return rb_nmin_run(ary, num, 0, 0, 1);
6149 const long n = RARRAY_LEN(ary);
6150 if (rb_block_given_p()) {
6151 for (i = 0; i < RARRAY_LEN(ary); i++) {
6152 v = RARRAY_AREF(ary, i);
6153 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6154 result = v;
6158 else if (n > 0) {
6159 result = RARRAY_AREF(ary, 0);
6160 if (n > 1) {
6161 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6162 return ary_min_opt_fixnum(ary, 1, result);
6164 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6165 return ary_min_opt_string(ary, 1, result);
6167 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6168 return ary_min_opt_float(ary, 1, result);
6170 else {
6171 return ary_min_generic(ary, 1, result);
6175 if (UNDEF_P(result)) return Qnil;
6176 return result;
6180 * call-seq:
6181 * minmax -> array
6182 * minmax {|a, b| ... } -> array
6184 * Returns a 2-element array containing the minimum-valued and maximum-valued
6185 * elements from +self+;
6186 * does not modify +self+.
6188 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6190 * [1, 0, 3, 2].minmax # => [0, 3]
6192 * With a block given, the block must return a numeric;
6193 * the block is called <tt>self.size - 1</tt> times to compare elements;
6194 * returns the elements having the minimum and maximum values per the block:
6196 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6197 * # => ["", "000"]
6199 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6201 static VALUE
6202 rb_ary_minmax(VALUE ary)
6204 if (rb_block_given_p()) {
6205 return rb_call_super(0, NULL);
6207 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6210 static int
6211 push_value(st_data_t key, st_data_t val, st_data_t ary)
6213 rb_ary_push((VALUE)ary, (VALUE)val);
6214 return ST_CONTINUE;
6218 * call-seq:
6219 * array.uniq! -> self or nil
6220 * array.uniq! {|element| ... } -> self or nil
6222 * Removes duplicate elements from +self+, the first occurrence always being retained;
6223 * returns +self+ if any elements removed, +nil+ otherwise.
6225 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6226 * to compare.
6228 * Returns +self+ if any elements removed:
6230 * a = [0, 0, 1, 1, 2, 2]
6231 * a.uniq! # => [0, 1, 2]
6233 * Returns +nil+ if no elements removed.
6235 * With a block given, calls the block for each element;
6236 * identifies (using method <tt>eql?</tt>) and removes
6237 * elements for which the block returns duplicate values.
6239 * Returns +self+ if any elements removed:
6241 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6242 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
6244 * Returns +nil+ if no elements removed.
6246 static VALUE
6247 rb_ary_uniq_bang(VALUE ary)
6249 VALUE hash;
6250 long hash_size;
6252 rb_ary_modify_check(ary);
6253 if (RARRAY_LEN(ary) <= 1)
6254 return Qnil;
6255 if (rb_block_given_p())
6256 hash = ary_make_hash_by(ary);
6257 else
6258 hash = ary_make_hash(ary);
6260 hash_size = RHASH_SIZE(hash);
6261 if (RARRAY_LEN(ary) == hash_size) {
6262 return Qnil;
6264 rb_ary_modify_check(ary);
6265 ARY_SET_LEN(ary, 0);
6266 if (ARY_SHARED_P(ary)) {
6267 rb_ary_unshare(ary);
6268 FL_SET_EMBED(ary);
6270 ary_resize_capa(ary, hash_size);
6271 rb_hash_foreach(hash, push_value, ary);
6273 return ary;
6277 * call-seq:
6278 * array.uniq -> new_array
6279 * array.uniq {|element| ... } -> new_array
6281 * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
6282 * the first occurrence always being retained.
6284 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
6285 * to compare:
6287 * a = [0, 0, 1, 1, 2, 2]
6288 * a.uniq # => [0, 1, 2]
6290 * With a block given, calls the block for each element;
6291 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
6292 * that is, those elements for which the block returns the same value:
6294 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6295 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6299 static VALUE
6300 rb_ary_uniq(VALUE ary)
6302 VALUE hash, uniq;
6304 if (RARRAY_LEN(ary) <= 1) {
6305 hash = 0;
6306 uniq = rb_ary_dup(ary);
6308 else if (rb_block_given_p()) {
6309 hash = ary_make_hash_by(ary);
6310 uniq = rb_hash_values(hash);
6312 else {
6313 hash = ary_make_hash(ary);
6314 uniq = rb_hash_values(hash);
6317 return uniq;
6321 * call-seq:
6322 * compact! -> self or nil
6324 * Removes all +nil+ elements from +self+;
6325 * Returns +self+ if any elements are removed, +nil+ otherwise:
6327 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6328 * a.compact! # => [0, false, "", [], {}]
6329 * a # => [0, false, "", [], {}]
6330 * a.compact! # => nil
6332 * Related: Array#compact;
6333 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6336 static VALUE
6337 rb_ary_compact_bang(VALUE ary)
6339 VALUE *p, *t, *end;
6340 long n;
6342 rb_ary_modify(ary);
6343 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6344 end = p + RARRAY_LEN(ary);
6346 while (t < end) {
6347 if (NIL_P(*t)) t++;
6348 else *p++ = *t++;
6350 n = p - RARRAY_CONST_PTR(ary);
6351 if (RARRAY_LEN(ary) == n) {
6352 return Qnil;
6354 ary_resize_smaller(ary, n);
6356 return ary;
6360 * call-seq:
6361 * compact -> new_array
6363 * Returns a new array containing only the non-+nil+ elements from +self+;
6364 * element order is preserved:
6366 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6367 * a.compact # => [0, false, "", [], {}]
6369 * Related: Array#compact!;
6370 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6373 static VALUE
6374 rb_ary_compact(VALUE ary)
6376 ary = rb_ary_dup(ary);
6377 rb_ary_compact_bang(ary);
6378 return ary;
6382 * call-seq:
6383 * count -> integer
6384 * count(object) -> integer
6385 * count {|element| ... } -> integer
6387 * Returns a count of specified elements.
6389 * With no argument and no block, returns the count of all elements:
6391 * [0, :one, 'two', 3, 3.0].count # => 5
6393 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6395 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6397 * With no argument and a block given, calls the block with each element;
6398 * returns the count of elements for which the block returns a truthy value:
6400 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6402 * With argument +object+ and a block given, issues a warning, ignores the block,
6403 * and returns the count of elements <tt>==</tt> to +object+.
6405 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6408 static VALUE
6409 rb_ary_count(int argc, VALUE *argv, VALUE ary)
6411 long i, n = 0;
6413 if (rb_check_arity(argc, 0, 1) == 0) {
6414 VALUE v;
6416 if (!rb_block_given_p())
6417 return LONG2NUM(RARRAY_LEN(ary));
6419 for (i = 0; i < RARRAY_LEN(ary); i++) {
6420 v = RARRAY_AREF(ary, i);
6421 if (RTEST(rb_yield(v))) n++;
6424 else {
6425 VALUE obj = argv[0];
6427 if (rb_block_given_p()) {
6428 rb_warn("given block not used");
6430 for (i = 0; i < RARRAY_LEN(ary); i++) {
6431 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6435 return LONG2NUM(n);
6438 static VALUE
6439 flatten(VALUE ary, int level)
6441 long i;
6442 VALUE stack, result, tmp = 0, elt;
6443 VALUE memo = Qfalse;
6445 for (i = 0; i < RARRAY_LEN(ary); i++) {
6446 elt = RARRAY_AREF(ary, i);
6447 tmp = rb_check_array_type(elt);
6448 if (!NIL_P(tmp)) {
6449 break;
6452 if (i == RARRAY_LEN(ary)) {
6453 return ary;
6456 result = ary_new(0, RARRAY_LEN(ary));
6457 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6458 ARY_SET_LEN(result, i);
6460 stack = ary_new(0, ARY_DEFAULT_SIZE);
6461 rb_ary_push(stack, ary);
6462 rb_ary_push(stack, LONG2NUM(i + 1));
6464 if (level < 0) {
6465 memo = rb_obj_hide(rb_ident_hash_new());
6466 rb_hash_aset(memo, ary, Qtrue);
6467 rb_hash_aset(memo, tmp, Qtrue);
6470 ary = tmp;
6471 i = 0;
6473 while (1) {
6474 while (i < RARRAY_LEN(ary)) {
6475 elt = RARRAY_AREF(ary, i++);
6476 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6477 rb_ary_push(result, elt);
6478 continue;
6480 tmp = rb_check_array_type(elt);
6481 if (RBASIC(result)->klass) {
6482 if (RTEST(memo)) {
6483 rb_hash_clear(memo);
6485 rb_raise(rb_eRuntimeError, "flatten reentered");
6487 if (NIL_P(tmp)) {
6488 rb_ary_push(result, elt);
6490 else {
6491 if (memo) {
6492 if (rb_hash_aref(memo, tmp) == Qtrue) {
6493 rb_hash_clear(memo);
6494 rb_raise(rb_eArgError, "tried to flatten recursive array");
6496 rb_hash_aset(memo, tmp, Qtrue);
6498 rb_ary_push(stack, ary);
6499 rb_ary_push(stack, LONG2NUM(i));
6500 ary = tmp;
6501 i = 0;
6504 if (RARRAY_LEN(stack) == 0) {
6505 break;
6507 if (memo) {
6508 rb_hash_delete(memo, ary);
6510 tmp = rb_ary_pop(stack);
6511 i = NUM2LONG(tmp);
6512 ary = rb_ary_pop(stack);
6515 if (memo) {
6516 rb_hash_clear(memo);
6519 RBASIC_SET_CLASS(result, rb_cArray);
6520 return result;
6524 * call-seq:
6525 * flatten!(depth = nil) -> self or nil
6527 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6528 * +depth+ must be an
6529 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6530 * or +nil+.
6531 * At each level of recursion:
6533 * - Each element that is an array is "flattened"
6534 * (that is, replaced by its individual array elements).
6535 * - Each element that is not an array is unchanged
6536 * (even if the element is an object that has instance method +flatten+).
6538 * Returns +nil+ if no elements were flattened.
6540 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6542 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6543 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6544 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6545 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6546 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6547 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6549 * With +nil+ or negative argument +depth+, flattens all levels:
6551 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6552 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6554 * Related: Array#flatten;
6555 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6558 static VALUE
6559 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6561 int mod = 0, level = -1;
6562 VALUE result, lv;
6564 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6565 rb_ary_modify_check(ary);
6566 if (!NIL_P(lv)) level = NUM2INT(lv);
6567 if (level == 0) return Qnil;
6569 result = flatten(ary, level);
6570 if (result == ary) {
6571 return Qnil;
6573 if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6574 rb_ary_replace(ary, result);
6575 if (mod) ARY_SET_EMBED_LEN(result, 0);
6577 return ary;
6581 * call-seq:
6582 * flatten(depth = nil) -> new_array
6584 * Returns a new array that is a recursive flattening of +self+
6585 * to +depth+ levels of recursion;
6586 * +depth+ must be an
6587 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6588 * or +nil+.
6589 * At each level of recursion:
6591 * - Each element that is an array is "flattened"
6592 * (that is, replaced by its individual array elements).
6593 * - Each element that is not an array is unchanged
6594 * (even if the element is an object that has instance method +flatten+).
6596 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6598 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6599 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6600 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6601 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6602 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6603 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6604 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6606 * With +nil+ or negative +depth+, flattens all levels.
6608 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6609 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6611 * Related: Array#flatten!;
6612 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6615 static VALUE
6616 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6618 int level = -1;
6619 VALUE result;
6621 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6622 level = NUM2INT(argv[0]);
6623 if (level == 0) return ary_make_shared_copy(ary);
6626 result = flatten(ary, level);
6627 if (result == ary) {
6628 result = ary_make_shared_copy(ary);
6631 return result;
6634 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6636 static VALUE
6637 rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6639 long i, len;
6641 rb_ary_modify(ary);
6642 i = len = RARRAY_LEN(ary);
6643 RARRAY_PTR_USE(ary, ptr, {
6644 while (i) {
6645 long j = RAND_UPTO(i);
6646 VALUE tmp;
6647 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6648 rb_raise(rb_eRuntimeError, "modified during shuffle");
6650 tmp = ptr[--i];
6651 ptr[i] = ptr[j];
6652 ptr[j] = tmp;
6654 }); /* WB: no new reference */
6655 return ary;
6658 static VALUE
6659 rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6661 ary = rb_ary_dup(ary);
6662 rb_ary_shuffle_bang(ec, ary, randgen);
6663 return ary;
6666 static const rb_data_type_t ary_sample_memo_type = {
6667 .wrap_struct_name = "ary_sample_memo",
6668 .function = {
6669 .dfree = (RUBY_DATA_FUNC)st_free_table,
6671 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
6674 static VALUE
6675 ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6677 VALUE result;
6678 long n, len, i, j, k, idx[10];
6679 long rnds[numberof(idx)];
6680 long memo_threshold;
6682 len = RARRAY_LEN(ary);
6683 if (!to_array) {
6684 if (len < 2)
6685 i = 0;
6686 else
6687 i = RAND_UPTO(len);
6689 return rb_ary_elt(ary, i);
6691 n = NUM2LONG(nv);
6692 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
6693 if (n > len) n = len;
6694 if (n <= numberof(idx)) {
6695 for (i = 0; i < n; ++i) {
6696 rnds[i] = RAND_UPTO(len - i);
6699 k = len;
6700 len = RARRAY_LEN(ary);
6701 if (len < k && n <= numberof(idx)) {
6702 for (i = 0; i < n; ++i) {
6703 if (rnds[i] >= len) return rb_ary_new_capa(0);
6706 if (n > len) n = len;
6707 switch (n) {
6708 case 0:
6709 return rb_ary_new_capa(0);
6710 case 1:
6711 i = rnds[0];
6712 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
6713 case 2:
6714 i = rnds[0];
6715 j = rnds[1];
6716 if (j >= i) j++;
6717 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
6718 case 3:
6719 i = rnds[0];
6720 j = rnds[1];
6721 k = rnds[2];
6723 long l = j, g = i;
6724 if (j >= i) l = i, g = ++j;
6725 if (k >= l && (++k >= g)) ++k;
6727 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
6729 memo_threshold =
6730 len < 2560 ? len / 128 :
6731 len < 5120 ? len / 64 :
6732 len < 10240 ? len / 32 :
6733 len / 16;
6734 if (n <= numberof(idx)) {
6735 long sorted[numberof(idx)];
6736 sorted[0] = idx[0] = rnds[0];
6737 for (i=1; i<n; i++) {
6738 k = rnds[i];
6739 for (j = 0; j < i; ++j) {
6740 if (k < sorted[j]) break;
6741 ++k;
6743 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
6744 sorted[j] = idx[i] = k;
6746 result = rb_ary_new_capa(n);
6747 RARRAY_PTR_USE(result, ptr_result, {
6748 for (i=0; i<n; i++) {
6749 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
6753 else if (n <= memo_threshold / 2) {
6754 long max_idx = 0;
6755 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
6756 st_table *memo = st_init_numtable_with_size(n);
6757 RTYPEDDATA_DATA(vmemo) = memo;
6758 result = rb_ary_new_capa(n);
6759 RARRAY_PTR_USE(result, ptr_result, {
6760 for (i=0; i<n; i++) {
6761 long r = RAND_UPTO(len-i) + i;
6762 ptr_result[i] = r;
6763 if (r > max_idx) max_idx = r;
6765 len = RARRAY_LEN(ary);
6766 if (len <= max_idx) n = 0;
6767 else if (n > len) n = len;
6768 RARRAY_PTR_USE(ary, ptr_ary, {
6769 for (i=0; i<n; i++) {
6770 long j2 = j = ptr_result[i];
6771 long i2 = i;
6772 st_data_t value;
6773 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
6774 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
6775 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6776 ptr_result[i] = ptr_ary[j2];
6780 RTYPEDDATA_DATA(vmemo) = 0;
6781 st_free_table(memo);
6782 RB_GC_GUARD(vmemo);
6784 else {
6785 result = rb_ary_dup(ary);
6786 RBASIC_CLEAR_CLASS(result);
6787 RB_GC_GUARD(ary);
6788 RARRAY_PTR_USE(result, ptr_result, {
6789 for (i=0; i<n; i++) {
6790 j = RAND_UPTO(len-i) + i;
6791 nv = ptr_result[j];
6792 ptr_result[j] = ptr_result[i];
6793 ptr_result[i] = nv;
6796 RBASIC_SET_CLASS_RAW(result, rb_cArray);
6798 ARY_SET_LEN(result, n);
6800 return result;
6803 static VALUE
6804 ary_sample0(rb_execution_context_t *ec, VALUE ary)
6806 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
6809 static VALUE
6810 rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
6812 long mul;
6813 VALUE n = Qnil;
6814 if (args && (RARRAY_LEN(args) > 0)) {
6815 n = RARRAY_AREF(args, 0);
6817 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
6818 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
6819 mul = NUM2LONG(n);
6820 if (mul <= 0) return INT2FIX(0);
6821 n = LONG2FIX(mul);
6822 return rb_fix_mul_fix(rb_ary_length(self), n);
6826 * call-seq:
6827 * cycle(count = nil) {|element| ... } -> nil
6828 * cycle(count = nil) -> new_enumerator
6830 * With a block given, may call the block, depending on the value of argument +count+;
6831 * +count+ must be an
6832 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6833 * or +nil+.
6835 * When +count+ is positive,
6836 * calls the block with each element, then does so repeatedly,
6837 * until it has done so +count+ times; returns +nil+:
6839 * output = []
6840 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6841 * output # => [0, 1, 0, 1]
6843 * When +count+ is zero or negative, does not call the block:
6845 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6846 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6848 * When +count+ is +nil+, cycles forever:
6850 * # Prints 0 and 1 forever.
6851 * [0, 1].cycle {|element| puts element }
6852 * [0, 1].cycle(nil) {|element| puts element }
6854 * With no block given, returns a new Enumerator.
6856 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6858 static VALUE
6859 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
6861 long n, i;
6863 rb_check_arity(argc, 0, 1);
6865 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
6866 if (argc == 0 || NIL_P(argv[0])) {
6867 n = -1;
6869 else {
6870 n = NUM2LONG(argv[0]);
6871 if (n <= 0) return Qnil;
6874 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
6875 for (i=0; i<RARRAY_LEN(ary); i++) {
6876 rb_yield(RARRAY_AREF(ary, i));
6879 return Qnil;
6883 * Build a ruby array of the corresponding values and yield it to the
6884 * associated block.
6885 * Return the class of +values+ for reentry check.
6887 static int
6888 yield_indexed_values(const VALUE values, const long r, const long *const p)
6890 const VALUE result = rb_ary_new2(r);
6891 long i;
6893 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
6894 ARY_SET_LEN(result, r);
6895 rb_yield(result);
6896 return !RBASIC(values)->klass;
6900 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6902 * When we have a complete permutation of array indices, copy the values
6903 * at those indices into a new array and yield that array.
6905 * n: the size of the set
6906 * r: the number of elements in each permutation
6907 * p: the array (of size r) that we're filling in
6908 * used: an array of booleans: whether a given index is already used
6909 * values: the Ruby array that holds the actual values to permute
6911 static void
6912 permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
6914 long i = 0, index = 0;
6916 for (;;) {
6917 const char *const unused = memchr(&used[i], 0, n-i);
6918 if (!unused) {
6919 if (!index) break;
6920 i = p[--index]; /* pop index */
6921 used[i++] = 0; /* index unused */
6923 else {
6924 i = unused - used;
6925 p[index] = i;
6926 used[i] = 1; /* mark index used */
6927 ++index;
6928 if (index < r-1) { /* if not done yet */
6929 p[index] = i = 0;
6930 continue;
6932 for (i = 0; i < n; ++i) {
6933 if (used[i]) continue;
6934 p[index] = i;
6935 if (!yield_indexed_values(values, r, p)) {
6936 rb_raise(rb_eRuntimeError, "permute reentered");
6939 i = p[--index]; /* pop index */
6940 used[i] = 0; /* index unused */
6941 p[index] = ++i;
6947 * Returns the product of from, from-1, ..., from - how_many + 1.
6948 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6950 static VALUE
6951 descending_factorial(long from, long how_many)
6953 VALUE cnt;
6954 if (how_many > 0) {
6955 cnt = LONG2FIX(from);
6956 while (--how_many > 0) {
6957 long v = --from;
6958 cnt = rb_int_mul(cnt, LONG2FIX(v));
6961 else {
6962 cnt = LONG2FIX(how_many == 0);
6964 return cnt;
6967 static VALUE
6968 binomial_coefficient(long comb, long size)
6970 VALUE r;
6971 long i;
6972 if (comb > size-comb) {
6973 comb = size-comb;
6975 if (comb < 0) {
6976 return LONG2FIX(0);
6978 else if (comb == 0) {
6979 return LONG2FIX(1);
6981 r = LONG2FIX(size);
6982 for (i = 1; i < comb; ++i) {
6983 r = rb_int_mul(r, LONG2FIX(size - i));
6984 r = rb_int_idiv(r, LONG2FIX(i + 1));
6986 return r;
6989 static VALUE
6990 rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
6992 long n = RARRAY_LEN(ary);
6993 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
6995 return descending_factorial(n, k);
6999 * call-seq:
7000 * permutation(n = self.size) {|permutation| ... } -> self
7001 * permutation(n = self.size) -> new_enumerator
7003 * Iterates over permutations of the elements of +self+;
7004 * the order of permutations is indeterminate.
7006 * With a block and an in-range positive integer argument +n+ (<tt>0 < n <= self.size</tt>) given,
7007 * calls the block with each +n+-tuple permutations of +self+;
7008 * returns +self+:
7010 * a = [0, 1, 2]
7011 * perms = []
7012 * a.permutation(1) {|perm| perms.push(perm) }
7013 * perms # => [[0], [1], [2]]
7015 * perms = []
7016 * a.permutation(2) {|perm| perms.push(perm) }
7017 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7019 * perms = []
7020 * a.permutation(3) {|perm| perms.push(perm) }
7021 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7023 * When +n+ is zero, calls the block once with a new empty array:
7025 * perms = []
7026 * a.permutation(0) {|perm| perms.push(perm) }
7027 * perms # => [[]]
7029 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
7030 * does not call the block:
7032 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7033 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7035 * With no block given, returns a new Enumerator.
7037 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7040 static VALUE
7041 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
7043 long r, n, i;
7045 n = RARRAY_LEN(ary); /* Array length */
7046 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
7047 r = n;
7048 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
7049 r = NUM2LONG(argv[0]); /* Permutation size from argument */
7051 if (r < 0 || n < r) {
7052 /* no permutations: yield nothing */
7054 else if (r == 0) { /* exactly one permutation: the zero-length array */
7055 rb_yield(rb_ary_new2(0));
7057 else if (r == 1) { /* this is a special, easy case */
7058 for (i = 0; i < RARRAY_LEN(ary); i++) {
7059 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7062 else { /* this is the general case */
7063 volatile VALUE t0;
7064 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
7065 char *used = (char*)(p + r);
7066 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7067 RBASIC_CLEAR_CLASS(ary0);
7069 MEMZERO(used, char, n); /* initialize array */
7071 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7072 ALLOCV_END(t0);
7073 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7075 return ary;
7078 static void
7079 combinate0(const long len, const long n, long *const stack, const VALUE values)
7081 long lev = 0;
7083 MEMZERO(stack+1, long, n);
7084 stack[0] = -1;
7085 for (;;) {
7086 for (lev++; lev < n; lev++) {
7087 stack[lev+1] = stack[lev]+1;
7089 if (!yield_indexed_values(values, n, stack+1)) {
7090 rb_raise(rb_eRuntimeError, "combination reentered");
7092 do {
7093 if (lev == 0) return;
7094 stack[lev--]++;
7095 } while (stack[lev+1]+n == len+lev+1);
7099 static VALUE
7100 rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7102 long n = RARRAY_LEN(ary);
7103 long k = NUM2LONG(RARRAY_AREF(args, 0));
7105 return binomial_coefficient(k, n);
7109 * call-seq:
7110 * combination(n) {|element| ... } -> self
7111 * combination(n) -> new_enumerator
7113 * When a block and a positive
7114 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7115 * argument +n+ (<tt>0 < n <= self.size</tt>)
7116 * are given, calls the block with all +n+-tuple combinations of +self+;
7117 * returns +self+:
7119 * a = %w[a b c] # => ["a", "b", "c"]
7120 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7122 * Output:
7124 * ["a", "b"]
7125 * ["a", "c"]
7126 * ["b", "c"]
7128 * The order of the yielded combinations is not guaranteed.
7130 * When +n+ is zero, calls the block once with a new empty array:
7132 * a.combination(0) {|combination| p combination }
7133 * [].combination(0) {|combination| p combination }
7135 * Output:
7137 * []
7138 * []
7140 * When +n+ is negative or larger than +self.size+ and +self+ is non-empty,
7141 * does not call the block:
7143 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7144 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7146 * With no block given, returns a new Enumerator.
7148 * Related: Array#permutation;
7149 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7152 static VALUE
7153 rb_ary_combination(VALUE ary, VALUE num)
7155 long i, n, len;
7157 n = NUM2LONG(num);
7158 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7159 len = RARRAY_LEN(ary);
7160 if (n < 0 || len < n) {
7161 /* yield nothing */
7163 else if (n == 0) {
7164 rb_yield(rb_ary_new2(0));
7166 else if (n == 1) {
7167 for (i = 0; i < RARRAY_LEN(ary); i++) {
7168 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7171 else {
7172 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7173 volatile VALUE t0;
7174 long *stack = ALLOCV_N(long, t0, n+1);
7176 RBASIC_CLEAR_CLASS(ary0);
7177 combinate0(len, n, stack, ary0);
7178 ALLOCV_END(t0);
7179 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7181 return ary;
7185 * Compute repeated permutations of +r+ elements of the set
7186 * <code>[0..n-1]</code>.
7188 * When we have a complete repeated permutation of array indices, copy the
7189 * values at those indices into a new array and yield that array.
7191 * n: the size of the set
7192 * r: the number of elements in each permutation
7193 * p: the array (of size r) that we're filling in
7194 * values: the Ruby array that holds the actual values to permute
7196 static void
7197 rpermute0(const long n, const long r, long *const p, const VALUE values)
7199 long i = 0, index = 0;
7201 p[index] = i;
7202 for (;;) {
7203 if (++index < r-1) {
7204 p[index] = i = 0;
7205 continue;
7207 for (i = 0; i < n; ++i) {
7208 p[index] = i;
7209 if (!yield_indexed_values(values, r, p)) {
7210 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7213 do {
7214 if (index <= 0) return;
7215 } while ((i = ++p[--index]) >= n);
7219 static VALUE
7220 rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7222 long n = RARRAY_LEN(ary);
7223 long k = NUM2LONG(RARRAY_AREF(args, 0));
7225 if (k < 0) {
7226 return LONG2FIX(0);
7228 if (n <= 0) {
7229 return LONG2FIX(!k);
7231 return rb_int_positive_pow(n, (unsigned long)k);
7235 * call-seq:
7236 * array.repeated_permutation(n) {|permutation| ... } -> self
7237 * array.repeated_permutation(n) -> new_enumerator
7239 * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
7240 * each permutation is an +Array+;
7241 * returns +self+. The order of the permutations is indeterminate.
7243 * When a block and a positive Integer argument +n+ are given, calls the block with each
7244 * +n+-tuple repeated permutation of the elements of +self+.
7245 * The number of permutations is <tt>self.size**n</tt>.
7247 * +n+ = 1:
7249 * a = [0, 1, 2]
7250 * a.repeated_permutation(1) {|permutation| p permutation }
7252 * Output:
7254 * [0]
7255 * [1]
7256 * [2]
7258 * +n+ = 2:
7260 * a.repeated_permutation(2) {|permutation| p permutation }
7262 * Output:
7264 * [0, 0]
7265 * [0, 1]
7266 * [0, 2]
7267 * [1, 0]
7268 * [1, 1]
7269 * [1, 2]
7270 * [2, 0]
7271 * [2, 1]
7272 * [2, 2]
7274 * If +n+ is zero, calls the block once with an empty +Array+.
7276 * If +n+ is negative, does not call the block:
7278 * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7280 * Returns a new Enumerator if no block given:
7282 * a = [0, 1, 2]
7283 * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
7285 * Using Enumerators, it's convenient to show the permutations and counts
7286 * for some values of +n+:
7288 * e = a.repeated_permutation(0)
7289 * e.size # => 1
7290 * e.to_a # => [[]]
7291 * e = a.repeated_permutation(1)
7292 * e.size # => 3
7293 * e.to_a # => [[0], [1], [2]]
7294 * e = a.repeated_permutation(2)
7295 * e.size # => 9
7296 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7299 static VALUE
7300 rb_ary_repeated_permutation(VALUE ary, VALUE num)
7302 long r, n, i;
7304 n = RARRAY_LEN(ary); /* Array length */
7305 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7306 r = NUM2LONG(num); /* Permutation size from argument */
7308 if (r < 0) {
7309 /* no permutations: yield nothing */
7311 else if (r == 0) { /* exactly one permutation: the zero-length array */
7312 rb_yield(rb_ary_new2(0));
7314 else if (r == 1) { /* this is a special, easy case */
7315 for (i = 0; i < RARRAY_LEN(ary); i++) {
7316 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7319 else { /* this is the general case */
7320 volatile VALUE t0;
7321 long *p = ALLOCV_N(long, t0, r);
7322 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7323 RBASIC_CLEAR_CLASS(ary0);
7325 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7326 ALLOCV_END(t0);
7327 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7329 return ary;
7332 static void
7333 rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7335 long i = 0, index = 0;
7337 p[index] = i;
7338 for (;;) {
7339 if (++index < r-1) {
7340 p[index] = i;
7341 continue;
7343 for (; i < n; ++i) {
7344 p[index] = i;
7345 if (!yield_indexed_values(values, r, p)) {
7346 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7349 do {
7350 if (index <= 0) return;
7351 } while ((i = ++p[--index]) >= n);
7355 static VALUE
7356 rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7358 long n = RARRAY_LEN(ary);
7359 long k = NUM2LONG(RARRAY_AREF(args, 0));
7360 if (k == 0) {
7361 return LONG2FIX(1);
7363 return binomial_coefficient(k, n + k - 1);
7367 * call-seq:
7368 * repeated_combination(size) {|combination| ... } -> self
7369 * repeated_combination(size) -> new_enumerator
7371 * With a block given, calls the block with each repeated combination of length +size+
7372 * of the elements of +self+;
7373 * each combination is an array;
7374 * returns +self+. The order of the combinations is indeterminate.
7376 * If a positive integer argument +size+ is given,
7377 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7378 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7380 * Examples:
7382 * - +size+ is 1:
7384 * c = []
7385 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7386 * c # => [[0], [1], [2]]
7388 * - +size+ is 2:
7390 * c = []
7391 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7392 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7394 * If +size+ is zero, calls the block once with an empty array.
7396 * If +size+ is negative, does not call the block:
7398 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7400 * With no block given, returns a new Enumerator.
7402 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7405 static VALUE
7406 rb_ary_repeated_combination(VALUE ary, VALUE num)
7408 long n, i, len;
7410 n = NUM2LONG(num); /* Combination size from argument */
7411 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7412 len = RARRAY_LEN(ary);
7413 if (n < 0) {
7414 /* yield nothing */
7416 else if (n == 0) {
7417 rb_yield(rb_ary_new2(0));
7419 else if (n == 1) {
7420 for (i = 0; i < RARRAY_LEN(ary); i++) {
7421 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7424 else if (len == 0) {
7425 /* yield nothing */
7427 else {
7428 volatile VALUE t0;
7429 long *p = ALLOCV_N(long, t0, n);
7430 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7431 RBASIC_CLEAR_CLASS(ary0);
7433 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7434 ALLOCV_END(t0);
7435 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7437 return ary;
7441 * call-seq:
7442 * product(*other_arrays) -> new_array
7443 * product(*other_arrays) {|combination| ... } -> self
7445 * Computes all combinations of elements from all the arrays,
7446 * including both +self+ and +other_arrays+:
7448 * - The number of combinations is the product of the sizes of all the arrays,
7449 * including both +self+ and +other_arrays+.
7450 * - The order of the returned combinations is indeterminate.
7452 * With no block given, returns the combinations as an array of arrays:
7454 * p = [0, 1].product([2, 3])
7455 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7456 * p.size # => 4
7457 * p = [0, 1].product([2, 3], [4, 5])
7458 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7459 * p.size # => 8
7461 * If +self+ or any argument is empty, returns an empty array:
7463 * [].product([2, 3], [4, 5]) # => []
7464 * [0, 1].product([2, 3], []) # => []
7466 * If no argument is given, returns an array of 1-element arrays,
7467 * each containing an element of +self+:
7469 * a.product # => [[0], [1], [2]]
7471 * With a block given, calls the block with each combination; returns +self+:
7473 * p = []
7474 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7475 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7477 * If +self+ or any argument is empty, does not call the block:
7479 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7480 * # => []
7481 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7482 * # => [0, 1]
7484 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7486 * p = []
7487 * [0, 1].product {|combination| p.push(combination) }
7488 * p # => [[0], [1]]
7490 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7493 static VALUE
7494 rb_ary_product(int argc, VALUE *argv, VALUE ary)
7496 int n = argc+1; /* How many arrays we're operating on */
7497 volatile VALUE t0 = rb_ary_hidden_new(n);
7498 volatile VALUE t1 = Qundef;
7499 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7500 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7501 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7502 long i,j;
7503 long resultlen = 1;
7505 RBASIC_CLEAR_CLASS(t0);
7507 /* initialize the arrays of arrays */
7508 ARY_SET_LEN(t0, n);
7509 arrays[0] = ary;
7510 for (i = 1; i < n; i++) arrays[i] = Qnil;
7511 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7513 /* initialize the counters for the arrays */
7514 for (i = 0; i < n; i++) counters[i] = 0;
7516 /* Otherwise, allocate and fill in an array of results */
7517 if (rb_block_given_p()) {
7518 /* Make defensive copies of arrays; exit if any is empty */
7519 for (i = 0; i < n; i++) {
7520 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7521 arrays[i] = ary_make_shared_copy(arrays[i]);
7524 else {
7525 /* Compute the length of the result array; return [] if any is empty */
7526 for (i = 0; i < n; i++) {
7527 long k = RARRAY_LEN(arrays[i]);
7528 if (k == 0) {
7529 result = rb_ary_new2(0);
7530 goto done;
7532 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7533 rb_raise(rb_eRangeError, "too big to product");
7534 resultlen *= k;
7536 result = rb_ary_new2(resultlen);
7538 for (;;) {
7539 int m;
7540 /* fill in one subarray */
7541 VALUE subarray = rb_ary_new2(n);
7542 for (j = 0; j < n; j++) {
7543 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7546 /* put it on the result array */
7547 if (NIL_P(result)) {
7548 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7549 rb_yield(subarray);
7550 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7551 rb_raise(rb_eRuntimeError, "product reentered");
7553 else {
7554 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7557 else {
7558 rb_ary_push(result, subarray);
7562 * Increment the last counter. If it overflows, reset to 0
7563 * and increment the one before it.
7565 m = n-1;
7566 counters[m]++;
7567 while (counters[m] == RARRAY_LEN(arrays[m])) {
7568 counters[m] = 0;
7569 /* If the first counter overflows, we are done */
7570 if (--m < 0) goto done;
7571 counters[m]++;
7575 done:
7576 ALLOCV_END(t1);
7578 return NIL_P(result) ? ary : result;
7582 * call-seq:
7583 * array.take(n) -> new_array
7585 * Returns a new +Array+ containing the first +n+ element of +self+,
7586 * where +n+ is a non-negative Integer;
7587 * does not modify +self+.
7589 * Examples:
7591 * a = [0, 1, 2, 3, 4, 5]
7592 * a.take(1) # => [0]
7593 * a.take(2) # => [0, 1]
7594 * a.take(50) # => [0, 1, 2, 3, 4, 5]
7595 * a # => [0, 1, 2, 3, 4, 5]
7599 static VALUE
7600 rb_ary_take(VALUE obj, VALUE n)
7602 long len = NUM2LONG(n);
7603 if (len < 0) {
7604 rb_raise(rb_eArgError, "attempt to take negative size");
7606 return rb_ary_subseq(obj, 0, len);
7610 * call-seq:
7611 * array.take_while {|element| ... } -> new_array
7612 * array.take_while -> new_enumerator
7614 * Returns a new +Array+ containing zero or more leading elements of +self+;
7615 * does not modify +self+.
7617 * With a block given, calls the block with each successive element of +self+;
7618 * stops if the block returns +false+ or +nil+;
7619 * returns a new +Array+ containing those elements for which the block returned a truthy value:
7621 * a = [0, 1, 2, 3, 4, 5]
7622 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7623 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7624 * a # => [0, 1, 2, 3, 4, 5]
7626 * With no block given, returns a new Enumerator:
7628 * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
7632 static VALUE
7633 rb_ary_take_while(VALUE ary)
7635 long i;
7637 RETURN_ENUMERATOR(ary, 0, 0);
7638 for (i = 0; i < RARRAY_LEN(ary); i++) {
7639 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7641 return rb_ary_take(ary, LONG2FIX(i));
7645 * call-seq:
7646 * drop(n) -> new_array
7648 * Returns a new array containing all but the first +n+ element of +self+,
7649 * where +n+ is a non-negative Integer;
7650 * does not modify +self+.
7652 * Examples:
7654 * a = [0, 1, 2, 3, 4, 5]
7655 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7656 * a.drop(1) # => [1, 2, 3, 4, 5]
7657 * a.drop(2) # => [2, 3, 4, 5]
7658 * a.drop(9) # => []
7660 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7663 static VALUE
7664 rb_ary_drop(VALUE ary, VALUE n)
7666 VALUE result;
7667 long pos = NUM2LONG(n);
7668 if (pos < 0) {
7669 rb_raise(rb_eArgError, "attempt to drop negative size");
7672 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7673 if (NIL_P(result)) result = rb_ary_new();
7674 return result;
7678 * call-seq:
7679 * drop_while {|element| ... } -> new_array
7680 * drop_while -> new_enumerator
7682 * With a block given, calls the block with each successive element of +self+;
7683 * stops if the block returns +false+ or +nil+;
7684 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7685 * does not modify +self+:
7687 * a = [0, 1, 2, 3, 4, 5]
7688 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7690 * With no block given, returns a new Enumerator.
7692 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7695 static VALUE
7696 rb_ary_drop_while(VALUE ary)
7698 long i;
7700 RETURN_ENUMERATOR(ary, 0, 0);
7701 for (i = 0; i < RARRAY_LEN(ary); i++) {
7702 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7704 return rb_ary_drop(ary, LONG2FIX(i));
7708 * call-seq:
7709 * any? -> true or false
7710 * any?(object) -> true or false
7711 * any? {|element| ... } -> true or false
7713 * Returns whether for any element of +self+, a given criterion is satisfied.
7715 * With no block and no argument, returns whether any element of +self+ is truthy:
7717 * [nil, false, []].any? # => true # Array object is truthy.
7718 * [nil, false, {}].any? # => true # Hash object is truthy.
7719 * [nil, false, ''].any? # => true # String object is truthy.
7720 * [nil, false].any? # => false # Nil and false are not truthy.
7722 * With argument +object+ given,
7723 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7725 * [nil, false, 0].any?(0) # => true
7726 * [nil, false, 1].any?(0) # => false
7727 * [nil, false, 'food'].any?(/foo/) # => true
7728 * [nil, false, 'food'].any?(/bar/) # => false
7730 * With a block given,
7731 * calls the block with each element in +self+;
7732 * returns whether the block returns any truthy value:
7734 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7735 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7737 * With both a block and argument +object+ given,
7738 * ignores the block and uses +object+ as above.
7740 * <b>Special case</b>: returns +false+ if +self+ is empty
7741 * (regardless of any given argument or block).
7743 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7746 static VALUE
7747 rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
7749 long i, len = RARRAY_LEN(ary);
7751 rb_check_arity(argc, 0, 1);
7752 if (!len) return Qfalse;
7753 if (argc) {
7754 if (rb_block_given_p()) {
7755 rb_warn("given block not used");
7757 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7758 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
7761 else if (!rb_block_given_p()) {
7762 for (i = 0; i < len; ++i) {
7763 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
7766 else {
7767 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7768 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
7771 return Qfalse;
7775 * call-seq:
7776 * all? -> true or false
7777 * all?(object) -> true or false
7778 * all? {|element| ... } -> true or false
7780 * Returns whether for every element of +self+,
7781 * a given criterion is satisfied.
7783 * With no block and no argument,
7784 * returns whether every element of +self+ is truthy:
7786 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7787 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7788 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7790 * With argument +object+ given, returns whether <tt>object === ele</tt>
7791 * for every element +ele+ in +self+:
7793 * [0, 0, 0].all?(0) # => true
7794 * [0, 1, 2].all?(1) # => false
7795 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7796 * ['food', 'drink'].all?(/foo/) # => false
7798 * With a block given, calls the block with each element in +self+;
7799 * returns whether the block returns only truthy values:
7801 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7802 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7804 * With both a block and argument +object+ given,
7805 * ignores the block and uses +object+ as above.
7807 * <b>Special case</b>: returns +true+ if +self+ is empty
7808 * (regardless of any given argument or block).
7810 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7813 static VALUE
7814 rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
7816 long i, len = RARRAY_LEN(ary);
7818 rb_check_arity(argc, 0, 1);
7819 if (!len) return Qtrue;
7820 if (argc) {
7821 if (rb_block_given_p()) {
7822 rb_warn("given block not used");
7824 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7825 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7828 else if (!rb_block_given_p()) {
7829 for (i = 0; i < len; ++i) {
7830 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7833 else {
7834 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7835 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7838 return Qtrue;
7842 * call-seq:
7843 * none? -> true or false
7844 * none?(object) -> true or false
7845 * none? {|element| ... } -> true or false
7847 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
7849 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7850 * +false+ otherwise:
7852 * [nil, false].none? # => true
7853 * [nil, 0, false].none? # => false
7854 * [].none? # => true
7856 * With argument +object+ given, returns +false+ if for any element +element+,
7857 * <tt>object === element</tt>; +true+ otherwise:
7859 * ['food', 'drink'].none?(/bar/) # => true
7860 * ['food', 'drink'].none?(/foo/) # => false
7861 * [].none?(/foo/) # => true
7862 * [0, 1, 2].none?(3) # => true
7863 * [0, 1, 2].none?(1) # => false
7865 * With a block given, calls the block with each element in +self+;
7866 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7868 * [0, 1, 2].none? {|element| element > 3 } # => true
7869 * [0, 1, 2].none? {|element| element > 1 } # => false
7871 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7874 static VALUE
7875 rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
7877 long i, len = RARRAY_LEN(ary);
7879 rb_check_arity(argc, 0, 1);
7880 if (!len) return Qtrue;
7881 if (argc) {
7882 if (rb_block_given_p()) {
7883 rb_warn("given block not used");
7885 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7886 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7889 else if (!rb_block_given_p()) {
7890 for (i = 0; i < len; ++i) {
7891 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7894 else {
7895 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7896 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7899 return Qtrue;
7903 * call-seq:
7904 * one? -> true or false
7905 * one? {|element| ... } -> true or false
7906 * one?(object) -> true or false
7908 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7910 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7911 * +false+ otherwise:
7913 * [nil, 0].one? # => true
7914 * [0, 0].one? # => false
7915 * [nil, nil].one? # => false
7916 * [].one? # => false
7918 * With a block given, calls the block with each element in +self+;
7919 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7921 * [0, 1, 2].one? {|element| element > 0 } # => false
7922 * [0, 1, 2].one? {|element| element > 1 } # => true
7923 * [0, 1, 2].one? {|element| element > 2 } # => false
7925 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
7926 * +false+ otherwise:
7928 * [0, 1, 2].one?(0) # => true
7929 * [0, 0, 1].one?(0) # => false
7930 * [1, 1, 2].one?(0) # => false
7931 * ['food', 'drink'].one?(/bar/) # => false
7932 * ['food', 'drink'].one?(/foo/) # => true
7933 * [].one?(/foo/) # => false
7935 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7938 static VALUE
7939 rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
7941 long i, len = RARRAY_LEN(ary);
7942 VALUE result = Qfalse;
7944 rb_check_arity(argc, 0, 1);
7945 if (!len) return Qfalse;
7946 if (argc) {
7947 if (rb_block_given_p()) {
7948 rb_warn("given block not used");
7950 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7951 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
7952 if (result) return Qfalse;
7953 result = Qtrue;
7957 else if (!rb_block_given_p()) {
7958 for (i = 0; i < len; ++i) {
7959 if (RTEST(RARRAY_AREF(ary, i))) {
7960 if (result) return Qfalse;
7961 result = Qtrue;
7965 else {
7966 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7967 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
7968 if (result) return Qfalse;
7969 result = Qtrue;
7973 return result;
7977 * call-seq:
7978 * array.dig(index, *identifiers) -> object
7980 * Finds and returns the object in nested object
7981 * specified by +index+ and +identifiers+;
7982 * the nested objects may be instances of various classes.
7983 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
7985 * Examples:
7987 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
7988 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
7989 * a.dig(1, 2) # => [:bat, :bam]
7990 * a.dig(1, 2, 0) # => :bat
7991 * a.dig(1, 2, 3) # => nil
7993 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7996 static VALUE
7997 rb_ary_dig(int argc, VALUE *argv, VALUE self)
7999 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
8000 self = rb_ary_at(self, *argv);
8001 if (!--argc) return self;
8002 ++argv;
8003 return rb_obj_dig(argc, argv, self, Qnil);
8006 static inline VALUE
8007 finish_exact_sum(long n, VALUE r, VALUE v, int z)
8009 if (n != 0)
8010 v = rb_fix_plus(LONG2FIX(n), v);
8011 if (!UNDEF_P(r)) {
8012 v = rb_rational_plus(r, v);
8014 else if (!n && z) {
8015 v = rb_fix_plus(LONG2FIX(0), v);
8017 return v;
8021 * call-seq:
8022 * array.sum(init = 0) -> object
8023 * array.sum(init = 0) {|element| ... } -> object
8025 * When no block is given, returns the object equivalent to:
8027 * sum = init
8028 * array.each {|element| sum += element }
8029 * sum
8031 * For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
8033 * Examples:
8035 * a = [0, 1, 2, 3]
8036 * a.sum # => 6
8037 * a.sum(100) # => 106
8039 * The elements need not be numeric, but must be <tt>+</tt>-compatible
8040 * with each other and with +init+:
8042 * a = ['abc', 'def', 'ghi']
8043 * a.sum('jkl') # => "jklabcdefghi"
8045 * When a block is given, it is called with each element
8046 * and the block's return value (instead of the element itself) is used as the addend:
8048 * a = ['zero', 1, :two]
8049 * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
8050 * s # => "Coerced and concatenated: zero1two"
8052 * Notes:
8054 * - Array#join and Array#flatten may be faster than Array#sum
8055 * for an +Array+ of Strings or an +Array+ of Arrays.
8056 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8060 static VALUE
8061 rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8063 VALUE e, v, r;
8064 long i, n;
8065 int block_given;
8067 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8069 block_given = rb_block_given_p();
8071 if (RARRAY_LEN(ary) == 0)
8072 return v;
8074 n = 0;
8075 r = Qundef;
8077 if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8078 i = 0;
8079 goto init_is_a_value;
8082 for (i = 0; i < RARRAY_LEN(ary); i++) {
8083 e = RARRAY_AREF(ary, i);
8084 if (block_given)
8085 e = rb_yield(e);
8086 if (FIXNUM_P(e)) {
8087 n += FIX2LONG(e); /* should not overflow long type */
8088 if (!FIXABLE(n)) {
8089 v = rb_big_plus(LONG2NUM(n), v);
8090 n = 0;
8093 else if (RB_BIGNUM_TYPE_P(e))
8094 v = rb_big_plus(e, v);
8095 else if (RB_TYPE_P(e, T_RATIONAL)) {
8096 if (UNDEF_P(r))
8097 r = e;
8098 else
8099 r = rb_rational_plus(r, e);
8101 else
8102 goto not_exact;
8104 v = finish_exact_sum(n, r, v, argc!=0);
8105 return v;
8107 not_exact:
8108 v = finish_exact_sum(n, r, v, i!=0);
8110 if (RB_FLOAT_TYPE_P(e)) {
8112 * Kahan-Babuska balancing compensated summation algorithm
8113 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8115 double f, c;
8116 double x, t;
8118 f = NUM2DBL(v);
8119 c = 0.0;
8120 goto has_float_value;
8121 for (; i < RARRAY_LEN(ary); i++) {
8122 e = RARRAY_AREF(ary, i);
8123 if (block_given)
8124 e = rb_yield(e);
8125 if (RB_FLOAT_TYPE_P(e))
8126 has_float_value:
8127 x = RFLOAT_VALUE(e);
8128 else if (FIXNUM_P(e))
8129 x = FIX2LONG(e);
8130 else if (RB_BIGNUM_TYPE_P(e))
8131 x = rb_big2dbl(e);
8132 else if (RB_TYPE_P(e, T_RATIONAL))
8133 x = rb_num2dbl(e);
8134 else
8135 goto not_float;
8137 if (isnan(f)) continue;
8138 if (isnan(x)) {
8139 f = x;
8140 continue;
8142 if (isinf(x)) {
8143 if (isinf(f) && signbit(x) != signbit(f))
8144 f = NAN;
8145 else
8146 f = x;
8147 continue;
8149 if (isinf(f)) continue;
8151 t = f + x;
8152 if (fabs(f) >= fabs(x))
8153 c += ((f - t) + x);
8154 else
8155 c += ((x - t) + f);
8156 f = t;
8158 f += c;
8159 return DBL2NUM(f);
8161 not_float:
8162 v = DBL2NUM(f);
8165 goto has_some_value;
8166 init_is_a_value:
8167 for (; i < RARRAY_LEN(ary); i++) {
8168 e = RARRAY_AREF(ary, i);
8169 if (block_given)
8170 e = rb_yield(e);
8171 has_some_value:
8172 v = rb_funcall(v, idPLUS, 1, e);
8174 return v;
8177 /* :nodoc: */
8178 static VALUE
8179 rb_ary_deconstruct(VALUE ary)
8181 return ary;
8185 * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
8186 * Any object (even another array) may be an array element,
8187 * and an array can contain objects of different types.
8189 * == +Array+ Indexes
8191 * +Array+ indexing starts at 0, as in C or Java.
8193 * A positive index is an offset from the first element:
8195 * - Index 0 indicates the first element.
8196 * - Index 1 indicates the second element.
8197 * - ...
8199 * A negative index is an offset, backwards, from the end of the array:
8201 * - Index -1 indicates the last element.
8202 * - Index -2 indicates the next-to-last element.
8203 * - ...
8205 * A non-negative index is <i>in range</i> if and only if it is smaller than
8206 * the size of the array. For a 3-element array:
8208 * - Indexes 0 through 2 are in range.
8209 * - Index 3 is out of range.
8211 * A negative index is <i>in range</i> if and only if its absolute value is
8212 * not larger than the size of the array. For a 3-element array:
8214 * - Indexes -1 through -3 are in range.
8215 * - Index -4 is out of range.
8217 * Although the effective index into an array is always an integer,
8218 * some methods (both within and outside of class +Array+)
8219 * accept one or more non-integer arguments that are
8220 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8223 * == Creating Arrays
8225 * You can create an +Array+ object explicitly with:
8227 * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
8229 * [1, 'one', :one, [2, 'two', :two]]
8231 * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8233 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8234 * %w[1 % *] # => ["1", "%", "*"]
8236 * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8238 * %i[foo bar baz] # => [:foo, :bar, :baz]
8239 * %i[1 % *] # => [:"1", :%, :*]
8241 * - \Method Kernel#Array:
8243 * Array(["a", "b"]) # => ["a", "b"]
8244 * Array(1..5) # => [1, 2, 3, 4, 5]
8245 * Array(key: :value) # => [[:key, :value]]
8246 * Array(nil) # => []
8247 * Array(1) # => [1]
8248 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8250 * - \Method Array.new:
8252 * Array.new # => []
8253 * Array.new(3) # => [nil, nil, nil]
8254 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8255 * Array.new(3, true) # => [true, true, true]
8257 * Note that the last example above populates the array
8258 * with references to the same object.
8259 * This is recommended only in cases where that object is a natively immutable object
8260 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8262 * Another way to create an array with various objects, using a block;
8263 * this usage is safe for mutable objects such as hashes, strings or
8264 * other arrays:
8266 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8268 * Here is a way to create a multi-dimensional array:
8270 * Array.new(3) {Array.new(3)}
8271 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8273 * A number of Ruby methods, both in the core and in the standard library,
8274 * provide instance method +to_a+, which converts an object to an array.
8276 * - ARGF#to_a
8277 * - Array#to_a
8278 * - Enumerable#to_a
8279 * - Hash#to_a
8280 * - MatchData#to_a
8281 * - NilClass#to_a
8282 * - OptionParser#to_a
8283 * - Range#to_a
8284 * - Set#to_a
8285 * - Struct#to_a
8286 * - Time#to_a
8287 * - Benchmark::Tms#to_a
8288 * - CSV::Table#to_a
8289 * - Enumerator::Lazy#to_a
8290 * - Gem::List#to_a
8291 * - Gem::NameTuple#to_a
8292 * - Gem::Platform#to_a
8293 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8294 * - Gem::SourceList#to_a
8295 * - OpenSSL::X509::Extension#to_a
8296 * - OpenSSL::X509::Name#to_a
8297 * - Racc::ISet#to_a
8298 * - Rinda::RingFinger#to_a
8299 * - Ripper::Lexer::Elem#to_a
8300 * - RubyVM::InstructionSequence#to_a
8301 * - YAML::DBM#to_a
8303 * == Example Usage
8305 * In addition to the methods it mixes in through the Enumerable module, the
8306 * +Array+ class has proprietary methods for accessing, searching and otherwise
8307 * manipulating arrays.
8309 * Some of the more common ones are illustrated below.
8311 * == Accessing Elements
8313 * Elements in an array can be retrieved using the Array#[] method. It can
8314 * take a single integer argument (a numeric index), a pair of arguments
8315 * (start and length) or a range. Negative indices start counting from the end,
8316 * with -1 being the last element.
8318 * arr = [1, 2, 3, 4, 5, 6]
8319 * arr[2] #=> 3
8320 * arr[100] #=> nil
8321 * arr[-3] #=> 4
8322 * arr[2, 3] #=> [3, 4, 5]
8323 * arr[1..4] #=> [2, 3, 4, 5]
8324 * arr[1..-3] #=> [2, 3, 4]
8326 * Another way to access a particular array element is by using the #at method
8328 * arr.at(0) #=> 1
8330 * The #slice method works in an identical manner to Array#[].
8332 * To raise an error for indices outside of the array bounds or else to
8333 * provide a default value when that happens, you can use #fetch.
8335 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8336 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8337 * arr.fetch(100, "oops") #=> "oops"
8339 * The special methods #first and #last will return the first and last
8340 * elements of an array, respectively.
8342 * arr.first #=> 1
8343 * arr.last #=> 6
8345 * To return the first +n+ elements of an array, use #take
8347 * arr.take(3) #=> [1, 2, 3]
8349 * #drop does the opposite of #take, by returning the elements after +n+
8350 * elements have been dropped:
8352 * arr.drop(3) #=> [4, 5, 6]
8354 * == Obtaining Information about an +Array+
8356 * Arrays keep track of their own length at all times. To query an array
8357 * about the number of elements it contains, use #length, #count or #size.
8359 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8360 * browsers.length #=> 5
8361 * browsers.count #=> 5
8363 * To check whether an array contains any elements at all
8365 * browsers.empty? #=> false
8367 * To check whether a particular item is included in the array
8369 * browsers.include?('Konqueror') #=> false
8371 * == Adding Items to Arrays
8373 * Items can be added to the end of an array by using either #push or #<<
8375 * arr = [1, 2, 3, 4]
8376 * arr.push(5) #=> [1, 2, 3, 4, 5]
8377 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8379 * #unshift will add a new item to the beginning of an array.
8381 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8383 * With #insert you can add a new element to an array at any position.
8385 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8387 * Using the #insert method, you can also insert multiple values at once:
8389 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8390 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8392 * == Removing Items from an +Array+
8394 * The method #pop removes the last element in an array and returns it:
8396 * arr = [1, 2, 3, 4, 5, 6]
8397 * arr.pop #=> 6
8398 * arr #=> [1, 2, 3, 4, 5]
8400 * To retrieve and at the same time remove the first item, use #shift:
8402 * arr.shift #=> 1
8403 * arr #=> [2, 3, 4, 5]
8405 * To delete an element at a particular index:
8407 * arr.delete_at(2) #=> 4
8408 * arr #=> [2, 3, 5]
8410 * To delete a particular element anywhere in an array, use #delete:
8412 * arr = [1, 2, 2, 3]
8413 * arr.delete(2) #=> 2
8414 * arr #=> [1,3]
8416 * A useful method if you need to remove +nil+ values from an array is
8417 * #compact:
8419 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8420 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8421 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8422 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8423 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8425 * Another common need is to remove duplicate elements from an array.
8427 * It has the non-destructive #uniq, and destructive method #uniq!
8429 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8430 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8432 * == Iterating over Arrays
8434 * Like all classes that include the Enumerable module, +Array+ has an each
8435 * method, which defines what elements should be iterated over and how. In
8436 * case of Array's #each, all elements in the +Array+ instance are yielded to
8437 * the supplied block in sequence.
8439 * Note that this operation leaves the array unchanged.
8441 * arr = [1, 2, 3, 4, 5]
8442 * arr.each {|a| print a -= 10, " "}
8443 * # prints: -9 -8 -7 -6 -5
8444 * #=> [1, 2, 3, 4, 5]
8446 * Another sometimes useful iterator is #reverse_each which will iterate over
8447 * the elements in the array in reverse order.
8449 * words = %w[first second third fourth fifth sixth]
8450 * str = ""
8451 * words.reverse_each {|word| str += "#{word} "}
8452 * p str #=> "sixth fifth fourth third second first "
8454 * The #map method can be used to create a new array based on the original
8455 * array, but with the values modified by the supplied block:
8457 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8458 * arr #=> [1, 2, 3, 4, 5]
8459 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8460 * arr #=> [1, 4, 9, 16, 25]
8463 * == Selecting Items from an +Array+
8465 * Elements can be selected from an array according to criteria defined in a
8466 * block. The selection can happen in a destructive or a non-destructive
8467 * manner. While the destructive operations will modify the array they were
8468 * called on, the non-destructive methods usually return a new array with the
8469 * selected elements, but leave the original array unchanged.
8471 * === Non-destructive Selection
8473 * arr = [1, 2, 3, 4, 5, 6]
8474 * arr.select {|a| a > 3} #=> [4, 5, 6]
8475 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8476 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8477 * arr #=> [1, 2, 3, 4, 5, 6]
8479 * === Destructive Selection
8481 * #select! and #reject! are the corresponding destructive methods to #select
8482 * and #reject
8484 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8485 * opposite result when supplied with the same block:
8487 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8488 * arr #=> [4, 5, 6]
8490 * arr = [1, 2, 3, 4, 5, 6]
8491 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8492 * arr #=> [1, 2, 3]
8494 * == What's Here
8496 * First, what's elsewhere. \Class +Array+:
8498 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8499 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8500 * which provides dozens of additional methods.
8502 * Here, class +Array+ provides methods that are useful for:
8504 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8505 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8506 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8507 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8508 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8509 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8510 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8511 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8512 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8513 * - {And more....}[rdoc-ref:Array@Other+Methods]
8515 * === Methods for Creating an +Array+
8517 * - ::[]: Returns a new array populated with given objects.
8518 * - ::new: Returns a new array.
8519 * - ::try_convert: Returns a new array created from a given object.
8521 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8523 * === Methods for Querying
8525 * - #length (aliased as #size): Returns the count of elements.
8526 * - #include?: Returns whether any element <tt>==</tt> a given object.
8527 * - #empty?: Returns whether there are no elements.
8528 * - #all?: Returns whether all elements meet a given criterion.
8529 * - #any?: Returns whether any element meets a given criterion.
8530 * - #none?: Returns whether no element <tt>==</tt> a given object.
8531 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8532 * - #count: Returns the count of elements that meet a given criterion.
8533 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8534 * - #rindex: Returns the index of the last element that meets a given criterion.
8535 * - #hash: Returns the integer hash code.
8537 * === Methods for Comparing
8539 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or
8540 * greater than a given object.
8541 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
8542 * in a given object.
8543 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8544 * element in a given object.
8546 * === Methods for Fetching
8548 * These methods do not modify +self+.
8550 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8551 * - #fetch: Returns the element at a given offset.
8552 * - #fetch_values: Returns elements at given offsets.
8553 * - #first: Returns one or more leading elements.
8554 * - #last: Returns one or more trailing elements.
8555 * - #max: Returns one or more maximum-valued elements,
8556 * as determined by <tt>#<=></tt> or a given block.
8557 * - #min: Returns one or more minimum-valued elements,
8558 * as determined by <tt>#<=></tt> or a given block.
8559 * - #minmax: Returns the minimum-valued and maximum-valued elements,
8560 * as determined by <tt>#<=></tt> or a given block.
8561 * - #assoc: Returns the first element that is an array
8562 * whose first element <tt>==</tt> a given object.
8563 * - #rassoc: Returns the first element that is an array
8564 * whose second element <tt>==</tt> a given object.
8565 * - #at: Returns the element at a given offset.
8566 * - #values_at: Returns the elements at given offsets.
8567 * - #dig: Returns the object in nested objects
8568 * that is specified by a given index and additional arguments.
8569 * - #drop: Returns trailing elements as determined by a given index.
8570 * - #take: Returns leading elements as determined by a given index.
8571 * - #drop_while: Returns trailing elements as determined by a given block.
8572 * - #take_while: Returns leading elements as determined by a given block.
8573 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8574 * - #reverse: Returns all elements in reverse order.
8575 * - #compact: Returns an array containing all non-+nil+ elements.
8576 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8577 * - #uniq: Returns an array containing non-duplicate elements.
8578 * - #rotate: Returns all elements with some rotated from one end to the other.
8579 * - #bsearch: Returns an element selected via a binary search
8580 * as determined by a given block.
8581 * - #bsearch_index: Returns the index of an element selected via a binary search
8582 * as determined by a given block.
8583 * - #sample: Returns one or more random elements.
8584 * - #shuffle: Returns elements in a random order.
8585 * - #reject: Returns an array containing elements not rejected by a given block.
8587 * === Methods for Assigning
8589 * These methods add, replace, or reorder elements in +self+.
8591 * - #[]=: Assigns specified elements with a given object.
8592 * - #<<: Appends an element.
8593 * - #push (aliased as #append): Appends elements.
8594 * - #unshift (aliased as #prepend): Prepends leading elements.
8595 * - #insert: Inserts given objects at a given offset; does not replace elements.
8596 * - #concat: Appends all elements from given arrays.
8597 * - #fill: Replaces specified elements with specified objects.
8598 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8599 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8600 * - #reverse!: Replaces +self+ with its elements reversed.
8601 * - #rotate!: Replaces +self+ with its elements rotated.
8602 * - #shuffle!: Replaces +self+ with its elements in random order.
8603 * - #sort!: Replaces +self+ with its elements sorted,
8604 * as determined by <tt>#<=></tt> or a given block.
8605 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8607 * === Methods for Deleting
8609 * Each of these methods removes elements from +self+:
8611 * - #pop: Removes and returns the last element.
8612 * - #shift: Removes and returns the first element.
8613 * - #compact!: Removes all +nil+ elements.
8614 * - #delete: Removes elements equal to a given object.
8615 * - #delete_at: Removes the element at a given offset.
8616 * - #delete_if: Removes elements specified by a given block.
8617 * - #clear: Removes all elements.
8618 * - #keep_if: Removes elements not specified by a given block.
8619 * - #reject!: Removes elements specified by a given block.
8620 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8621 * - #slice!: Removes and returns a sequence of elements.
8622 * - #uniq!: Removes duplicates.
8624 * === Methods for Combining
8626 * - #&: Returns an array containing elements found both in +self+ and a given array.
8627 * - #intersection: Returns an array containing elements found both in +self+
8628 * and in each given array.
8629 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8630 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8631 * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
8632 * duplicates removed.
8633 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
8634 * duplicates removed.
8635 * - #difference: Returns an array containing all elements of +self+ that are not found
8636 * in any of the given arrays..
8637 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8638 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8640 * === Methods for Iterating
8642 * - #each: Passes each element to a given block.
8643 * - #reverse_each: Passes each element, in reverse order, to a given block.
8644 * - #each_index: Passes each element index to a given block.
8645 * - #cycle: Calls a given block with each element, then does so again,
8646 * for a specified number of times, or forever.
8647 * - #combination: Calls a given block with combinations of elements of +self+;
8648 * a combination does not use the same element more than once.
8649 * - #permutation: Calls a given block with permutations of elements of +self+;
8650 * a permutation does not use the same element more than once.
8651 * - #repeated_combination: Calls a given block with combinations of elements of +self+;
8652 * a combination may use the same element more than once.
8653 * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
8654 * a permutation may use the same element more than once.
8656 * === Methods for Converting
8658 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8659 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8660 * - #flatten: Returns an array that is a recursive flattening of +self+.
8661 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8662 * - #join: Returns a newsString containing the elements joined by the field separator.
8663 * - #to_a: Returns +self+ or a new array containing all elements.
8664 * - #to_ary: Returns +self+.
8665 * - #to_h: Returns a new hash formed from the elements.
8666 * - #transpose: Transposes +self+, which must be an array of arrays.
8667 * - #zip: Returns a new array of arrays containing +self+ and given arrays;
8668 * follow the link for details.
8670 * === Other Methods
8672 * - #*: Returns one of the following:
8674 * - With integer argument +n+, a new array that is the concatenation
8675 * of +n+ copies of +self+.
8676 * - With string argument +field_separator+, a new string that is equivalent to
8677 * <tt>join(field_separator)</tt>.
8679 * - #pack: Packs the elements into a binary sequence.
8680 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8683 void
8684 Init_Array(void)
8686 fake_ary_flags = init_fake_ary_flags();
8688 rb_cArray = rb_define_class("Array", rb_cObject);
8689 rb_include_module(rb_cArray, rb_mEnumerable);
8691 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8692 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
8693 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8694 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8695 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8696 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8698 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
8699 rb_define_alias(rb_cArray, "to_s", "inspect");
8700 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
8701 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
8702 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
8704 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
8705 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
8706 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
8708 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
8709 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
8710 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
8711 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8712 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
8713 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
8714 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
8715 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
8716 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
8717 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
8718 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
8719 rb_define_alias(rb_cArray, "append", "push");
8720 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
8721 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
8722 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
8723 rb_define_alias(rb_cArray, "prepend", "unshift");
8724 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
8725 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
8726 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
8727 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
8728 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
8729 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
8730 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
8731 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
8732 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
8733 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
8734 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
8735 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
8736 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
8737 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
8738 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
8739 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
8740 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
8741 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
8742 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
8743 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
8744 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8745 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
8746 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8747 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
8748 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
8749 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
8750 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
8751 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
8752 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
8753 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
8754 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
8755 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
8756 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
8757 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
8758 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
8759 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
8760 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
8761 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
8762 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
8764 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
8765 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
8767 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
8768 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
8770 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
8771 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
8773 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
8774 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
8775 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
8777 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
8778 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
8779 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
8781 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
8782 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
8783 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
8784 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
8785 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
8786 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
8787 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
8788 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
8789 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
8790 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
8791 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
8792 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
8793 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
8795 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
8796 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
8797 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
8798 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
8799 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
8800 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
8801 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
8802 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
8803 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
8804 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
8805 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
8806 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
8807 rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
8809 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
8811 rb_cArray_empty_frozen = rb_ary_freeze(rb_ary_new());
8812 rb_vm_register_global_object(rb_cArray_empty_frozen);
8815 #include "array.rbinc"