[rubygems/rubygems] Use a constant empty tar header to avoid extra allocations
[ruby.git] / array.c
blob6ad69dd23fa791d2815ff22a34f4c5ca0dea10cc
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;
42 /* Flags of RArray
44 * 1: RARRAY_EMBED_FLAG
45 * The array is embedded (its contents follow the header, rather than
46 * being on a separately allocated buffer).
47 * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
48 * The array is shared. The buffer this array points to is owned by
49 * another array (the shared root).
50 * 3-9: RARRAY_EMBED_LEN
51 * The length of the array when RARRAY_EMBED_FLAG is set.
52 * 12: RARRAY_SHARED_ROOT_FLAG
53 * The array is a shared root that does reference counting. The buffer
54 * this array points to is owned by this array but may be pointed to
55 * by other arrays.
56 * Note: Frozen arrays may be a shared root without this flag being
57 * set. Frozen arrays do not have reference counting because
58 * they cannot be modified. Not updating the reference count
59 * improves copy-on-write performance. Their reference count is
60 * assumed to be infinity.
61 * 14: RARRAY_PTR_IN_USE_FLAG
62 * The buffer of the array is in use. This is only used during
63 * debugging.
66 /* for OPTIMIZED_CMP: */
67 #define id_cmp idCmp
69 #define ARY_DEFAULT_SIZE 16
70 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
71 #define SMALL_ARRAY_LEN 16
73 RBIMPL_ATTR_MAYBE_UNUSED()
74 static int
75 should_be_T_ARRAY(VALUE ary)
77 return RB_TYPE_P(ary, T_ARRAY);
80 #define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
81 #define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
82 #define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
83 RARRAY(a)->as.heap.aux.capa)
85 #define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
86 #define ARY_EMBED_LEN(a) \
87 (RUBY_ASSERT(ARY_EMBED_P(a)), \
88 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
89 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
90 #define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
92 #define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
93 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
95 #define FL_SET_EMBED(a) do { \
96 RUBY_ASSERT(!ARY_SHARED_P(a)); \
97 FL_SET((a), RARRAY_EMBED_FLAG); \
98 ary_verify(a); \
99 } while (0)
101 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
102 #define FL_SET_SHARED(ary) do { \
103 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
104 FL_SET((ary), RARRAY_SHARED_FLAG); \
105 } while (0)
106 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
108 #define ARY_SET_PTR(ary, p) do { \
109 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
110 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
111 RARRAY(ary)->as.heap.ptr = (p); \
112 } while (0)
113 #define ARY_SET_EMBED_LEN(ary, n) do { \
114 long tmp_n = (n); \
115 RUBY_ASSERT(ARY_EMBED_P(ary)); \
116 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
117 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
118 } while (0)
119 #define ARY_SET_HEAP_LEN(ary, n) do { \
120 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
121 RARRAY(ary)->as.heap.len = (n); \
122 } while (0)
123 #define ARY_SET_LEN(ary, n) do { \
124 if (ARY_EMBED_P(ary)) { \
125 ARY_SET_EMBED_LEN((ary), (n)); \
127 else { \
128 ARY_SET_HEAP_LEN((ary), (n)); \
130 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
131 } while (0)
132 #define ARY_INCREASE_PTR(ary, n) do { \
133 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
134 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
135 RARRAY(ary)->as.heap.ptr += (n); \
136 } while (0)
137 #define ARY_INCREASE_LEN(ary, n) do { \
138 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
139 if (ARY_EMBED_P(ary)) { \
140 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
142 else { \
143 RARRAY(ary)->as.heap.len += (n); \
145 } while (0)
147 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
148 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
149 #define ARY_SET_CAPA(ary, n) do { \
150 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
151 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
152 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
153 RARRAY(ary)->as.heap.aux.capa = (n); \
154 } while (0)
156 #define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
157 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
158 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
159 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
160 RUBY_ASSERT((value) >= 0); \
161 RARRAY(ary)->as.heap.aux.capa = (value); \
162 } while (0)
163 #define FL_SET_SHARED_ROOT(ary) do { \
164 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
165 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
166 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
167 } while (0)
169 static inline void
170 ARY_SET(VALUE a, long i, VALUE v)
172 RUBY_ASSERT(!ARY_SHARED_P(a));
173 RUBY_ASSERT(!OBJ_FROZEN(a));
175 RARRAY_ASET(a, i, v);
177 #undef RARRAY_ASET
179 static long
180 ary_embed_capa(VALUE ary)
182 size_t size = rb_gc_obj_slot_size(ary) - offsetof(struct RArray, as.ary);
183 RUBY_ASSERT(size % sizeof(VALUE) == 0);
184 return size / sizeof(VALUE);
187 static size_t
188 ary_embed_size(long capa)
190 return offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
193 static bool
194 ary_embeddable_p(long capa)
196 return rb_gc_size_allocatable_p(ary_embed_size(capa));
199 bool
200 rb_ary_embeddable_p(VALUE ary)
202 /* An array cannot be turned embeddable when the array is:
203 * - Shared root: other objects may point to the buffer of this array
204 * so we cannot make it embedded.
205 * - Frozen: this array may also be a shared root without the shared root
206 * flag.
207 * - Shared: we don't want to re-embed an array that points to a shared
208 * root (to save memory).
210 return !(ARY_SHARED_ROOT_P(ary) || OBJ_FROZEN(ary) || ARY_SHARED_P(ary));
213 size_t
214 rb_ary_size_as_embedded(VALUE ary)
216 size_t real_size;
218 if (ARY_EMBED_P(ary)) {
219 real_size = ary_embed_size(ARY_EMBED_LEN(ary));
221 else if (rb_ary_embeddable_p(ary)) {
222 real_size = ary_embed_size(ARY_HEAP_CAPA(ary));
224 else {
225 real_size = sizeof(struct RArray);
227 return real_size;
231 #if ARRAY_DEBUG
232 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
234 static VALUE
235 ary_verify_(VALUE ary, const char *file, int line)
237 RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
239 if (ARY_SHARED_P(ary)) {
240 VALUE root = ARY_SHARED_ROOT(ary);
241 const VALUE *ptr = ARY_HEAP_PTR(ary);
242 const VALUE *root_ptr = RARRAY_CONST_PTR(root);
243 long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
244 RUBY_ASSERT(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
245 RUBY_ASSERT(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
246 ary_verify(root);
248 else if (ARY_EMBED_P(ary)) {
249 RUBY_ASSERT(!ARY_SHARED_P(ary));
250 RUBY_ASSERT(RARRAY_LEN(ary) <= ary_embed_capa(ary));
252 else {
253 const VALUE *ptr = RARRAY_CONST_PTR(ary);
254 long i, len = RARRAY_LEN(ary);
255 volatile VALUE v;
256 if (len > 1) len = 1; /* check only HEAD */
257 for (i=0; i<len; i++) {
258 v = ptr[i]; /* access check */
260 v = v;
263 return ary;
266 void
267 rb_ary_verify(VALUE ary)
269 ary_verify(ary);
271 #else
272 #define ary_verify(ary) ((void)0)
273 #endif
275 VALUE *
276 rb_ary_ptr_use_start(VALUE ary)
278 #if ARRAY_DEBUG
279 FL_SET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
280 #endif
281 return (VALUE *)RARRAY_CONST_PTR(ary);
284 void
285 rb_ary_ptr_use_end(VALUE ary)
287 #if ARRAY_DEBUG
288 FL_UNSET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
289 #endif
292 void
293 rb_mem_clear(VALUE *mem, long size)
295 while (size--) {
296 *mem++ = Qnil;
300 static void
301 ary_mem_clear(VALUE ary, long beg, long size)
303 RARRAY_PTR_USE(ary, ptr, {
304 rb_mem_clear(ptr + beg, size);
308 static inline void
309 memfill(register VALUE *mem, register long size, register VALUE val)
311 while (size--) {
312 *mem++ = val;
316 static void
317 ary_memfill(VALUE ary, long beg, long size, VALUE val)
319 RARRAY_PTR_USE(ary, ptr, {
320 memfill(ptr + beg, size, val);
321 RB_OBJ_WRITTEN(ary, Qundef, val);
325 static void
326 ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
328 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary));
330 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
331 rb_gc_writebarrier_remember(buff_owner_ary);
332 RARRAY_PTR_USE(ary, ptr, {
333 MEMCPY(ptr+beg, argv, VALUE, argc);
336 else {
337 int i;
338 RARRAY_PTR_USE(ary, ptr, {
339 for (i=0; i<argc; i++) {
340 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
346 static void
347 ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
349 ary_memcpy0(ary, beg, argc, argv, ary);
352 static VALUE *
353 ary_heap_alloc_buffer(size_t capa)
355 return ALLOC_N(VALUE, capa);
358 static void
359 ary_heap_free_ptr(VALUE ary, const VALUE *ptr, long size)
361 ruby_sized_xfree((void *)ptr, size);
364 static void
365 ary_heap_free(VALUE ary)
367 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
370 static size_t
371 ary_heap_realloc(VALUE ary, size_t new_capa)
373 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, ARY_HEAP_CAPA(ary));
374 ary_verify(ary);
376 return new_capa;
379 void
380 rb_ary_make_embedded(VALUE ary)
382 RUBY_ASSERT(rb_ary_embeddable_p(ary));
383 if (!ARY_EMBED_P(ary)) {
384 const VALUE *buf = ARY_HEAP_PTR(ary);
385 long len = ARY_HEAP_LEN(ary);
387 FL_SET_EMBED(ary);
388 ARY_SET_EMBED_LEN(ary, len);
390 MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
392 ary_heap_free_ptr(ary, buf, len * sizeof(VALUE));
396 static void
397 ary_resize_capa(VALUE ary, long capacity)
399 RUBY_ASSERT(RARRAY_LEN(ary) <= capacity);
400 RUBY_ASSERT(!OBJ_FROZEN(ary));
401 RUBY_ASSERT(!ARY_SHARED_P(ary));
403 if (capacity > ary_embed_capa(ary)) {
404 size_t new_capa = capacity;
405 if (ARY_EMBED_P(ary)) {
406 long len = ARY_EMBED_LEN(ary);
407 VALUE *ptr = ary_heap_alloc_buffer(capacity);
409 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
410 FL_UNSET_EMBED(ary);
411 ARY_SET_PTR(ary, ptr);
412 ARY_SET_HEAP_LEN(ary, len);
414 else {
415 new_capa = ary_heap_realloc(ary, capacity);
417 ARY_SET_CAPA(ary, new_capa);
419 else {
420 if (!ARY_EMBED_P(ary)) {
421 long len = ARY_HEAP_LEN(ary);
422 long old_capa = ARY_HEAP_CAPA(ary);
423 const VALUE *ptr = ARY_HEAP_PTR(ary);
425 if (len > capacity) len = capacity;
426 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
427 ary_heap_free_ptr(ary, ptr, old_capa);
429 FL_SET_EMBED(ary);
430 ARY_SET_LEN(ary, len);
434 ary_verify(ary);
437 static inline void
438 ary_shrink_capa(VALUE ary)
440 long capacity = ARY_HEAP_LEN(ary);
441 long old_capa = ARY_HEAP_CAPA(ary);
442 RUBY_ASSERT(!ARY_SHARED_P(ary));
443 RUBY_ASSERT(old_capa >= capacity);
444 if (old_capa > capacity) ary_heap_realloc(ary, capacity);
446 ary_verify(ary);
449 static void
450 ary_double_capa(VALUE ary, long min)
452 long new_capa = ARY_CAPA(ary) / 2;
454 if (new_capa < ARY_DEFAULT_SIZE) {
455 new_capa = ARY_DEFAULT_SIZE;
457 if (new_capa >= ARY_MAX_SIZE - min) {
458 new_capa = (ARY_MAX_SIZE - min) / 2;
460 new_capa += min;
461 ary_resize_capa(ary, new_capa);
463 ary_verify(ary);
466 static void
467 rb_ary_decrement_share(VALUE shared_root)
469 if (!OBJ_FROZEN(shared_root)) {
470 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
471 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
475 static void
476 rb_ary_unshare(VALUE ary)
478 VALUE shared_root = ARY_SHARED_ROOT(ary);
479 rb_ary_decrement_share(shared_root);
480 FL_UNSET_SHARED(ary);
483 static void
484 rb_ary_reset(VALUE ary)
486 if (ARY_OWNS_HEAP_P(ary)) {
487 ary_heap_free(ary);
489 else if (ARY_SHARED_P(ary)) {
490 rb_ary_unshare(ary);
493 FL_SET_EMBED(ary);
494 ARY_SET_EMBED_LEN(ary, 0);
497 static VALUE
498 rb_ary_increment_share(VALUE shared_root)
500 if (!OBJ_FROZEN(shared_root)) {
501 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
502 RUBY_ASSERT(num >= 0);
503 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
505 return shared_root;
508 static void
509 rb_ary_set_shared(VALUE ary, VALUE shared_root)
511 RUBY_ASSERT(!ARY_EMBED_P(ary));
512 RUBY_ASSERT(!OBJ_FROZEN(ary));
513 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root));
515 rb_ary_increment_share(shared_root);
516 FL_SET_SHARED(ary);
517 RB_OBJ_WRITE(ary, &RARRAY(ary)->as.heap.aux.shared_root, shared_root);
519 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
522 static inline void
523 rb_ary_modify_check(VALUE ary)
525 rb_check_frozen(ary);
526 ary_verify(ary);
529 void
530 rb_ary_cancel_sharing(VALUE ary)
532 if (ARY_SHARED_P(ary)) {
533 long shared_len, len = RARRAY_LEN(ary);
534 VALUE shared_root = ARY_SHARED_ROOT(ary);
536 ary_verify(shared_root);
538 if (len <= ary_embed_capa(ary)) {
539 const VALUE *ptr = ARY_HEAP_PTR(ary);
540 FL_UNSET_SHARED(ary);
541 FL_SET_EMBED(ary);
542 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
543 rb_ary_decrement_share(shared_root);
544 ARY_SET_EMBED_LEN(ary, len);
546 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
547 long shift = RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared_root);
548 FL_UNSET_SHARED(ary);
549 ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared_root));
550 ARY_SET_CAPA(ary, shared_len);
551 RARRAY_PTR_USE(ary, ptr, {
552 MEMMOVE(ptr, ptr+shift, VALUE, len);
554 FL_SET_EMBED(shared_root);
555 rb_ary_decrement_share(shared_root);
557 else {
558 VALUE *ptr = ary_heap_alloc_buffer(len);
559 MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
560 rb_ary_unshare(ary);
561 ARY_SET_CAPA(ary, len);
562 ARY_SET_PTR(ary, ptr);
565 rb_gc_writebarrier_remember(ary);
567 ary_verify(ary);
570 void
571 rb_ary_modify(VALUE ary)
573 rb_ary_modify_check(ary);
574 rb_ary_cancel_sharing(ary);
577 static VALUE
578 ary_ensure_room_for_push(VALUE ary, long add_len)
580 long old_len = RARRAY_LEN(ary);
581 long new_len = old_len + add_len;
582 long capa;
584 if (old_len > ARY_MAX_SIZE - add_len) {
585 rb_raise(rb_eIndexError, "index %ld too big", new_len);
587 if (ARY_SHARED_P(ary)) {
588 if (new_len > ary_embed_capa(ary)) {
589 VALUE shared_root = ARY_SHARED_ROOT(ary);
590 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
591 if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
592 rb_ary_modify_check(ary);
594 ary_verify(ary);
595 ary_verify(shared_root);
596 return shared_root;
598 else {
599 /* if array is shared, then it is likely it participate in push/shift pattern */
600 rb_ary_modify(ary);
601 capa = ARY_CAPA(ary);
602 if (new_len > capa - (capa >> 6)) {
603 ary_double_capa(ary, new_len);
605 ary_verify(ary);
606 return ary;
610 ary_verify(ary);
611 rb_ary_modify(ary);
613 else {
614 rb_ary_modify_check(ary);
616 capa = ARY_CAPA(ary);
617 if (new_len > capa) {
618 ary_double_capa(ary, new_len);
621 ary_verify(ary);
622 return ary;
626 * call-seq:
627 * array.freeze -> self
629 * Freezes +self+; returns +self+:
631 * a = []
632 * a.frozen? # => false
633 * a.freeze
634 * a.frozen? # => true
636 * An attempt to modify a frozen +Array+ raises FrozenError.
639 VALUE
640 rb_ary_freeze(VALUE ary)
642 return rb_obj_freeze(ary);
645 /* This can be used to take a snapshot of an array (with
646 e.g. rb_ary_replace) and check later whether the array has been
647 modified from the snapshot. The snapshot is cheap, though if
648 something does modify the array it will pay the cost of copying
649 it. If Array#pop or Array#shift has been called, the array will
650 be still shared with the snapshot, but the array length will
651 differ. */
652 VALUE
653 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
655 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
656 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
657 ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
658 ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
659 return Qtrue;
661 return Qfalse;
664 static VALUE
665 ary_alloc_embed(VALUE klass, long capa)
667 size_t size = ary_embed_size(capa);
668 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
669 NEWOBJ_OF(ary, struct RArray, klass,
670 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
671 size, 0);
672 /* Created array is:
673 * FL_SET_EMBED((VALUE)ary);
674 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
676 return (VALUE)ary;
679 static VALUE
680 ary_alloc_heap(VALUE klass)
682 NEWOBJ_OF(ary, struct RArray, klass,
683 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
684 sizeof(struct RArray), 0);
685 return (VALUE)ary;
688 static VALUE
689 empty_ary_alloc(VALUE klass)
691 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
692 return ary_alloc_embed(klass, 0);
695 static VALUE
696 ary_new(VALUE klass, long capa)
698 VALUE ary;
700 if (capa < 0) {
701 rb_raise(rb_eArgError, "negative array size (or size too big)");
703 if (capa > ARY_MAX_SIZE) {
704 rb_raise(rb_eArgError, "array size too big");
707 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
709 if (ary_embeddable_p(capa)) {
710 ary = ary_alloc_embed(klass, capa);
712 else {
713 ary = ary_alloc_heap(klass);
714 ARY_SET_CAPA(ary, capa);
715 RUBY_ASSERT(!ARY_EMBED_P(ary));
717 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
718 ARY_SET_HEAP_LEN(ary, 0);
721 return ary;
724 VALUE
725 rb_ary_new_capa(long capa)
727 return ary_new(rb_cArray, capa);
730 VALUE
731 rb_ary_new(void)
733 return rb_ary_new_capa(0);
736 VALUE
737 (rb_ary_new_from_args)(long n, ...)
739 va_list ar;
740 VALUE ary;
741 long i;
743 ary = rb_ary_new2(n);
745 va_start(ar, n);
746 for (i=0; i<n; i++) {
747 ARY_SET(ary, i, va_arg(ar, VALUE));
749 va_end(ar);
751 ARY_SET_LEN(ary, n);
752 return ary;
755 VALUE
756 rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
758 VALUE ary;
760 ary = ary_new(klass, n);
761 if (n > 0 && elts) {
762 ary_memcpy(ary, 0, n, elts);
763 ARY_SET_LEN(ary, n);
766 return ary;
769 VALUE
770 rb_ary_new_from_values(long n, const VALUE *elts)
772 return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
775 static VALUE
776 ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
778 size_t size = ary_embed_size(capa);
779 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
780 NEWOBJ_OF(ary, struct RArray, klass,
781 T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
782 size, ec);
783 /* Created array is:
784 * FL_SET_EMBED((VALUE)ary);
785 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
787 return (VALUE)ary;
790 static VALUE
791 ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
793 NEWOBJ_OF(ary, struct RArray, klass,
794 T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
795 sizeof(struct RArray), ec);
796 return (VALUE)ary;
799 static VALUE
800 ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
802 VALUE ary;
804 if (capa < 0) {
805 rb_raise(rb_eArgError, "negative array size (or size too big)");
807 if (capa > ARY_MAX_SIZE) {
808 rb_raise(rb_eArgError, "array size too big");
811 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
813 if (ary_embeddable_p(capa)) {
814 ary = ec_ary_alloc_embed(ec, klass, capa);
816 else {
817 ary = ec_ary_alloc_heap(ec, klass);
818 ARY_SET_CAPA(ary, capa);
819 RUBY_ASSERT(!ARY_EMBED_P(ary));
821 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
822 ARY_SET_HEAP_LEN(ary, 0);
825 return ary;
828 VALUE
829 rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
831 VALUE ary;
833 ary = ec_ary_new(ec, rb_cArray, n);
834 if (n > 0 && elts) {
835 ary_memcpy(ary, 0, n, elts);
836 ARY_SET_LEN(ary, n);
839 return ary;
842 VALUE
843 rb_ary_hidden_new(long capa)
845 VALUE ary = ary_new(0, capa);
846 return ary;
849 VALUE
850 rb_ary_hidden_new_fill(long capa)
852 VALUE ary = rb_ary_hidden_new(capa);
853 ary_memfill(ary, 0, capa, Qnil);
854 ARY_SET_LEN(ary, capa);
855 return ary;
858 void
859 rb_ary_free(VALUE ary)
861 if (ARY_OWNS_HEAP_P(ary)) {
862 if (USE_DEBUG_COUNTER &&
863 !ARY_SHARED_ROOT_P(ary) &&
864 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
865 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
868 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
869 ary_heap_free(ary);
871 else {
872 RB_DEBUG_COUNTER_INC(obj_ary_embed);
875 if (ARY_SHARED_P(ary)) {
876 RB_DEBUG_COUNTER_INC(obj_ary_shared);
878 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
879 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
883 size_t
884 rb_ary_memsize(VALUE ary)
886 if (ARY_OWNS_HEAP_P(ary)) {
887 return ARY_CAPA(ary) * sizeof(VALUE);
889 else {
890 return 0;
894 static VALUE
895 ary_make_shared(VALUE ary)
897 ary_verify(ary);
899 if (ARY_SHARED_P(ary)) {
900 return ARY_SHARED_ROOT(ary);
902 else if (ARY_SHARED_ROOT_P(ary)) {
903 return ary;
905 else if (OBJ_FROZEN(ary)) {
906 if (!ARY_EMBED_P(ary)) {
907 ary_shrink_capa(ary);
909 return ary;
911 else {
912 long capa = ARY_CAPA(ary);
913 long len = RARRAY_LEN(ary);
915 /* Shared roots cannot be embedded because the reference count
916 * (refcnt) is stored in as.heap.aux.capa. */
917 VALUE shared = ary_alloc_heap(0);
918 FL_SET_SHARED_ROOT(shared);
920 if (ARY_EMBED_P(ary)) {
921 VALUE *ptr = ary_heap_alloc_buffer(capa);
922 ARY_SET_PTR(shared, ptr);
923 ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary));
925 FL_UNSET_EMBED(ary);
926 ARY_SET_HEAP_LEN(ary, len);
927 ARY_SET_PTR(ary, ptr);
929 else {
930 ARY_SET_PTR(shared, RARRAY_CONST_PTR(ary));
933 ARY_SET_LEN(shared, capa);
934 ary_mem_clear(shared, len, capa - len);
935 rb_ary_set_shared(ary, shared);
937 ary_verify(shared);
938 ary_verify(ary);
940 return shared;
944 static VALUE
945 ary_make_substitution(VALUE ary)
947 long len = RARRAY_LEN(ary);
949 if (ary_embeddable_p(len)) {
950 VALUE subst = rb_ary_new_capa(len);
951 RUBY_ASSERT(ARY_EMBED_P(subst));
953 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
954 ARY_SET_EMBED_LEN(subst, len);
955 return subst;
957 else {
958 return rb_ary_increment_share(ary_make_shared(ary));
962 VALUE
963 rb_assoc_new(VALUE car, VALUE cdr)
965 return rb_ary_new3(2, car, cdr);
968 VALUE
969 rb_to_array_type(VALUE ary)
971 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
973 #define to_ary rb_to_array_type
975 VALUE
976 rb_check_array_type(VALUE ary)
978 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
981 VALUE
982 rb_check_to_array(VALUE ary)
984 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
987 VALUE
988 rb_to_array(VALUE ary)
990 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
994 * call-seq:
995 * Array.try_convert(object) -> object, new_array, or nil
997 * If +object+ is an +Array+ object, returns +object+.
999 * Otherwise if +object+ responds to <tt>:to_ary</tt>,
1000 * calls <tt>object.to_ary</tt> and returns the result.
1002 * Returns +nil+ if +object+ does not respond to <tt>:to_ary</tt>
1004 * Raises an exception unless <tt>object.to_ary</tt> returns an +Array+ object.
1007 static VALUE
1008 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
1010 return rb_check_array_type(ary);
1013 /* :nodoc: */
1014 static VALUE
1015 rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
1017 VALUE ary;
1019 if (klass == rb_cArray) {
1020 long size = 0;
1021 if (argc > 0 && FIXNUM_P(argv[0])) {
1022 size = FIX2LONG(argv[0]);
1023 if (size < 0) size = 0;
1026 ary = ary_new(klass, size);
1028 rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
1030 else {
1031 ary = rb_class_new_instance_pass_kw(argc, argv, klass);
1034 return ary;
1038 * call-seq:
1039 * Array.new -> new_empty_array
1040 * Array.new(array) -> new_array
1041 * Array.new(size) -> new_array
1042 * Array.new(size, default_value) -> new_array
1043 * Array.new(size) {|index| ... } -> new_array
1045 * Returns a new +Array+.
1047 * With no block and no arguments, returns a new empty +Array+ object.
1049 * With no block and a single +Array+ argument +array+,
1050 * returns a new +Array+ formed from +array+:
1052 * a = Array.new([:foo, 'bar', 2])
1053 * a.class # => Array
1054 * a # => [:foo, "bar", 2]
1056 * With no block and a single Integer argument +size+,
1057 * returns a new +Array+ of the given size
1058 * whose elements are all +nil+:
1060 * a = Array.new(3)
1061 * a # => [nil, nil, nil]
1063 * With no block and arguments +size+ and +default_value+,
1064 * returns an +Array+ of the given size;
1065 * each element is that same +default_value+:
1067 * a = Array.new(3, 'x')
1068 * a # => ['x', 'x', 'x']
1070 * With a block and argument +size+,
1071 * returns an +Array+ of the given size;
1072 * the block is called with each successive integer +index+;
1073 * the element for that +index+ is the return value from the block:
1075 * a = Array.new(3) {|index| "Element #{index}" }
1076 * a # => ["Element 0", "Element 1", "Element 2"]
1078 * Raises ArgumentError if +size+ is negative.
1080 * With a block and no argument,
1081 * or a single argument +0+,
1082 * ignores the block and returns a new empty +Array+.
1085 static VALUE
1086 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1088 long len;
1089 VALUE size, val;
1091 rb_ary_modify(ary);
1092 if (argc == 0) {
1093 rb_ary_reset(ary);
1094 RUBY_ASSERT(ARY_EMBED_P(ary));
1095 RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
1096 if (rb_block_given_p()) {
1097 rb_warning("given block not used");
1099 return ary;
1101 rb_scan_args(argc, argv, "02", &size, &val);
1102 if (argc == 1 && !FIXNUM_P(size)) {
1103 val = rb_check_array_type(size);
1104 if (!NIL_P(val)) {
1105 rb_ary_replace(ary, val);
1106 return ary;
1110 len = NUM2LONG(size);
1111 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1112 if (len < 0) {
1113 rb_raise(rb_eArgError, "negative array size");
1115 if (len > ARY_MAX_SIZE) {
1116 rb_raise(rb_eArgError, "array size too big");
1118 /* recheck after argument conversion */
1119 rb_ary_modify(ary);
1120 ary_resize_capa(ary, len);
1121 if (rb_block_given_p()) {
1122 long i;
1124 if (argc == 2) {
1125 rb_warn("block supersedes default value argument");
1127 for (i=0; i<len; i++) {
1128 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
1129 ARY_SET_LEN(ary, i + 1);
1132 else {
1133 ary_memfill(ary, 0, len, val);
1134 ARY_SET_LEN(ary, len);
1136 return ary;
1140 * Returns a new array populated with the given objects.
1142 * Array.[]( 1, 'a', /^A/) # => [1, "a", /^A/]
1143 * Array[ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1144 * [ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1147 static VALUE
1148 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1150 VALUE ary = ary_new(klass, argc);
1151 if (argc > 0 && argv) {
1152 ary_memcpy(ary, 0, argc, argv);
1153 ARY_SET_LEN(ary, argc);
1156 return ary;
1159 void
1160 rb_ary_store(VALUE ary, long idx, VALUE val)
1162 long len = RARRAY_LEN(ary);
1164 if (idx < 0) {
1165 idx += len;
1166 if (idx < 0) {
1167 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1168 idx - len, -len);
1171 else if (idx >= ARY_MAX_SIZE) {
1172 rb_raise(rb_eIndexError, "index %ld too big", idx);
1175 rb_ary_modify(ary);
1176 if (idx >= ARY_CAPA(ary)) {
1177 ary_double_capa(ary, idx);
1179 if (idx > len) {
1180 ary_mem_clear(ary, len, idx - len + 1);
1183 if (idx >= len) {
1184 ARY_SET_LEN(ary, idx + 1);
1186 ARY_SET(ary, idx, val);
1189 static VALUE
1190 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1192 RUBY_ASSERT(offset >= 0);
1193 RUBY_ASSERT(len >= 0);
1194 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1196 VALUE result = ary_alloc_heap(klass);
1197 size_t embed_capa = ary_embed_capa(result);
1198 if ((size_t)len <= embed_capa) {
1199 FL_SET_EMBED(result);
1200 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
1201 ARY_SET_EMBED_LEN(result, len);
1203 else {
1204 VALUE shared = ary_make_shared(ary);
1206 /* The ary_make_shared call may allocate, which can trigger a GC
1207 * compaction. This can cause the array to be embedded because it has
1208 * a length of 0. */
1209 FL_UNSET_EMBED(result);
1211 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
1212 ARY_SET_LEN(result, RARRAY_LEN(ary));
1213 rb_ary_set_shared(result, shared);
1215 ARY_INCREASE_PTR(result, offset);
1216 ARY_SET_LEN(result, len);
1218 ary_verify(shared);
1221 ary_verify(result);
1222 return result;
1225 static VALUE
1226 ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
1228 RUBY_ASSERT(offset >= 0);
1229 RUBY_ASSERT(len >= 0);
1230 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1231 RUBY_ASSERT(step != 0);
1233 const long orig_len = len;
1235 if (step > 0 && step >= len) {
1236 VALUE result = ary_new(klass, 1);
1237 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1238 const VALUE *values = RARRAY_CONST_PTR(ary);
1240 RB_OBJ_WRITE(result, ptr, values[offset]);
1241 ARY_SET_EMBED_LEN(result, 1);
1242 return result;
1244 else if (step < 0 && step < -len) {
1245 step = -len;
1248 long ustep = (step < 0) ? -step : step;
1249 len = roomof(len, ustep);
1251 long i;
1252 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1254 VALUE result = ary_new(klass, len);
1255 if (ARY_EMBED_P(result)) {
1256 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1257 const VALUE *values = RARRAY_CONST_PTR(ary);
1259 for (i = 0; i < len; ++i) {
1260 RB_OBJ_WRITE(result, ptr+i, values[j]);
1261 j += step;
1263 ARY_SET_EMBED_LEN(result, len);
1265 else {
1266 const VALUE *values = RARRAY_CONST_PTR(ary);
1268 RARRAY_PTR_USE(result, ptr, {
1269 for (i = 0; i < len; ++i) {
1270 RB_OBJ_WRITE(result, ptr+i, values[j]);
1271 j += step;
1274 ARY_SET_LEN(result, len);
1277 return result;
1280 static VALUE
1281 ary_make_shared_copy(VALUE ary)
1283 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
1286 enum ary_take_pos_flags
1288 ARY_TAKE_FIRST = 0,
1289 ARY_TAKE_LAST = 1
1292 static VALUE
1293 ary_take_first_or_last_n(VALUE ary, long n, enum ary_take_pos_flags last)
1295 long len = RARRAY_LEN(ary);
1296 long offset = 0;
1298 if (n > len) {
1299 n = len;
1301 else if (n < 0) {
1302 rb_raise(rb_eArgError, "negative array size");
1304 if (last) {
1305 offset = len - n;
1307 return ary_make_partial(ary, rb_cArray, offset, n);
1310 static VALUE
1311 ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1313 argc = rb_check_arity(argc, 0, 1);
1314 /* the case optional argument is omitted should be handled in
1315 * callers of this function. if another arity case is added,
1316 * this arity check needs to rewrite. */
1317 RUBY_ASSERT_ALWAYS(argc == 1);
1318 return ary_take_first_or_last_n(ary, NUM2LONG(argv[0]), last);
1322 * call-seq:
1323 * array << object -> self
1325 * Appends +object+ to +self+; returns +self+:
1327 * a = [:foo, 'bar', 2]
1328 * a << :baz # => [:foo, "bar", 2, :baz]
1330 * Appends +object+ as one element, even if it is another +Array+:
1332 * a = [:foo, 'bar', 2]
1333 * a1 = a << [3, 4]
1334 * a1 # => [:foo, "bar", 2, [3, 4]]
1338 VALUE
1339 rb_ary_push(VALUE ary, VALUE item)
1341 long idx = RARRAY_LEN((ary_verify(ary), ary));
1342 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1343 RARRAY_PTR_USE(ary, ptr, {
1344 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1346 ARY_SET_LEN(ary, idx + 1);
1347 ary_verify(ary);
1348 return ary;
1351 VALUE
1352 rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1354 long oldlen = RARRAY_LEN(ary);
1355 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1356 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1357 ARY_SET_LEN(ary, oldlen + len);
1358 return ary;
1362 * call-seq:
1363 * array.push(*objects) -> self
1365 * Appends trailing elements.
1367 * Appends each argument in +objects+ to +self+; returns +self+:
1369 * a = [:foo, 'bar', 2]
1370 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1372 * Appends each argument as one element, even if it is another +Array+:
1374 * a = [:foo, 'bar', 2]
1375 * a1 = a.push([:baz, :bat], [:bam, :bad])
1376 * a1 # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1378 * Related: #pop, #shift, #unshift.
1381 static VALUE
1382 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1384 return rb_ary_cat(ary, argv, argc);
1387 VALUE
1388 rb_ary_pop(VALUE ary)
1390 long n;
1391 rb_ary_modify_check(ary);
1392 n = RARRAY_LEN(ary);
1393 if (n == 0) return Qnil;
1394 if (ARY_OWNS_HEAP_P(ary) &&
1395 n * 3 < ARY_CAPA(ary) &&
1396 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1398 ary_resize_capa(ary, n * 2);
1400 --n;
1401 ARY_SET_LEN(ary, n);
1402 ary_verify(ary);
1403 return RARRAY_AREF(ary, n);
1407 * call-seq:
1408 * array.pop -> object or nil
1409 * array.pop(n) -> new_array
1411 * Removes and returns trailing elements.
1413 * When no argument is given and +self+ is not empty,
1414 * removes and returns the last element:
1416 * a = [:foo, 'bar', 2]
1417 * a.pop # => 2
1418 * a # => [:foo, "bar"]
1420 * Returns +nil+ if the array is empty.
1422 * When a non-negative Integer argument +n+ is given and is in range,
1424 * removes and returns the last +n+ elements in a new +Array+:
1425 * a = [:foo, 'bar', 2]
1426 * a.pop(2) # => ["bar", 2]
1428 * If +n+ is positive and out of range,
1429 * removes and returns all elements:
1431 * a = [:foo, 'bar', 2]
1432 * a.pop(50) # => [:foo, "bar", 2]
1434 * Related: #push, #shift, #unshift.
1437 static VALUE
1438 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1440 VALUE result;
1442 if (argc == 0) {
1443 return rb_ary_pop(ary);
1446 rb_ary_modify_check(ary);
1447 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1448 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1449 ary_verify(ary);
1450 return result;
1453 VALUE
1454 rb_ary_shift(VALUE ary)
1456 VALUE top;
1457 long len = RARRAY_LEN(ary);
1459 if (len == 0) {
1460 rb_ary_modify_check(ary);
1461 return Qnil;
1464 top = RARRAY_AREF(ary, 0);
1466 rb_ary_behead(ary, 1);
1468 return top;
1472 * call-seq:
1473 * array.shift -> object or nil
1474 * array.shift(n) -> new_array
1476 * Removes and returns leading elements.
1478 * When no argument is given, removes and returns the first element:
1480 * a = [:foo, 'bar', 2]
1481 * a.shift # => :foo
1482 * a # => ['bar', 2]
1484 * Returns +nil+ if +self+ is empty.
1486 * When positive Integer argument +n+ is given, removes the first +n+ elements;
1487 * returns those elements in a new +Array+:
1489 * a = [:foo, 'bar', 2]
1490 * a.shift(2) # => [:foo, 'bar']
1491 * a # => [2]
1493 * If +n+ is as large as or larger than <tt>self.length</tt>,
1494 * removes all elements; returns those elements in a new +Array+:
1496 * a = [:foo, 'bar', 2]
1497 * a.shift(3) # => [:foo, 'bar', 2]
1499 * If +n+ is zero, returns a new empty +Array+; +self+ is unmodified.
1501 * Related: #push, #pop, #unshift.
1504 static VALUE
1505 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1507 VALUE result;
1508 long n;
1510 if (argc == 0) {
1511 return rb_ary_shift(ary);
1514 rb_ary_modify_check(ary);
1515 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1516 n = RARRAY_LEN(result);
1517 rb_ary_behead(ary,n);
1519 return result;
1522 VALUE
1523 rb_ary_behead(VALUE ary, long n)
1525 if (n <= 0) {
1526 return ary;
1529 rb_ary_modify_check(ary);
1531 if (!ARY_SHARED_P(ary)) {
1532 if (ARY_EMBED_P(ary) || RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
1533 RARRAY_PTR_USE(ary, ptr, {
1534 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary) - n);
1535 }); /* WB: no new reference */
1536 ARY_INCREASE_LEN(ary, -n);
1537 ary_verify(ary);
1538 return ary;
1541 ary_mem_clear(ary, 0, n);
1542 ary_make_shared(ary);
1544 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1545 ary_mem_clear(ary, 0, n);
1548 ARY_INCREASE_PTR(ary, n);
1549 ARY_INCREASE_LEN(ary, -n);
1550 ary_verify(ary);
1552 return ary;
1555 static VALUE
1556 make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
1558 if (head - sharedp < argc) {
1559 long room = capa - len - argc;
1561 room -= room >> 4;
1562 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1563 head = sharedp + argc + room;
1565 ARY_SET_PTR(ary, head - argc);
1566 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1568 ary_verify(ary);
1569 return ARY_SHARED_ROOT(ary);
1572 static VALUE
1573 ary_modify_for_unshift(VALUE ary, int argc)
1575 long len = RARRAY_LEN(ary);
1576 long new_len = len + argc;
1577 long capa;
1578 const VALUE *head, *sharedp;
1580 rb_ary_modify(ary);
1581 capa = ARY_CAPA(ary);
1582 if (capa - (capa >> 6) <= new_len) {
1583 ary_double_capa(ary, new_len);
1586 /* use shared array for big "queues" */
1587 if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
1588 ary_verify(ary);
1590 /* make a room for unshifted items */
1591 capa = ARY_CAPA(ary);
1592 ary_make_shared(ary);
1594 head = sharedp = RARRAY_CONST_PTR(ary);
1595 return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
1597 else {
1598 /* sliding items */
1599 RARRAY_PTR_USE(ary, ptr, {
1600 MEMMOVE(ptr + argc, ptr, VALUE, len);
1603 ary_verify(ary);
1604 return ary;
1608 static VALUE
1609 ary_ensure_room_for_unshift(VALUE ary, int argc)
1611 long len = RARRAY_LEN(ary);
1612 long new_len = len + argc;
1614 if (len > ARY_MAX_SIZE - argc) {
1615 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1617 else if (! ARY_SHARED_P(ary)) {
1618 return ary_modify_for_unshift(ary, argc);
1620 else {
1621 VALUE shared_root = ARY_SHARED_ROOT(ary);
1622 long capa = RARRAY_LEN(shared_root);
1624 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1625 return ary_modify_for_unshift(ary, argc);
1627 else if (new_len > capa) {
1628 return ary_modify_for_unshift(ary, argc);
1630 else {
1631 const VALUE * head = RARRAY_CONST_PTR(ary);
1632 void *sharedp = (void *)RARRAY_CONST_PTR(shared_root);
1634 rb_ary_modify_check(ary);
1635 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1641 * call-seq:
1642 * array.unshift(*objects) -> self
1644 * Prepends the given +objects+ to +self+:
1646 * a = [:foo, 'bar', 2]
1647 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1649 * Related: #push, #pop, #shift.
1652 VALUE
1653 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1655 long len = RARRAY_LEN(ary);
1656 VALUE target_ary;
1658 if (argc == 0) {
1659 rb_ary_modify_check(ary);
1660 return ary;
1663 target_ary = ary_ensure_room_for_unshift(ary, argc);
1664 ary_memcpy0(ary, 0, argc, argv, target_ary);
1665 ARY_SET_LEN(ary, len + argc);
1666 return ary;
1669 VALUE
1670 rb_ary_unshift(VALUE ary, VALUE item)
1672 return rb_ary_unshift_m(1, &item, ary);
1675 /* faster version - use this if you don't need to treat negative offset */
1676 static inline VALUE
1677 rb_ary_elt(VALUE ary, long offset)
1679 long len = RARRAY_LEN(ary);
1680 if (len == 0) return Qnil;
1681 if (offset < 0 || len <= offset) {
1682 return Qnil;
1684 return RARRAY_AREF(ary, offset);
1687 VALUE
1688 rb_ary_entry(VALUE ary, long offset)
1690 return rb_ary_entry_internal(ary, offset);
1693 VALUE
1694 rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
1696 VALUE klass;
1697 long alen = RARRAY_LEN(ary);
1699 if (beg > alen) return Qnil;
1700 if (beg < 0 || len < 0) return Qnil;
1702 if (alen < len || alen < beg + len) {
1703 len = alen - beg;
1705 klass = rb_cArray;
1706 if (len == 0) return ary_new(klass, 0);
1707 if (step == 0)
1708 rb_raise(rb_eArgError, "slice step cannot be zero");
1709 if (step == 1)
1710 return ary_make_partial(ary, klass, beg, len);
1711 else
1712 return ary_make_partial_step(ary, klass, beg, len, step);
1715 VALUE
1716 rb_ary_subseq(VALUE ary, long beg, long len)
1718 return rb_ary_subseq_step(ary, beg, len, 1);
1721 static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1724 * call-seq:
1725 * array[index] -> object or nil
1726 * array[start, length] -> object or nil
1727 * array[range] -> object or nil
1728 * array[aseq] -> object or nil
1729 * array.slice(index) -> object or nil
1730 * array.slice(start, length) -> object or nil
1731 * array.slice(range) -> object or nil
1732 * array.slice(aseq) -> object or nil
1734 * Returns elements from +self+; does not modify +self+.
1736 * In brief:
1738 * a = [:foo, 'bar', 2]
1739 * a[0] # => :foo
1740 * a[-1] # => 2
1741 * a[1, 2] # => ["bar", 2]
1742 * a[0..1] # => [:foo, "bar"]
1743 * a[0..-2] # => [:foo, "bar"]
1744 * a[-2..2] # => ["bar", 2]
1746 * When a single Integer argument +index+ is given, returns the element at offset +index+:
1748 * a = [:foo, 'bar', 2]
1749 * a[0] # => :foo
1750 * a[2] # => 2
1751 * a # => [:foo, "bar", 2]
1753 * If +index+ is negative, counts relative to the end of +self+:
1755 * a = [:foo, 'bar', 2]
1756 * a[-1] # => 2
1757 * a[-2] # => "bar"
1759 * If +index+ is out of range, returns +nil+.
1761 * When two Integer arguments +start+ and +length+ are given,
1762 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1764 * a = [:foo, 'bar', 2]
1765 * a[0, 2] # => [:foo, "bar"]
1766 * a[1, 2] # => ["bar", 2]
1768 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1769 * returns all elements from offset +start+ to the end:
1771 * a = [:foo, 'bar', 2]
1772 * a[0, 4] # => [:foo, "bar", 2]
1773 * a[1, 3] # => ["bar", 2]
1774 * a[2, 2] # => [2]
1776 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1777 * returns a new empty +Array+.
1779 * If +length+ is negative, returns +nil+.
1781 * When a single Range argument +range+ is given,
1782 * treats <tt>range.min</tt> as +start+ above
1783 * and <tt>range.size</tt> as +length+ above:
1785 * a = [:foo, 'bar', 2]
1786 * a[0..1] # => [:foo, "bar"]
1787 * a[1..2] # => ["bar", 2]
1789 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1791 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1793 * a = [:foo, 'bar', 2]
1794 * a[0..-1] # => [:foo, "bar", 2]
1795 * a[0..-2] # => [:foo, "bar"]
1796 * a[0..-3] # => [:foo]
1798 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1800 * a = [:foo, 'bar', 2]
1801 * a[-1..2] # => [2]
1802 * a[-2..2] # => ["bar", 2]
1803 * a[-3..2] # => [:foo, "bar", 2]
1805 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1807 * a = [:foo, 'bar', 2]
1808 * a[4..1] # => nil
1809 * a[4..0] # => nil
1810 * a[4..-1] # => nil
1812 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1813 * returns an +Array+ of elements corresponding to the indexes produced by
1814 * the sequence.
1816 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1817 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1819 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1820 * is larger than array size, throws RangeError.
1822 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1823 * a[(1..11).step(2)]
1824 * # RangeError (((1..11).step(2)) out of range)
1825 * a[(7..).step(2)]
1826 * # RangeError (((7..).step(2)) out of range)
1828 * If given a single argument, and its type is not one of the listed, tries to
1829 * convert it to Integer, and raises if it is impossible:
1831 * a = [:foo, 'bar', 2]
1832 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1833 * a[:foo]
1837 VALUE
1838 rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
1840 rb_check_arity(argc, 1, 2);
1841 if (argc == 2) {
1842 return rb_ary_aref2(ary, argv[0], argv[1]);
1844 return rb_ary_aref1(ary, argv[0]);
1847 static VALUE
1848 rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1850 long beg = NUM2LONG(b);
1851 long len = NUM2LONG(e);
1852 if (beg < 0) {
1853 beg += RARRAY_LEN(ary);
1855 return rb_ary_subseq(ary, beg, len);
1858 VALUE
1859 rb_ary_aref1(VALUE ary, VALUE arg)
1861 long beg, len, step;
1863 /* special case - speeding up */
1864 if (FIXNUM_P(arg)) {
1865 return rb_ary_entry(ary, FIX2LONG(arg));
1867 /* check if idx is Range or ArithmeticSequence */
1868 switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
1869 case Qfalse:
1870 break;
1871 case Qnil:
1872 return Qnil;
1873 default:
1874 return rb_ary_subseq_step(ary, beg, len, step);
1877 return rb_ary_entry(ary, NUM2LONG(arg));
1881 * call-seq:
1882 * array.at(index) -> object
1884 * Returns the element at Integer offset +index+; does not modify +self+.
1885 * a = [:foo, 'bar', 2]
1886 * a.at(0) # => :foo
1887 * a.at(2) # => 2
1891 VALUE
1892 rb_ary_at(VALUE ary, VALUE pos)
1894 return rb_ary_entry(ary, NUM2LONG(pos));
1897 #if 0
1898 static VALUE
1899 rb_ary_first(int argc, VALUE *argv, VALUE ary)
1901 if (argc == 0) {
1902 if (RARRAY_LEN(ary) == 0) return Qnil;
1903 return RARRAY_AREF(ary, 0);
1905 else {
1906 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1909 #endif
1911 static VALUE
1912 ary_first(VALUE self)
1914 return (RARRAY_LEN(self) == 0) ? Qnil : RARRAY_AREF(self, 0);
1917 static VALUE
1918 ary_last(VALUE self)
1920 long len = RARRAY_LEN(self);
1921 return (len == 0) ? Qnil : RARRAY_AREF(self, len-1);
1924 VALUE
1925 rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
1927 if (argc == 0) {
1928 return ary_last(ary);
1930 else {
1931 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1936 * call-seq:
1937 * array.fetch(index) -> element
1938 * array.fetch(index, default_value) -> element
1939 * array.fetch(index) {|index| ... } -> element
1941 * Returns the element at offset +index+.
1943 * With the single Integer argument +index+,
1944 * returns the element at offset +index+:
1946 * a = [:foo, 'bar', 2]
1947 * a.fetch(1) # => "bar"
1949 * If +index+ is negative, counts from the end of the array:
1951 * a = [:foo, 'bar', 2]
1952 * a.fetch(-1) # => 2
1953 * a.fetch(-2) # => "bar"
1955 * With arguments +index+ and +default_value+,
1956 * returns the element at offset +index+ if index is in range,
1957 * otherwise returns +default_value+:
1959 * a = [:foo, 'bar', 2]
1960 * a.fetch(1, nil) # => "bar"
1962 * With argument +index+ and a block,
1963 * returns the element at offset +index+ if index is in range
1964 * (and the block is not called); otherwise calls the block with index and returns its return value:
1966 * a = [:foo, 'bar', 2]
1967 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
1968 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
1972 static VALUE
1973 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
1975 VALUE pos, ifnone;
1976 long block_given;
1977 long idx;
1979 rb_scan_args(argc, argv, "11", &pos, &ifnone);
1980 block_given = rb_block_given_p();
1981 if (block_given && argc == 2) {
1982 rb_warn("block supersedes default value argument");
1984 idx = NUM2LONG(pos);
1986 if (idx < 0) {
1987 idx += RARRAY_LEN(ary);
1989 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
1990 if (block_given) return rb_yield(pos);
1991 if (argc == 1) {
1992 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
1993 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
1995 return ifnone;
1997 return RARRAY_AREF(ary, idx);
2001 * call-seq:
2002 * array.index(object) -> integer or nil
2003 * array.index {|element| ... } -> integer or nil
2004 * array.index -> new_enumerator
2006 * Returns the index of a specified element.
2008 * When argument +object+ is given but no block,
2009 * returns the index of the first element +element+
2010 * for which <tt>object == element</tt>:
2012 * a = [:foo, 'bar', 2, 'bar']
2013 * a.index('bar') # => 1
2015 * Returns +nil+ if no such element found.
2017 * When both argument +object+ and a block are given,
2018 * calls the block with each successive element;
2019 * returns the index of the first element for which the block returns a truthy value:
2021 * a = [:foo, 'bar', 2, 'bar']
2022 * a.index {|element| element == 'bar' } # => 1
2024 * Returns +nil+ if the block never returns a truthy value.
2026 * When neither an argument nor a block is given, returns a new Enumerator:
2028 * a = [:foo, 'bar', 2]
2029 * e = a.index
2030 * e # => #<Enumerator: [:foo, "bar", 2]:index>
2031 * e.each {|element| element == 'bar' } # => 1
2033 * Related: #rindex.
2036 static VALUE
2037 rb_ary_index(int argc, VALUE *argv, VALUE ary)
2039 VALUE val;
2040 long i;
2042 if (argc == 0) {
2043 RETURN_ENUMERATOR(ary, 0, 0);
2044 for (i=0; i<RARRAY_LEN(ary); i++) {
2045 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2046 return LONG2NUM(i);
2049 return Qnil;
2051 rb_check_arity(argc, 0, 1);
2052 val = argv[0];
2053 if (rb_block_given_p())
2054 rb_warn("given block not used");
2055 for (i=0; i<RARRAY_LEN(ary); i++) {
2056 VALUE e = RARRAY_AREF(ary, i);
2057 if (rb_equal(e, val)) {
2058 return LONG2NUM(i);
2061 return Qnil;
2065 * call-seq:
2066 * array.rindex(object) -> integer or nil
2067 * array.rindex {|element| ... } -> integer or nil
2068 * array.rindex -> new_enumerator
2070 * Returns the index of the last element for which <tt>object == element</tt>.
2072 * When argument +object+ is given but no block, returns the index of the last such element found:
2074 * a = [:foo, 'bar', 2, 'bar']
2075 * a.rindex('bar') # => 3
2077 * Returns +nil+ if no such object found.
2079 * When a block is given but no argument, calls the block with each successive element;
2080 * returns the index of the last element for which the block returns a truthy value:
2082 * a = [:foo, 'bar', 2, 'bar']
2083 * a.rindex {|element| element == 'bar' } # => 3
2085 * Returns +nil+ if the block never returns a truthy value.
2087 * When neither an argument nor a block is given, returns a new Enumerator:
2089 * a = [:foo, 'bar', 2, 'bar']
2090 * e = a.rindex
2091 * e # => #<Enumerator: [:foo, "bar", 2, "bar"]:rindex>
2092 * e.each {|element| element == 'bar' } # => 3
2094 * Related: #index.
2097 static VALUE
2098 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
2100 VALUE val;
2101 long i = RARRAY_LEN(ary), len;
2103 if (argc == 0) {
2104 RETURN_ENUMERATOR(ary, 0, 0);
2105 while (i--) {
2106 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
2107 return LONG2NUM(i);
2108 if (i > (len = RARRAY_LEN(ary))) {
2109 i = len;
2112 return Qnil;
2114 rb_check_arity(argc, 0, 1);
2115 val = argv[0];
2116 if (rb_block_given_p())
2117 rb_warn("given block not used");
2118 while (i--) {
2119 VALUE e = RARRAY_AREF(ary, i);
2120 if (rb_equal(e, val)) {
2121 return LONG2NUM(i);
2123 if (i > RARRAY_LEN(ary)) {
2124 break;
2127 return Qnil;
2130 VALUE
2131 rb_ary_to_ary(VALUE obj)
2133 VALUE tmp = rb_check_array_type(obj);
2135 if (!NIL_P(tmp)) return tmp;
2136 return rb_ary_new3(1, obj);
2139 static void
2140 rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
2142 long olen;
2143 long rofs;
2145 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2146 olen = RARRAY_LEN(ary);
2147 if (beg < 0) {
2148 beg += olen;
2149 if (beg < 0) {
2150 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2151 beg - olen, -olen);
2154 if (olen < len || olen < beg + len) {
2155 len = olen - beg;
2159 const VALUE *optr = RARRAY_CONST_PTR(ary);
2160 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
2163 if (beg >= olen) {
2164 VALUE target_ary;
2165 if (beg > ARY_MAX_SIZE - rlen) {
2166 rb_raise(rb_eIndexError, "index %ld too big", beg);
2168 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2169 len = beg + rlen;
2170 ary_mem_clear(ary, olen, beg - olen);
2171 if (rlen > 0) {
2172 if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
2173 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2175 ARY_SET_LEN(ary, len);
2177 else {
2178 long alen;
2180 if (olen - len > ARY_MAX_SIZE - rlen) {
2181 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2183 rb_ary_modify(ary);
2184 alen = olen + rlen - len;
2185 if (alen >= ARY_CAPA(ary)) {
2186 ary_double_capa(ary, alen);
2189 if (len != rlen) {
2190 RARRAY_PTR_USE(ary, ptr,
2191 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2192 VALUE, olen - (beg + len)));
2193 ARY_SET_LEN(ary, alen);
2195 if (rlen > 0) {
2196 if (rofs == -1) {
2197 rb_gc_writebarrier_remember(ary);
2199 else {
2200 /* In this case, we're copying from a region in this array, so
2201 * we don't need to fire the write barrier. */
2202 rptr = RARRAY_CONST_PTR(ary) + rofs;
2205 /* do not use RARRAY_PTR() because it can causes GC.
2206 * ary can contain T_NONE object because it is not cleared.
2208 RARRAY_PTR_USE(ary, ptr,
2209 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2214 void
2215 rb_ary_set_len(VALUE ary, long len)
2217 long capa;
2219 rb_ary_modify_check(ary);
2220 if (ARY_SHARED_P(ary)) {
2221 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2223 if (len > (capa = (long)ARY_CAPA(ary))) {
2224 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2226 ARY_SET_LEN(ary, len);
2229 VALUE
2230 rb_ary_resize(VALUE ary, long len)
2232 long olen;
2234 rb_ary_modify(ary);
2235 olen = RARRAY_LEN(ary);
2236 if (len == olen) return ary;
2237 if (len > ARY_MAX_SIZE) {
2238 rb_raise(rb_eIndexError, "index %ld too big", len);
2240 if (len > olen) {
2241 if (len >= ARY_CAPA(ary)) {
2242 ary_double_capa(ary, len);
2244 ary_mem_clear(ary, olen, len - olen);
2245 ARY_SET_LEN(ary, len);
2247 else if (ARY_EMBED_P(ary)) {
2248 ARY_SET_EMBED_LEN(ary, len);
2250 else if (len <= ary_embed_capa(ary)) {
2251 const VALUE *ptr = ARY_HEAP_PTR(ary);
2252 long ptr_capa = ARY_HEAP_SIZE(ary);
2253 bool is_malloc_ptr = !ARY_SHARED_P(ary);
2255 FL_SET_EMBED(ary);
2257 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
2258 ARY_SET_EMBED_LEN(ary, len);
2260 if (is_malloc_ptr) ruby_sized_xfree((void *)ptr, ptr_capa);
2262 else {
2263 if (olen > len + ARY_DEFAULT_SIZE) {
2264 size_t new_capa = ary_heap_realloc(ary, len);
2265 ARY_SET_CAPA(ary, new_capa);
2267 ARY_SET_HEAP_LEN(ary, len);
2269 ary_verify(ary);
2270 return ary;
2273 static VALUE
2274 ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2276 rb_ary_store(ary, key, val);
2277 return val;
2280 static VALUE
2281 ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2283 VALUE rpl = rb_ary_to_ary(val);
2284 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl));
2285 RB_GC_GUARD(rpl);
2286 return val;
2290 * call-seq:
2291 * array[index] = object -> object
2292 * array[start, length] = object -> object
2293 * array[range] = object -> object
2295 * Assigns elements in +self+; returns the given +object+.
2297 * In brief:
2299 * a_orig = [:foo, 'bar', 2]
2300 * # With argument index.
2301 * a = a_orig.dup
2302 * a[0] = 'foo' # => "foo"
2303 * a # => ["foo", "bar", 2]
2304 * a = a_orig.dup
2305 * a[7] = 'foo' # => "foo"
2306 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2307 * # With arguments start and length.
2308 * a = a_orig.dup
2309 * a[0, 2] = 'foo' # => "foo"
2310 * a # => ["foo", 2]
2311 * a = a_orig.dup
2312 * a[6, 50] = 'foo' # => "foo"
2313 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2314 * # With argument range.
2315 * a = a_orig.dup
2316 * a[0..1] = 'foo' # => "foo"
2317 * a # => ["foo", 2]
2318 * a = a_orig.dup
2319 * a[6..50] = 'foo' # => "foo"
2320 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2322 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2324 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2326 * a = [:foo, 'bar', 2]
2327 * a[0] = 'foo' # => "foo"
2328 * a # => ["foo", "bar", 2]
2330 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2332 * a = [:foo, 'bar', 2]
2333 * a[7] = 'foo' # => "foo"
2334 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2336 * If +index+ is negative, counts backwards from the end of the array:
2338 * a = [:foo, 'bar', 2]
2339 * a[-1] = 'two' # => "two"
2340 * a # => [:foo, "bar", "two"]
2342 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2343 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2344 * and assigns +object+ at offset +start+:
2346 * a = [:foo, 'bar', 2]
2347 * a[0, 2] = 'foo' # => "foo"
2348 * a # => ["foo", 2]
2350 * If +start+ is negative, counts backwards from the end of the array:
2352 * a = [:foo, 'bar', 2]
2353 * a[-2, 2] = 'foo' # => "foo"
2354 * a # => [:foo, "foo"]
2356 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2357 * extends the array with +nil+, assigns +object+ at offset +start+,
2358 * and ignores +length+:
2360 * a = [:foo, 'bar', 2]
2361 * a[6, 50] = 'foo' # => "foo"
2362 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2364 * If +length+ is zero, shifts elements at and following offset +start+
2365 * and assigns +object+ at offset +start+:
2367 * a = [:foo, 'bar', 2]
2368 * a[1, 0] = 'foo' # => "foo"
2369 * a # => [:foo, "foo", "bar", 2]
2371 * If +length+ is too large for the existing array, does not extend the array:
2373 * a = [:foo, 'bar', 2]
2374 * a[1, 5] = 'foo' # => "foo"
2375 * a # => [:foo, "foo"]
2377 * When Range argument +range+ is given and +object+ is not an +Array+,
2378 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2379 * and assigns +object+ at offset +start+:
2381 * a = [:foo, 'bar', 2]
2382 * a[0..1] = 'foo' # => "foo"
2383 * a # => ["foo", 2]
2385 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2387 * a = [:foo, 'bar', 2]
2388 * a[-2..2] = 'foo' # => "foo"
2389 * a # => [:foo, "foo"]
2391 * If the array length is less than <tt>range.begin</tt>,
2392 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2393 * and ignores +length+:
2395 * a = [:foo, 'bar', 2]
2396 * a[6..50] = 'foo' # => "foo"
2397 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2399 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2400 * and assigns +object+ at offset +start+:
2402 * a = [:foo, 'bar', 2]
2403 * a[1..0] = 'foo' # => "foo"
2404 * a # => [:foo, "foo", "bar", 2]
2406 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2407 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2409 * a = [:foo, 'bar', 2]
2410 * a[1..-1] = 'foo' # => "foo"
2411 * a # => [:foo, "foo"]
2412 * a = [:foo, 'bar', 2]
2413 * a[1..-2] = 'foo' # => "foo"
2414 * a # => [:foo, "foo", 2]
2415 * a = [:foo, 'bar', 2]
2416 * a[1..-3] = 'foo' # => "foo"
2417 * a # => [:foo, "foo", "bar", 2]
2418 * a = [:foo, 'bar', 2]
2420 * If <tt>range.end</tt> is too large for the existing array,
2421 * replaces array elements, but does not extend the array with +nil+ values:
2423 * a = [:foo, 'bar', 2]
2424 * a[1..5] = 'foo' # => "foo"
2425 * a # => [:foo, "foo"]
2429 static VALUE
2430 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2432 long offset, beg, len;
2434 rb_check_arity(argc, 2, 3);
2435 rb_ary_modify_check(ary);
2436 if (argc == 3) {
2437 beg = NUM2LONG(argv[0]);
2438 len = NUM2LONG(argv[1]);
2439 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2441 if (FIXNUM_P(argv[0])) {
2442 offset = FIX2LONG(argv[0]);
2443 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2445 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2446 /* check if idx is Range */
2447 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2450 offset = NUM2LONG(argv[0]);
2451 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2455 * call-seq:
2456 * array.insert(index, *objects) -> self
2458 * Inserts given +objects+ before or after the element at Integer index +offset+;
2459 * returns +self+.
2461 * When +index+ is non-negative, inserts all given +objects+
2462 * before the element at offset +index+:
2464 * a = [:foo, 'bar', 2]
2465 * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2]
2467 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2469 * a = [:foo, 'bar', 2]
2470 * a.insert(5, :bat, :bam)
2471 * a # => [:foo, "bar", 2, nil, nil, :bat, :bam]
2473 * Does nothing if no objects given:
2475 * a = [:foo, 'bar', 2]
2476 * a.insert(1)
2477 * a.insert(50)
2478 * a.insert(-50)
2479 * a # => [:foo, "bar", 2]
2481 * When +index+ is negative, inserts all given +objects+
2482 * _after_ the element at offset <tt>index+self.size</tt>:
2484 * a = [:foo, 'bar', 2]
2485 * a.insert(-2, :bat, :bam)
2486 * a # => [:foo, "bar", :bat, :bam, 2]
2490 static VALUE
2491 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2493 long pos;
2495 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
2496 rb_ary_modify_check(ary);
2497 pos = NUM2LONG(argv[0]);
2498 if (argc == 1) return ary;
2499 if (pos == -1) {
2500 pos = RARRAY_LEN(ary);
2502 else if (pos < 0) {
2503 long minpos = -RARRAY_LEN(ary) - 1;
2504 if (pos < minpos) {
2505 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2506 pos, minpos);
2508 pos++;
2510 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2511 return ary;
2514 static VALUE
2515 rb_ary_length(VALUE ary);
2517 static VALUE
2518 ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2520 return rb_ary_length(ary);
2523 // Primitive to avoid a race condition in Array#each.
2524 // Return `true` and write `value` and `index` if the element exists.
2525 static VALUE
2526 ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
2528 long i = NUM2LONG(*index);
2529 if (i >= RARRAY_LEN(self)) {
2530 return Qfalse;
2532 *value = RARRAY_AREF(self, i);
2533 *index = LONG2NUM(i + 1);
2534 return Qtrue;
2537 VALUE
2538 rb_ary_each(VALUE ary)
2540 long i;
2541 ary_verify(ary);
2542 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2543 for (i=0; i<RARRAY_LEN(ary); i++) {
2544 rb_yield(RARRAY_AREF(ary, i));
2546 return ary;
2550 * call-seq:
2551 * array.each_index {|index| ... } -> self
2552 * array.each_index -> Enumerator
2554 * Iterates over array indexes.
2556 * When a block given, passes each successive array index to the block;
2557 * returns +self+:
2559 * a = [:foo, 'bar', 2]
2560 * a.each_index {|index| puts "#{index} #{a[index]}" }
2562 * Output:
2564 * 0 foo
2565 * 1 bar
2566 * 2 2
2568 * Allows the array to be modified during iteration:
2570 * a = [:foo, 'bar', 2]
2571 * a.each_index {|index| puts index; a.clear if index > 0 }
2573 * Output:
2578 * When no block given, returns a new Enumerator:
2580 * a = [:foo, 'bar', 2]
2581 * e = a.each_index
2582 * e # => #<Enumerator: [:foo, "bar", 2]:each_index>
2583 * a1 = e.each {|index| puts "#{index} #{a[index]}"}
2585 * Output:
2587 * 0 foo
2588 * 1 bar
2589 * 2 2
2591 * Related: #each, #reverse_each.
2594 static VALUE
2595 rb_ary_each_index(VALUE ary)
2597 long i;
2598 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2600 for (i=0; i<RARRAY_LEN(ary); i++) {
2601 rb_yield(LONG2NUM(i));
2603 return ary;
2607 * call-seq:
2608 * array.reverse_each {|element| ... } -> self
2609 * array.reverse_each -> Enumerator
2611 * Iterates backwards over array elements.
2613 * When a block given, passes, in reverse order, each element to the block;
2614 * returns +self+:
2616 * a = [:foo, 'bar', 2]
2617 * a.reverse_each {|element| puts "#{element.class} #{element}" }
2619 * Output:
2621 * Integer 2
2622 * String bar
2623 * Symbol foo
2625 * Allows the array to be modified during iteration:
2627 * a = [:foo, 'bar', 2]
2628 * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2630 * Output:
2633 * bar
2635 * When no block given, returns a new Enumerator:
2637 * a = [:foo, 'bar', 2]
2638 * e = a.reverse_each
2639 * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
2640 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2642 * Output:
2644 * Integer 2
2645 * String bar
2646 * Symbol foo
2648 * Related: #each, #each_index.
2651 static VALUE
2652 rb_ary_reverse_each(VALUE ary)
2654 long len;
2656 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2657 len = RARRAY_LEN(ary);
2658 while (len--) {
2659 long nlen;
2660 rb_yield(RARRAY_AREF(ary, len));
2661 nlen = RARRAY_LEN(ary);
2662 if (nlen < len) {
2663 len = nlen;
2666 return ary;
2670 * call-seq:
2671 * array.length -> an_integer
2673 * Returns the count of elements in +self+.
2676 static VALUE
2677 rb_ary_length(VALUE ary)
2679 long len = RARRAY_LEN(ary);
2680 return LONG2NUM(len);
2684 * call-seq:
2685 * array.empty? -> true or false
2687 * Returns +true+ if the count of elements in +self+ is zero,
2688 * +false+ otherwise.
2691 static VALUE
2692 rb_ary_empty_p(VALUE ary)
2694 return RBOOL(RARRAY_LEN(ary) == 0);
2697 VALUE
2698 rb_ary_dup(VALUE ary)
2700 long len = RARRAY_LEN(ary);
2701 VALUE dup = rb_ary_new2(len);
2702 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2703 ARY_SET_LEN(dup, len);
2705 ary_verify(ary);
2706 ary_verify(dup);
2707 return dup;
2710 VALUE
2711 rb_ary_resurrect(VALUE ary)
2713 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2716 extern VALUE rb_output_fs;
2718 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2720 static VALUE
2721 recursive_join(VALUE obj, VALUE argp, int recur)
2723 VALUE *arg = (VALUE *)argp;
2724 VALUE ary = arg[0];
2725 VALUE sep = arg[1];
2726 VALUE result = arg[2];
2727 int *first = (int *)arg[3];
2729 if (recur) {
2730 rb_raise(rb_eArgError, "recursive array join");
2732 else {
2733 ary_join_1(obj, ary, sep, 0, result, first);
2735 return Qnil;
2738 static long
2739 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2741 long i;
2742 VALUE val;
2744 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2745 for (i=0; i<max; i++) {
2746 val = RARRAY_AREF(ary, i);
2747 if (!RB_TYPE_P(val, T_STRING)) break;
2748 if (i > 0 && !NIL_P(sep))
2749 rb_str_buf_append(result, sep);
2750 rb_str_buf_append(result, val);
2752 return i;
2755 static void
2756 ary_join_1_str(VALUE dst, VALUE src, int *first)
2758 rb_str_buf_append(dst, src);
2759 if (*first) {
2760 rb_enc_copy(dst, src);
2761 *first = FALSE;
2765 static void
2766 ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
2768 if (val == ary) {
2769 rb_raise(rb_eArgError, "recursive array join");
2771 else {
2772 VALUE args[4];
2774 *first = FALSE;
2775 args[0] = val;
2776 args[1] = sep;
2777 args[2] = result;
2778 args[3] = (VALUE)first;
2779 rb_exec_recursive(recursive_join, obj, (VALUE)args);
2783 static void
2784 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
2786 VALUE val, tmp;
2788 for (; i<RARRAY_LEN(ary); i++) {
2789 if (i > 0 && !NIL_P(sep))
2790 rb_str_buf_append(result, sep);
2792 val = RARRAY_AREF(ary, i);
2793 if (RB_TYPE_P(val, T_STRING)) {
2794 ary_join_1_str(result, val, first);
2796 else if (RB_TYPE_P(val, T_ARRAY)) {
2797 ary_join_1_ary(val, ary, sep, result, val, first);
2799 else if (!NIL_P(tmp = rb_check_string_type(val))) {
2800 ary_join_1_str(result, tmp, first);
2802 else if (!NIL_P(tmp = rb_check_array_type(val))) {
2803 ary_join_1_ary(val, ary, sep, result, tmp, first);
2805 else {
2806 ary_join_1_str(result, rb_obj_as_string(val), first);
2811 VALUE
2812 rb_ary_join(VALUE ary, VALUE sep)
2814 long len = 1, i;
2815 VALUE val, tmp, result;
2817 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
2819 if (!NIL_P(sep)) {
2820 StringValue(sep);
2821 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
2823 for (i=0; i<RARRAY_LEN(ary); i++) {
2824 val = RARRAY_AREF(ary, i);
2825 tmp = rb_check_string_type(val);
2827 if (NIL_P(tmp) || tmp != val) {
2828 int first;
2829 long n = RARRAY_LEN(ary);
2830 if (i > n) i = n;
2831 result = rb_str_buf_new(len + (n-i)*10);
2832 rb_enc_associate(result, rb_usascii_encoding());
2833 i = ary_join_0(ary, sep, i, result);
2834 first = i == 0;
2835 ary_join_1(ary, ary, sep, i, result, &first);
2836 return result;
2839 len += RSTRING_LEN(tmp);
2842 result = rb_str_new(0, len);
2843 rb_str_set_len(result, 0);
2845 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
2847 return result;
2851 * call-seq:
2852 * array.join ->new_string
2853 * array.join(separator = $,) -> new_string
2855 * Returns the new String formed by joining the array elements after conversion.
2856 * For each element +element+:
2858 * - Uses <tt>element.to_s</tt> if +element+ is not a <tt>kind_of?(Array)</tt>.
2859 * - Uses recursive <tt>element.join(separator)</tt> if +element+ is a <tt>kind_of?(Array)</tt>.
2861 * With no argument, joins using the output field separator, <tt>$,</tt>:
2863 * a = [:foo, 'bar', 2]
2864 * $, # => nil
2865 * a.join # => "foobar2"
2867 * With \string argument +separator+, joins using that separator:
2869 * a = [:foo, 'bar', 2]
2870 * a.join("\n") # => "foo\nbar\n2"
2872 * Joins recursively for nested Arrays:
2874 * a = [:foo, [:bar, [:baz, :bat]]]
2875 * a.join # => "foobarbazbat"
2878 static VALUE
2879 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
2881 VALUE sep;
2883 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
2884 sep = rb_output_fs;
2885 if (!NIL_P(sep)) {
2886 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
2890 return rb_ary_join(ary, sep);
2893 static VALUE
2894 inspect_ary(VALUE ary, VALUE dummy, int recur)
2896 long i;
2897 VALUE s, str;
2899 if (recur) return rb_usascii_str_new_cstr("[...]");
2900 str = rb_str_buf_new2("[");
2901 for (i=0; i<RARRAY_LEN(ary); i++) {
2902 s = rb_inspect(RARRAY_AREF(ary, i));
2903 if (i > 0) rb_str_buf_cat2(str, ", ");
2904 else rb_enc_copy(str, s);
2905 rb_str_buf_append(str, s);
2907 rb_str_buf_cat2(str, "]");
2908 return str;
2912 * call-seq:
2913 * array.inspect -> new_string
2915 * Returns the new String formed by calling method <tt>#inspect</tt>
2916 * on each array element:
2918 * a = [:foo, 'bar', 2]
2919 * a.inspect # => "[:foo, \"bar\", 2]"
2923 static VALUE
2924 rb_ary_inspect(VALUE ary)
2926 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
2927 return rb_exec_recursive(inspect_ary, ary, 0);
2930 VALUE
2931 rb_ary_to_s(VALUE ary)
2933 return rb_ary_inspect(ary);
2937 * call-seq:
2938 * to_a -> self or new_array
2940 * When +self+ is an instance of +Array+, returns +self+:
2942 * a = [:foo, 'bar', 2]
2943 * a.to_a # => [:foo, "bar", 2]
2945 * Otherwise, returns a new +Array+ containing the elements of +self+:
2947 * class MyArray < Array; end
2948 * a = MyArray.new(['foo', 'bar', 'two'])
2949 * a.instance_of?(Array) # => false
2950 * a.kind_of?(Array) # => true
2951 * a1 = a.to_a
2952 * a1 # => ["foo", "bar", "two"]
2953 * a1.class # => Array # Not MyArray
2957 static VALUE
2958 rb_ary_to_a(VALUE ary)
2960 if (rb_obj_class(ary) != rb_cArray) {
2961 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
2962 rb_ary_replace(dup, ary);
2963 return dup;
2965 return ary;
2969 * call-seq:
2970 * array.to_h -> new_hash
2971 * array.to_h {|item| ... } -> new_hash
2973 * Returns a new Hash formed from +self+.
2975 * When a block is given, calls the block with each array element;
2976 * the block must return a 2-element +Array+ whose two elements
2977 * form a key-value pair in the returned Hash:
2979 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
2980 * h = a.to_h {|item| [item, item] }
2981 * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
2983 * When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
2984 * each sub-array is formed into a key-value pair in the new Hash:
2986 * [].to_h # => {}
2987 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
2988 * h = a.to_h
2989 * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
2993 static VALUE
2994 rb_ary_to_h(VALUE ary)
2996 long i;
2997 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
2998 int block_given = rb_block_given_p();
3000 for (i=0; i<RARRAY_LEN(ary); i++) {
3001 const VALUE e = rb_ary_elt(ary, i);
3002 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3003 const VALUE key_value_pair = rb_check_array_type(elt);
3004 if (NIL_P(key_value_pair)) {
3005 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
3006 rb_obj_class(elt), i);
3008 if (RARRAY_LEN(key_value_pair) != 2) {
3009 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
3010 i, RARRAY_LEN(key_value_pair));
3012 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3014 return hash;
3018 * call-seq:
3019 * array.to_ary -> self
3021 * Returns +self+.
3024 static VALUE
3025 rb_ary_to_ary_m(VALUE ary)
3027 return ary;
3030 static void
3031 ary_reverse(VALUE *p1, VALUE *p2)
3033 while (p1 < p2) {
3034 VALUE tmp = *p1;
3035 *p1++ = *p2;
3036 *p2-- = tmp;
3040 VALUE
3041 rb_ary_reverse(VALUE ary)
3043 VALUE *p2;
3044 long len = RARRAY_LEN(ary);
3046 rb_ary_modify(ary);
3047 if (len > 1) {
3048 RARRAY_PTR_USE(ary, p1, {
3049 p2 = p1 + len - 1; /* points last item */
3050 ary_reverse(p1, p2);
3051 }); /* WB: no new reference */
3053 return ary;
3057 * call-seq:
3058 * array.reverse! -> self
3060 * Reverses +self+ in place:
3062 * a = ['foo', 'bar', 'two']
3063 * a.reverse! # => ["two", "bar", "foo"]
3067 static VALUE
3068 rb_ary_reverse_bang(VALUE ary)
3070 return rb_ary_reverse(ary);
3074 * call-seq:
3075 * array.reverse -> new_array
3077 * Returns a new +Array+ with the elements of +self+ in reverse order:
3079 * a = ['foo', 'bar', 'two']
3080 * a1 = a.reverse
3081 * a1 # => ["two", "bar", "foo"]
3085 static VALUE
3086 rb_ary_reverse_m(VALUE ary)
3088 long len = RARRAY_LEN(ary);
3089 VALUE dup = rb_ary_new2(len);
3091 if (len > 0) {
3092 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3093 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3094 do *p2-- = *p1++; while (--len > 0);
3096 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3097 return dup;
3100 static inline long
3101 rotate_count(long cnt, long len)
3103 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3106 static void
3107 ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3109 if (cnt == 1) {
3110 VALUE tmp = *ptr;
3111 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3112 *(ptr + len - 1) = tmp;
3114 else if (cnt == len - 1) {
3115 VALUE tmp = *(ptr + len - 1);
3116 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3117 *ptr = tmp;
3119 else {
3120 --len;
3121 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3122 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3123 if (len > 0) ary_reverse(ptr, ptr + len);
3127 VALUE
3128 rb_ary_rotate(VALUE ary, long cnt)
3130 rb_ary_modify(ary);
3132 if (cnt != 0) {
3133 long len = RARRAY_LEN(ary);
3134 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3135 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3136 return ary;
3139 return Qnil;
3143 * call-seq:
3144 * array.rotate! -> self
3145 * array.rotate!(count) -> self
3147 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3149 * When no argument given, rotates the first element to the last position:
3151 * a = [:foo, 'bar', 2, 'bar']
3152 * a.rotate! # => ["bar", 2, "bar", :foo]
3154 * When given a non-negative Integer +count+,
3155 * rotates +count+ elements from the beginning to the end:
3157 * a = [:foo, 'bar', 2]
3158 * a.rotate!(2)
3159 * a # => [2, :foo, "bar"]
3161 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3163 * a = [:foo, 'bar', 2]
3164 * a.rotate!(20)
3165 * a # => [2, :foo, "bar"]
3167 * If +count+ is zero, returns +self+ unmodified:
3169 * a = [:foo, 'bar', 2]
3170 * a.rotate!(0)
3171 * a # => [:foo, "bar", 2]
3173 * When given a negative Integer +count+, rotates in the opposite direction,
3174 * from end to beginning:
3176 * a = [:foo, 'bar', 2]
3177 * a.rotate!(-2)
3178 * a # => ["bar", 2, :foo]
3180 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3182 * a = [:foo, 'bar', 2]
3183 * a.rotate!(-5)
3184 * a # => ["bar", 2, :foo]
3188 static VALUE
3189 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3191 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3192 rb_ary_rotate(ary, n);
3193 return ary;
3197 * call-seq:
3198 * array.rotate -> new_array
3199 * array.rotate(count) -> new_array
3201 * Returns a new +Array+ formed from +self+ with elements
3202 * rotated from one end to the other.
3204 * When no argument given, returns a new +Array+ that is like +self+,
3205 * except that the first element has been rotated to the last position:
3207 * a = [:foo, 'bar', 2, 'bar']
3208 * a1 = a.rotate
3209 * a1 # => ["bar", 2, "bar", :foo]
3211 * When given a non-negative Integer +count+,
3212 * returns a new +Array+ with +count+ elements rotated from the beginning to the end:
3214 * a = [:foo, 'bar', 2]
3215 * a1 = a.rotate(2)
3216 * a1 # => [2, :foo, "bar"]
3218 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3220 * a = [:foo, 'bar', 2]
3221 * a1 = a.rotate(20)
3222 * a1 # => [2, :foo, "bar"]
3224 * If +count+ is zero, returns a copy of +self+, unmodified:
3226 * a = [:foo, 'bar', 2]
3227 * a1 = a.rotate(0)
3228 * a1 # => [:foo, "bar", 2]
3230 * When given a negative Integer +count+, rotates in the opposite direction,
3231 * from end to beginning:
3233 * a = [:foo, 'bar', 2]
3234 * a1 = a.rotate(-2)
3235 * a1 # => ["bar", 2, :foo]
3237 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3239 * a = [:foo, 'bar', 2]
3240 * a1 = a.rotate(-5)
3241 * a1 # => ["bar", 2, :foo]
3245 static VALUE
3246 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3248 VALUE rotated;
3249 const VALUE *ptr;
3250 long len;
3251 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3253 len = RARRAY_LEN(ary);
3254 rotated = rb_ary_new2(len);
3255 if (len > 0) {
3256 cnt = rotate_count(cnt, len);
3257 ptr = RARRAY_CONST_PTR(ary);
3258 len -= cnt;
3259 ary_memcpy(rotated, 0, len, ptr + cnt);
3260 ary_memcpy(rotated, len, cnt, ptr);
3262 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3263 return rotated;
3266 struct ary_sort_data {
3267 VALUE ary;
3268 VALUE receiver;
3271 static VALUE
3272 sort_reentered(VALUE ary)
3274 if (RBASIC(ary)->klass) {
3275 rb_raise(rb_eRuntimeError, "sort reentered");
3277 return Qnil;
3280 static void
3281 sort_returned(struct ary_sort_data *data)
3283 if (rb_obj_frozen_p(data->receiver)) {
3284 rb_raise(rb_eFrozenError, "array frozen during sort");
3286 sort_reentered(data->ary);
3289 static int
3290 sort_1(const void *ap, const void *bp, void *dummy)
3292 struct ary_sort_data *data = dummy;
3293 VALUE retval = sort_reentered(data->ary);
3294 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3295 VALUE args[2];
3296 int n;
3298 args[0] = a;
3299 args[1] = b;
3300 retval = rb_yield_values2(2, args);
3301 n = rb_cmpint(retval, a, b);
3302 sort_returned(data);
3303 return n;
3306 static int
3307 sort_2(const void *ap, const void *bp, void *dummy)
3309 struct ary_sort_data *data = dummy;
3310 VALUE retval = sort_reentered(data->ary);
3311 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3312 int n;
3314 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3315 if ((long)a > (long)b) return 1;
3316 if ((long)a < (long)b) return -1;
3317 return 0;
3319 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3320 return rb_str_cmp(a, b);
3322 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3323 return rb_float_cmp(a, b);
3326 retval = rb_funcallv(a, id_cmp, 1, &b);
3327 n = rb_cmpint(retval, a, b);
3328 sort_returned(data);
3330 return n;
3334 * call-seq:
3335 * array.sort! -> self
3336 * array.sort! {|a, b| ... } -> self
3338 * Returns +self+ with its elements sorted in place.
3340 * With no block, compares elements using operator <tt><=></tt>
3341 * (see Comparable):
3343 * a = 'abcde'.split('').shuffle
3344 * a # => ["e", "b", "d", "a", "c"]
3345 * a.sort!
3346 * a # => ["a", "b", "c", "d", "e"]
3348 * With a block, calls the block with each element pair;
3349 * for each element pair +a+ and +b+, the block should return an integer:
3351 * - Negative when +b+ is to follow +a+.
3352 * - Zero when +a+ and +b+ are equivalent.
3353 * - Positive when +a+ is to follow +b+.
3355 * Example:
3357 * a = 'abcde'.split('').shuffle
3358 * a # => ["e", "b", "d", "a", "c"]
3359 * a.sort! {|a, b| a <=> b }
3360 * a # => ["a", "b", "c", "d", "e"]
3361 * a.sort! {|a, b| b <=> a }
3362 * a # => ["e", "d", "c", "b", "a"]
3364 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3365 * and may be unstable:
3367 * a = 'abcde'.split('').shuffle
3368 * a # => ["e", "b", "d", "a", "c"]
3369 * a.sort! {|a, b| 0 }
3370 * a # => ["d", "e", "c", "a", "b"]
3374 VALUE
3375 rb_ary_sort_bang(VALUE ary)
3377 rb_ary_modify(ary);
3378 RUBY_ASSERT(!ARY_SHARED_P(ary));
3379 if (RARRAY_LEN(ary) > 1) {
3380 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3381 struct ary_sort_data data;
3382 long len = RARRAY_LEN(ary);
3383 RBASIC_CLEAR_CLASS(tmp);
3384 data.ary = tmp;
3385 data.receiver = ary;
3386 RARRAY_PTR_USE(tmp, ptr, {
3387 ruby_qsort(ptr, len, sizeof(VALUE),
3388 rb_block_given_p()?sort_1:sort_2, &data);
3389 }); /* WB: no new reference */
3390 rb_ary_modify(ary);
3391 if (ARY_EMBED_P(tmp)) {
3392 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3393 rb_ary_unshare(ary);
3394 FL_SET_EMBED(ary);
3396 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3397 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3399 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3400 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3402 else {
3403 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3404 FL_UNSET_SHARED(ary);
3405 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3407 else {
3408 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3409 if (ARY_EMBED_P(ary)) {
3410 FL_UNSET_EMBED(ary);
3412 else if (ARY_SHARED_P(ary)) {
3413 /* ary might be destructively operated in the given block */
3414 rb_ary_unshare(ary);
3416 else {
3417 ary_heap_free(ary);
3419 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3420 ARY_SET_HEAP_LEN(ary, len);
3421 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3423 /* tmp was lost ownership for the ptr */
3424 FL_UNSET(tmp, FL_FREEZE);
3425 FL_SET_EMBED(tmp);
3426 ARY_SET_EMBED_LEN(tmp, 0);
3427 FL_SET(tmp, FL_FREEZE);
3429 /* tmp will be GC'ed. */
3430 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3432 ary_verify(ary);
3433 return ary;
3437 * call-seq:
3438 * array.sort -> new_array
3439 * array.sort {|a, b| ... } -> new_array
3441 * Returns a new +Array+ whose elements are those from +self+, sorted.
3443 * With no block, compares elements using operator <tt><=></tt>
3444 * (see Comparable):
3446 * a = 'abcde'.split('').shuffle
3447 * a # => ["e", "b", "d", "a", "c"]
3448 * a1 = a.sort
3449 * a1 # => ["a", "b", "c", "d", "e"]
3451 * With a block, calls the block with each element pair;
3452 * for each element pair +a+ and +b+, the block should return an integer:
3454 * - Negative when +b+ is to follow +a+.
3455 * - Zero when +a+ and +b+ are equivalent.
3456 * - Positive when +a+ is to follow +b+.
3458 * Example:
3460 * a = 'abcde'.split('').shuffle
3461 * a # => ["e", "b", "d", "a", "c"]
3462 * a1 = a.sort {|a, b| a <=> b }
3463 * a1 # => ["a", "b", "c", "d", "e"]
3464 * a2 = a.sort {|a, b| b <=> a }
3465 * a2 # => ["e", "d", "c", "b", "a"]
3467 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3468 * and may be unstable:
3470 * a = 'abcde'.split('').shuffle
3471 * a # => ["e", "b", "d", "a", "c"]
3472 * a1 = a.sort {|a, b| 0 }
3473 * a1 # => ["c", "e", "b", "d", "a"]
3475 * Related: Enumerable#sort_by.
3478 VALUE
3479 rb_ary_sort(VALUE ary)
3481 ary = rb_ary_dup(ary);
3482 rb_ary_sort_bang(ary);
3483 return ary;
3486 static VALUE rb_ary_bsearch_index(VALUE ary);
3489 * call-seq:
3490 * array.bsearch {|element| ... } -> object
3491 * array.bsearch -> new_enumerator
3493 * Returns an element from +self+ selected by a binary search.
3495 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3498 static VALUE
3499 rb_ary_bsearch(VALUE ary)
3501 VALUE index_result = rb_ary_bsearch_index(ary);
3503 if (FIXNUM_P(index_result)) {
3504 return rb_ary_entry(ary, FIX2LONG(index_result));
3506 return index_result;
3510 * call-seq:
3511 * array.bsearch_index {|element| ... } -> integer or nil
3512 * array.bsearch_index -> new_enumerator
3514 * Searches +self+ as described at method #bsearch,
3515 * but returns the _index_ of the found element instead of the element itself.
3518 static VALUE
3519 rb_ary_bsearch_index(VALUE ary)
3521 long low = 0, high = RARRAY_LEN(ary), mid;
3522 int smaller = 0, satisfied = 0;
3523 VALUE v, val;
3525 RETURN_ENUMERATOR(ary, 0, 0);
3526 while (low < high) {
3527 mid = low + ((high - low) / 2);
3528 val = rb_ary_entry(ary, mid);
3529 v = rb_yield(val);
3530 if (FIXNUM_P(v)) {
3531 if (v == INT2FIX(0)) return INT2FIX(mid);
3532 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3534 else if (v == Qtrue) {
3535 satisfied = 1;
3536 smaller = 1;
3538 else if (!RTEST(v)) {
3539 smaller = 0;
3541 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3542 const VALUE zero = INT2FIX(0);
3543 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3544 case 0: return INT2FIX(mid);
3545 case 1: smaller = 0; break;
3546 case -1: smaller = 1;
3549 else {
3550 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3551 " (must be numeric, true, false or nil)",
3552 rb_obj_class(v));
3554 if (smaller) {
3555 high = mid;
3557 else {
3558 low = mid + 1;
3561 if (!satisfied) return Qnil;
3562 return INT2FIX(low);
3566 static VALUE
3567 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3569 return rb_yield(i);
3573 * call-seq:
3574 * array.sort_by! {|element| ... } -> self
3575 * array.sort_by! -> new_enumerator
3577 * Sorts the elements of +self+ in place,
3578 * using an ordering determined by the block; returns self.
3580 * Calls the block with each successive element;
3581 * sorts elements based on the values returned from the block.
3583 * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
3585 * This example sorts strings based on their sizes:
3587 * a = ['aaaa', 'bbb', 'cc', 'd']
3588 * a.sort_by! {|element| element.size }
3589 * a # => ["d", "cc", "bbb", "aaaa"]
3591 * Returns a new Enumerator if no block given:
3593 * a = ['aaaa', 'bbb', 'cc', 'd']
3594 * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
3598 static VALUE
3599 rb_ary_sort_by_bang(VALUE ary)
3601 VALUE sorted;
3603 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3604 rb_ary_modify(ary);
3605 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3606 rb_ary_replace(ary, sorted);
3607 return ary;
3612 * call-seq:
3613 * array.map {|element| ... } -> new_array
3614 * array.map -> new_enumerator
3616 * Calls the block, if given, with each element of +self+;
3617 * returns a new +Array+ whose elements are the return values from the block:
3619 * a = [:foo, 'bar', 2]
3620 * a1 = a.map {|element| element.class }
3621 * a1 # => [Symbol, String, Integer]
3623 * Returns a new Enumerator if no block given:
3624 * a = [:foo, 'bar', 2]
3625 * a1 = a.map
3626 * a1 # => #<Enumerator: [:foo, "bar", 2]:map>
3630 static VALUE
3631 rb_ary_collect(VALUE ary)
3633 long i;
3634 VALUE collect;
3636 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3637 collect = rb_ary_new2(RARRAY_LEN(ary));
3638 for (i = 0; i < RARRAY_LEN(ary); i++) {
3639 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3641 return collect;
3646 * call-seq:
3647 * array.map! {|element| ... } -> self
3648 * array.map! -> new_enumerator
3650 * Calls the block, if given, with each element;
3651 * replaces the element with the block's return value:
3653 * a = [:foo, 'bar', 2]
3654 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3656 * Returns a new Enumerator if no block given:
3658 * a = [:foo, 'bar', 2]
3659 * a1 = a.map!
3660 * a1 # => #<Enumerator: [:foo, "bar", 2]:map!>
3664 static VALUE
3665 rb_ary_collect_bang(VALUE ary)
3667 long i;
3669 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3670 rb_ary_modify(ary);
3671 for (i = 0; i < RARRAY_LEN(ary); i++) {
3672 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3674 return ary;
3677 VALUE
3678 rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3680 VALUE result = rb_ary_new2(argc);
3681 long beg, len, i, j;
3683 for (i=0; i<argc; i++) {
3684 if (FIXNUM_P(argv[i])) {
3685 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3686 continue;
3688 /* check if idx is Range */
3689 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3690 long end = olen < beg+len ? olen : beg+len;
3691 for (j = beg; j < end; j++) {
3692 rb_ary_push(result, (*func)(obj, j));
3694 if (beg + len > j)
3695 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3696 continue;
3698 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3700 return result;
3703 static VALUE
3704 append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3706 long beg, len;
3707 if (FIXNUM_P(idx)) {
3708 beg = FIX2LONG(idx);
3710 /* check if idx is Range */
3711 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3712 if (len > 0) {
3713 const VALUE *const src = RARRAY_CONST_PTR(ary);
3714 const long end = beg + len;
3715 const long prevlen = RARRAY_LEN(result);
3716 if (beg < olen) {
3717 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3719 if (end > olen) {
3720 rb_ary_store(result, prevlen + len - 1, Qnil);
3723 return result;
3725 else {
3726 beg = NUM2LONG(idx);
3728 return rb_ary_push(result, rb_ary_entry(ary, beg));
3732 * call-seq:
3733 * array.values_at(*indexes) -> new_array
3735 * Returns a new +Array+ whose elements are the elements
3736 * of +self+ at the given Integer or Range +indexes+.
3738 * For each positive +index+, returns the element at offset +index+:
3740 * a = [:foo, 'bar', 2]
3741 * a.values_at(0, 2) # => [:foo, 2]
3742 * a.values_at(0..1) # => [:foo, "bar"]
3744 * The given +indexes+ may be in any order, and may repeat:
3746 * a = [:foo, 'bar', 2]
3747 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3748 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3750 * Assigns +nil+ for an +index+ that is too large:
3752 * a = [:foo, 'bar', 2]
3753 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3755 * Returns a new empty +Array+ if no arguments given.
3757 * For each negative +index+, counts backward from the end of the array:
3759 * a = [:foo, 'bar', 2]
3760 * a.values_at(-1, -3) # => [2, :foo]
3762 * Assigns +nil+ for an +index+ that is too small:
3764 * a = [:foo, 'bar', 2]
3765 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3767 * The given +indexes+ may have a mixture of signs:
3769 * a = [:foo, 'bar', 2]
3770 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3774 static VALUE
3775 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
3777 long i, olen = RARRAY_LEN(ary);
3778 VALUE result = rb_ary_new_capa(argc);
3779 for (i = 0; i < argc; ++i) {
3780 append_values_at_single(result, ary, olen, argv[i]);
3782 RB_GC_GUARD(ary);
3783 return result;
3788 * call-seq:
3789 * array.select {|element| ... } -> new_array
3790 * array.select -> new_enumerator
3792 * Calls the block, if given, with each element of +self+;
3793 * returns a new +Array+ containing those elements of +self+
3794 * for which the block returns a truthy value:
3796 * a = [:foo, 'bar', 2, :bam]
3797 * a1 = a.select {|element| element.to_s.start_with?('b') }
3798 * a1 # => ["bar", :bam]
3800 * Returns a new Enumerator if no block given:
3802 * a = [:foo, 'bar', 2, :bam]
3803 * a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
3807 static VALUE
3808 rb_ary_select(VALUE ary)
3810 VALUE result;
3811 long i;
3813 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3814 result = rb_ary_new2(RARRAY_LEN(ary));
3815 for (i = 0; i < RARRAY_LEN(ary); i++) {
3816 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
3817 rb_ary_push(result, rb_ary_elt(ary, i));
3820 return result;
3823 struct select_bang_arg {
3824 VALUE ary;
3825 long len[2];
3828 static VALUE
3829 select_bang_i(VALUE a)
3831 volatile struct select_bang_arg *arg = (void *)a;
3832 VALUE ary = arg->ary;
3833 long i1, i2;
3835 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
3836 VALUE v = RARRAY_AREF(ary, i1);
3837 if (!RTEST(rb_yield(v))) continue;
3838 if (i1 != i2) {
3839 rb_ary_store(ary, i2, v);
3841 arg->len[1] = ++i2;
3843 return (i1 == i2) ? Qnil : ary;
3846 static VALUE
3847 select_bang_ensure(VALUE a)
3849 volatile struct select_bang_arg *arg = (void *)a;
3850 VALUE ary = arg->ary;
3851 long len = RARRAY_LEN(ary);
3852 long i1 = arg->len[0], i2 = arg->len[1];
3854 if (i2 < len && i2 < i1) {
3855 long tail = 0;
3856 rb_ary_modify(ary);
3857 if (i1 < len) {
3858 tail = len - i1;
3859 RARRAY_PTR_USE(ary, ptr, {
3860 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
3863 ARY_SET_LEN(ary, i2 + tail);
3865 return ary;
3869 * call-seq:
3870 * array.select! {|element| ... } -> self or nil
3871 * array.select! -> new_enumerator
3873 * Calls the block, if given with each element of +self+;
3874 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3876 * Returns +self+ if any elements were removed:
3878 * a = [:foo, 'bar', 2, :bam]
3879 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3881 * Returns +nil+ if no elements were removed.
3883 * Returns a new Enumerator if no block given:
3885 * a = [:foo, 'bar', 2, :bam]
3886 * a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
3890 static VALUE
3891 rb_ary_select_bang(VALUE ary)
3893 struct select_bang_arg args;
3895 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3896 rb_ary_modify(ary);
3898 args.ary = ary;
3899 args.len[0] = args.len[1] = 0;
3900 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
3904 * call-seq:
3905 * array.keep_if {|element| ... } -> self
3906 * array.keep_if -> new_enumeration
3908 * Retains those elements for which the block returns a truthy value;
3909 * deletes all other elements; returns +self+:
3911 * a = [:foo, 'bar', 2, :bam]
3912 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3914 * Returns a new Enumerator if no block given:
3916 * a = [:foo, 'bar', 2, :bam]
3917 * a.keep_if # => #<Enumerator: [:foo, "bar", 2, :bam]:keep_if>
3921 static VALUE
3922 rb_ary_keep_if(VALUE ary)
3924 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3925 rb_ary_select_bang(ary);
3926 return ary;
3929 static void
3930 ary_resize_smaller(VALUE ary, long len)
3932 rb_ary_modify(ary);
3933 if (RARRAY_LEN(ary) > len) {
3934 ARY_SET_LEN(ary, len);
3935 if (len * 2 < ARY_CAPA(ary) &&
3936 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
3937 ary_resize_capa(ary, len * 2);
3943 * call-seq:
3944 * array.delete(obj) -> deleted_object
3945 * array.delete(obj) {|nosuch| ... } -> deleted_object or block_return
3947 * Removes zero or more elements from +self+.
3949 * When no block is given,
3950 * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>;
3951 * returns the last deleted element:
3953 * s1 = 'bar'; s2 = 'bar'
3954 * a = [:foo, s1, 2, s2]
3955 * a.delete('bar') # => "bar"
3956 * a # => [:foo, 2]
3958 * Returns +nil+ if no elements removed.
3960 * When a block is given,
3961 * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>.
3963 * If any such elements are found, ignores the block
3964 * and returns the last deleted element:
3966 * s1 = 'bar'; s2 = 'bar'
3967 * a = [:foo, s1, 2, s2]
3968 * deleted_obj = a.delete('bar') {|obj| fail 'Cannot happen' }
3969 * a # => [:foo, 2]
3971 * If no such elements are found, returns the block's return value:
3973 * a = [:foo, 'bar', 2]
3974 * a.delete(:nosuch) {|obj| "#{obj} not found" } # => "nosuch not found"
3978 VALUE
3979 rb_ary_delete(VALUE ary, VALUE item)
3981 VALUE v = item;
3982 long i1, i2;
3984 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
3985 VALUE e = RARRAY_AREF(ary, i1);
3987 if (rb_equal(e, item)) {
3988 v = e;
3989 continue;
3991 if (i1 != i2) {
3992 rb_ary_store(ary, i2, e);
3994 i2++;
3996 if (RARRAY_LEN(ary) == i2) {
3997 if (rb_block_given_p()) {
3998 return rb_yield(item);
4000 return Qnil;
4003 ary_resize_smaller(ary, i2);
4005 ary_verify(ary);
4006 return v;
4009 void
4010 rb_ary_delete_same(VALUE ary, VALUE item)
4012 long i1, i2;
4014 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4015 VALUE e = RARRAY_AREF(ary, i1);
4017 if (e == item) {
4018 continue;
4020 if (i1 != i2) {
4021 rb_ary_store(ary, i2, e);
4023 i2++;
4025 if (RARRAY_LEN(ary) == i2) {
4026 return;
4029 ary_resize_smaller(ary, i2);
4032 VALUE
4033 rb_ary_delete_at(VALUE ary, long pos)
4035 long len = RARRAY_LEN(ary);
4036 VALUE del;
4038 if (pos >= len) return Qnil;
4039 if (pos < 0) {
4040 pos += len;
4041 if (pos < 0) return Qnil;
4044 rb_ary_modify(ary);
4045 del = RARRAY_AREF(ary, pos);
4046 RARRAY_PTR_USE(ary, ptr, {
4047 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4049 ARY_INCREASE_LEN(ary, -1);
4050 ary_verify(ary);
4051 return del;
4055 * call-seq:
4056 * array.delete_at(index) -> deleted_object or nil
4058 * Deletes an element from +self+, per the given Integer +index+.
4060 * When +index+ is non-negative, deletes the element at offset +index+:
4062 * a = [:foo, 'bar', 2]
4063 * a.delete_at(1) # => "bar"
4064 * a # => [:foo, 2]
4066 * If index is too large, returns +nil+.
4068 * When +index+ is negative, counts backward from the end of the array:
4070 * a = [:foo, 'bar', 2]
4071 * a.delete_at(-2) # => "bar"
4072 * a # => [:foo, 2]
4074 * If +index+ is too small (far from zero), returns nil.
4077 static VALUE
4078 rb_ary_delete_at_m(VALUE ary, VALUE pos)
4080 return rb_ary_delete_at(ary, NUM2LONG(pos));
4083 static VALUE
4084 ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
4086 const long orig_len = RARRAY_LEN(ary);
4088 if (len < 0) {
4089 return Qnil;
4091 else if (pos < -orig_len) {
4092 return Qnil;
4094 else if (pos < 0) {
4095 pos += orig_len;
4097 else if (orig_len < pos) {
4098 return Qnil;
4100 if (orig_len < pos + len) {
4101 len = orig_len - pos;
4103 if (len == 0) {
4104 return rb_ary_new2(0);
4106 else {
4107 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4108 rb_ary_splice(ary, pos, len, 0, 0);
4109 return arg2;
4114 * call-seq:
4115 * array.slice!(n) -> object or nil
4116 * array.slice!(start, length) -> new_array or nil
4117 * array.slice!(range) -> new_array or nil
4119 * Removes and returns elements from +self+.
4121 * When the only argument is an Integer +n+,
4122 * removes and returns the _nth_ element in +self+:
4124 * a = [:foo, 'bar', 2]
4125 * a.slice!(1) # => "bar"
4126 * a # => [:foo, 2]
4128 * If +n+ is negative, counts backwards from the end of +self+:
4130 * a = [:foo, 'bar', 2]
4131 * a.slice!(-1) # => 2
4132 * a # => [:foo, "bar"]
4134 * If +n+ is out of range, returns +nil+.
4136 * When the only arguments are Integers +start+ and +length+,
4137 * removes +length+ elements from +self+ beginning at offset +start+;
4138 * returns the deleted objects in a new +Array+:
4140 * a = [:foo, 'bar', 2]
4141 * a.slice!(0, 2) # => [:foo, "bar"]
4142 * a # => [2]
4144 * If <tt>start + length</tt> exceeds the array size,
4145 * removes and returns all elements from offset +start+ to the end:
4147 * a = [:foo, 'bar', 2]
4148 * a.slice!(1, 50) # => ["bar", 2]
4149 * a # => [:foo]
4151 * If <tt>start == a.size</tt> and +length+ is non-negative,
4152 * returns a new empty +Array+.
4154 * If +length+ is negative, returns +nil+.
4156 * When the only argument is a Range object +range+,
4157 * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
4159 * a = [:foo, 'bar', 2]
4160 * a.slice!(1..2) # => ["bar", 2]
4161 * a # => [:foo]
4163 * If <tt>range.start == a.size</tt>, returns a new empty +Array+.
4165 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
4167 * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
4169 * a = [:foo, 'bar', 2]
4170 * a.slice!(0..-2) # => [:foo, "bar"]
4171 * a # => [2]
4173 * If <tt>range.start</tt> is negative,
4174 * calculates the start index backwards from the end of the array:
4176 * a = [:foo, 'bar', 2]
4177 * a.slice!(-2..2) # => ["bar", 2]
4178 * a # => [:foo]
4182 static VALUE
4183 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4185 VALUE arg1;
4186 long pos, len;
4188 rb_ary_modify_check(ary);
4189 rb_check_arity(argc, 1, 2);
4190 arg1 = argv[0];
4192 if (argc == 2) {
4193 pos = NUM2LONG(argv[0]);
4194 len = NUM2LONG(argv[1]);
4195 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4198 if (!FIXNUM_P(arg1)) {
4199 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4200 case Qtrue:
4201 /* valid range */
4202 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4203 case Qnil:
4204 /* invalid range */
4205 return Qnil;
4206 default:
4207 /* not a range */
4208 break;
4212 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4215 static VALUE
4216 ary_reject(VALUE orig, VALUE result)
4218 long i;
4220 for (i = 0; i < RARRAY_LEN(orig); i++) {
4221 VALUE v = RARRAY_AREF(orig, i);
4223 if (!RTEST(rb_yield(v))) {
4224 rb_ary_push(result, v);
4227 return result;
4230 static VALUE
4231 reject_bang_i(VALUE a)
4233 volatile struct select_bang_arg *arg = (void *)a;
4234 VALUE ary = arg->ary;
4235 long i1, i2;
4237 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4238 VALUE v = RARRAY_AREF(ary, i1);
4239 if (RTEST(rb_yield(v))) continue;
4240 if (i1 != i2) {
4241 rb_ary_store(ary, i2, v);
4243 arg->len[1] = ++i2;
4245 return (i1 == i2) ? Qnil : ary;
4248 static VALUE
4249 ary_reject_bang(VALUE ary)
4251 struct select_bang_arg args;
4252 rb_ary_modify_check(ary);
4253 args.ary = ary;
4254 args.len[0] = args.len[1] = 0;
4255 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4259 * call-seq:
4260 * array.reject! {|element| ... } -> self or nil
4261 * array.reject! -> new_enumerator
4263 * Removes each element for which the block returns a truthy value.
4265 * Returns +self+ if any elements removed:
4267 * a = [:foo, 'bar', 2, 'bat']
4268 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4270 * Returns +nil+ if no elements removed.
4272 * Returns a new Enumerator if no block given:
4274 * a = [:foo, 'bar', 2]
4275 * a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
4279 static VALUE
4280 rb_ary_reject_bang(VALUE ary)
4282 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4283 rb_ary_modify(ary);
4284 return ary_reject_bang(ary);
4288 * call-seq:
4289 * array.reject {|element| ... } -> new_array
4290 * array.reject -> new_enumerator
4292 * Returns a new +Array+ whose elements are all those from +self+
4293 * for which the block returns +false+ or +nil+:
4295 * a = [:foo, 'bar', 2, 'bat']
4296 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4297 * a1 # => [:foo, 2]
4299 * Returns a new Enumerator if no block given:
4301 * a = [:foo, 'bar', 2]
4302 * a.reject # => #<Enumerator: [:foo, "bar", 2]:reject>
4306 static VALUE
4307 rb_ary_reject(VALUE ary)
4309 VALUE rejected_ary;
4311 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4312 rejected_ary = rb_ary_new();
4313 ary_reject(ary, rejected_ary);
4314 return rejected_ary;
4318 * call-seq:
4319 * array.delete_if {|element| ... } -> self
4320 * array.delete_if -> Enumerator
4322 * Removes each element in +self+ for which the block returns a truthy value;
4323 * returns +self+:
4325 * a = [:foo, 'bar', 2, 'bat']
4326 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4328 * Returns a new Enumerator if no block given:
4330 * a = [:foo, 'bar', 2]
4331 * a.delete_if # => #<Enumerator: [:foo, "bar", 2]:delete_if>
4335 static VALUE
4336 rb_ary_delete_if(VALUE ary)
4338 ary_verify(ary);
4339 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4340 ary_reject_bang(ary);
4341 return ary;
4344 static VALUE
4345 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4347 VALUE *args = (VALUE *)cbarg;
4348 if (argc > 1) val = rb_ary_new4(argc, argv);
4349 rb_ary_push(args[0], val);
4350 if (--args[1] == 0) rb_iter_break();
4351 return Qnil;
4354 static VALUE
4355 take_items(VALUE obj, long n)
4357 VALUE result = rb_check_array_type(obj);
4358 VALUE args[2];
4360 if (n == 0) return result;
4361 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4362 result = rb_ary_new2(n);
4363 args[0] = result; args[1] = (VALUE)n;
4364 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4365 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4366 rb_obj_class(obj));
4367 return result;
4372 * call-seq:
4373 * array.zip(*other_arrays) -> new_array
4374 * array.zip(*other_arrays) {|other_array| ... } -> nil
4376 * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
4377 * whose elements are Arrays.
4379 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4380 * and contains:
4382 * - The _nth_ element of +self+.
4383 * - The _nth_ element of each of the +other_arrays+.
4385 * If all +other_arrays+ and +self+ are the same size:
4387 * a = [:a0, :a1, :a2, :a3]
4388 * b = [:b0, :b1, :b2, :b3]
4389 * c = [:c0, :c1, :c2, :c3]
4390 * d = a.zip(b, c)
4391 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4393 * If any array in +other_arrays+ is smaller than +self+,
4394 * fills to <tt>self.size</tt> with +nil+:
4396 * a = [:a0, :a1, :a2, :a3]
4397 * b = [:b0, :b1, :b2]
4398 * c = [:c0, :c1]
4399 * d = a.zip(b, c)
4400 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4402 * If any array in +other_arrays+ is larger than +self+,
4403 * its trailing elements are ignored:
4405 * a = [:a0, :a1, :a2, :a3]
4406 * b = [:b0, :b1, :b2, :b3, :b4]
4407 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4408 * d = a.zip(b, c)
4409 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4411 * If an argument is not an array, it extracts the values by calling #each:
4413 * a = [:a0, :a1, :a2, :a2]
4414 * b = 1..4
4415 * c = a.zip(b)
4416 * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
4418 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
4420 * a = [:a0, :a1, :a2, :a3]
4421 * b = [:b0, :b1, :b2, :b3]
4422 * c = [:c0, :c1, :c2, :c3]
4423 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4425 * Output:
4427 * [:a0, :b0, :c0]
4428 * [:a1, :b1, :c1]
4429 * [:a2, :b2, :c2]
4430 * [:a3, :b3, :c3]
4434 static VALUE
4435 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4437 int i, j;
4438 long len = RARRAY_LEN(ary);
4439 VALUE result = Qnil;
4441 for (i=0; i<argc; i++) {
4442 argv[i] = take_items(argv[i], len);
4445 if (rb_block_given_p()) {
4446 int arity = rb_block_arity();
4448 if (arity > 1) {
4449 VALUE work, *tmp;
4451 tmp = ALLOCV_N(VALUE, work, argc+1);
4453 for (i=0; i<RARRAY_LEN(ary); i++) {
4454 tmp[0] = RARRAY_AREF(ary, i);
4455 for (j=0; j<argc; j++) {
4456 tmp[j+1] = rb_ary_elt(argv[j], i);
4458 rb_yield_values2(argc+1, tmp);
4461 if (work) ALLOCV_END(work);
4463 else {
4464 for (i=0; i<RARRAY_LEN(ary); i++) {
4465 VALUE tmp = rb_ary_new2(argc+1);
4467 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4468 for (j=0; j<argc; j++) {
4469 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4471 rb_yield(tmp);
4475 else {
4476 result = rb_ary_new_capa(len);
4478 for (i=0; i<len; i++) {
4479 VALUE tmp = rb_ary_new_capa(argc+1);
4481 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4482 for (j=0; j<argc; j++) {
4483 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4485 rb_ary_push(result, tmp);
4489 return result;
4493 * call-seq:
4494 * array.transpose -> new_array
4496 * Transposes the rows and columns in an +Array+ of Arrays;
4497 * the nested Arrays must all be the same size:
4499 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4500 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4504 static VALUE
4505 rb_ary_transpose(VALUE ary)
4507 long elen = -1, alen, i, j;
4508 VALUE tmp, result = 0;
4510 alen = RARRAY_LEN(ary);
4511 if (alen == 0) return rb_ary_dup(ary);
4512 for (i=0; i<alen; i++) {
4513 tmp = to_ary(rb_ary_elt(ary, i));
4514 if (elen < 0) { /* first element */
4515 elen = RARRAY_LEN(tmp);
4516 result = rb_ary_new2(elen);
4517 for (j=0; j<elen; j++) {
4518 rb_ary_store(result, j, rb_ary_new2(alen));
4521 else if (elen != RARRAY_LEN(tmp)) {
4522 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4523 RARRAY_LEN(tmp), elen);
4525 for (j=0; j<elen; j++) {
4526 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4529 return result;
4533 * call-seq:
4534 * array.replace(other_array) -> self
4536 * Replaces the content of +self+ with the content of +other_array+; returns +self+:
4538 * a = [:foo, 'bar', 2]
4539 * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3]
4543 VALUE
4544 rb_ary_replace(VALUE copy, VALUE orig)
4546 rb_ary_modify_check(copy);
4547 orig = to_ary(orig);
4548 if (copy == orig) return copy;
4550 rb_ary_reset(copy);
4552 /* orig has enough space to embed the contents of orig. */
4553 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4554 RUBY_ASSERT(ARY_EMBED_P(copy));
4555 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4556 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4558 /* orig is embedded but copy does not have enough space to embed the
4559 * contents of orig. */
4560 else if (ARY_EMBED_P(orig)) {
4561 long len = ARY_EMBED_LEN(orig);
4562 VALUE *ptr = ary_heap_alloc_buffer(len);
4564 FL_UNSET_EMBED(copy);
4565 ARY_SET_PTR(copy, ptr);
4566 ARY_SET_LEN(copy, len);
4567 ARY_SET_CAPA(copy, len);
4569 // No allocation and exception expected that could leave `copy` in a
4570 // bad state from the edits above.
4571 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
4573 /* Otherwise, orig is on heap and copy does not have enough space to embed
4574 * the contents of orig. */
4575 else {
4576 VALUE shared_root = ary_make_shared(orig);
4577 FL_UNSET_EMBED(copy);
4578 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4579 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4580 rb_ary_set_shared(copy, shared_root);
4582 ary_verify(copy);
4583 return copy;
4587 * call-seq:
4588 * array.clear -> self
4590 * Removes all elements from +self+:
4592 * a = [:foo, 'bar', 2]
4593 * a.clear # => []
4597 VALUE
4598 rb_ary_clear(VALUE ary)
4600 rb_ary_modify_check(ary);
4601 if (ARY_SHARED_P(ary)) {
4602 if (!ARY_EMBED_P(ary)) {
4603 rb_ary_unshare(ary);
4604 FL_SET_EMBED(ary);
4605 ARY_SET_EMBED_LEN(ary, 0);
4608 else {
4609 ARY_SET_LEN(ary, 0);
4610 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4611 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
4614 ary_verify(ary);
4615 return ary;
4619 * call-seq:
4620 * array.fill(obj) -> self
4621 * array.fill(obj, start) -> self
4622 * array.fill(obj, start, length) -> self
4623 * array.fill(obj, range) -> self
4624 * array.fill {|index| ... } -> self
4625 * array.fill(start) {|index| ... } -> self
4626 * array.fill(start, length) {|index| ... } -> self
4627 * array.fill(range) {|index| ... } -> self
4629 * Replaces specified elements in +self+ with specified objects; returns +self+.
4631 * With argument +obj+ and no block given, replaces all elements with that one object:
4633 * a = ['a', 'b', 'c', 'd']
4634 * a # => ["a", "b", "c", "d"]
4635 * a.fill(:X) # => [:X, :X, :X, :X]
4637 * With arguments +obj+ and Integer +start+, and no block given,
4638 * replaces elements based on the given start.
4640 * If +start+ is in range (<tt>0 <= start < array.size</tt>),
4641 * replaces all elements from offset +start+ through the end:
4643 * a = ['a', 'b', 'c', 'd']
4644 * a.fill(:X, 2) # => ["a", "b", :X, :X]
4646 * If +start+ is too large (<tt>start >= array.size</tt>), does nothing:
4648 * a = ['a', 'b', 'c', 'd']
4649 * a.fill(:X, 4) # => ["a", "b", "c", "d"]
4650 * a = ['a', 'b', 'c', 'd']
4651 * a.fill(:X, 5) # => ["a", "b", "c", "d"]
4653 * If +start+ is negative, counts from the end (starting index is <tt>start + array.size</tt>):
4655 * a = ['a', 'b', 'c', 'd']
4656 * a.fill(:X, -2) # => ["a", "b", :X, :X]
4658 * If +start+ is too small (less than and far from zero), replaces all elements:
4660 * a = ['a', 'b', 'c', 'd']
4661 * a.fill(:X, -6) # => [:X, :X, :X, :X]
4662 * a = ['a', 'b', 'c', 'd']
4663 * a.fill(:X, -50) # => [:X, :X, :X, :X]
4665 * With arguments +obj+, Integer +start+, and Integer +length+, and no block given,
4666 * replaces elements based on the given +start+ and +length+.
4668 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4670 * a = ['a', 'b', 'c', 'd']
4671 * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"]
4673 * If +start+ is negative, counts from the end:
4675 * a = ['a', 'b', 'c', 'd']
4676 * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"]
4678 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4680 * a = ['a', 'b', 'c', 'd']
4681 * a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil]
4682 * a = ['a', 'b', 'c', 'd']
4683 * a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X]
4685 * If +length+ is zero or negative, replaces no elements:
4687 * a = ['a', 'b', 'c', 'd']
4688 * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"]
4689 * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"]
4691 * With arguments +obj+ and Range +range+, and no block given,
4692 * replaces elements based on the given range.
4694 * If the range is positive and ascending (<tt>0 < range.begin <= range.end</tt>),
4695 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4697 * a = ['a', 'b', 'c', 'd']
4698 * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"]
4700 * If <tt>range.first</tt> is negative, replaces no elements:
4702 * a = ['a', 'b', 'c', 'd']
4703 * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"]
4705 * If <tt>range.last</tt> is negative, counts from the end:
4707 * a = ['a', 'b', 'c', 'd']
4708 * a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"]
4709 * a = ['a', 'b', 'c', 'd']
4710 * a.fill(:X, (1..-2)) # => ["a", :X, :X, "d"]
4712 * If <tt>range.last</tt> and <tt>range.last</tt> are both negative,
4713 * both count from the end of the array:
4715 * a = ['a', 'b', 'c', 'd']
4716 * a.fill(:X, (-1..-1)) # => ["a", "b", "c", :X]
4717 * a = ['a', 'b', 'c', 'd']
4718 * a.fill(:X, (-2..-2)) # => ["a", "b", :X, "d"]
4720 * With no arguments and a block given, calls the block with each index;
4721 * replaces the corresponding element with the block's return value:
4723 * a = ['a', 'b', 'c', 'd']
4724 * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4726 * With argument +start+ and a block given, calls the block with each index
4727 * from offset +start+ to the end; replaces the corresponding element
4728 * with the block's return value.
4730 * If start is in range (<tt>0 <= start < array.size</tt>),
4731 * replaces from offset +start+ to the end:
4733 * a = ['a', 'b', 'c', 'd']
4734 * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"]
4736 * If +start+ is too large(<tt>start >= array.size</tt>), does nothing:
4738 * a = ['a', 'b', 'c', 'd']
4739 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4740 * a = ['a', 'b', 'c', 'd']
4741 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4743 * If +start+ is negative, counts from the end:
4745 * a = ['a', 'b', 'c', 'd']
4746 * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"]
4748 * If start is too small (<tt>start <= -array.size</tt>, replaces all elements:
4750 * a = ['a', 'b', 'c', 'd']
4751 * a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4752 * a = ['a', 'b', 'c', 'd']
4753 * a.fill(-50) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4755 * With arguments +start+ and +length+, and a block given,
4756 * calls the block for each index specified by start length;
4757 * replaces the corresponding element with the block's return value.
4759 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4761 * a = ['a', 'b', 'c', 'd']
4762 * a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4764 * If start is negative, counts from the end:
4766 * a = ['a', 'b', 'c', 'd']
4767 * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4769 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4771 * a = ['a', 'b', 'c', 'd']
4772 * a.fill(5, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil]
4773 * a = ['a', 'b', 'c', 'd']
4774 * a.fill(5, 2) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil, "new_5", "new_6"]
4776 * If +length+ is zero or less, replaces no elements:
4778 * a = ['a', 'b', 'c', 'd']
4779 * a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4780 * a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4782 * With arguments +obj+ and +range+, and a block given,
4783 * calls the block with each index in the given range;
4784 * replaces the corresponding element with the block's return value.
4786 * If the range is positive and ascending (<tt>range 0 < range.begin <= range.end</tt>,
4787 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4789 * a = ['a', 'b', 'c', 'd']
4790 * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4792 * If +range.first+ is negative, does nothing:
4794 * a = ['a', 'b', 'c', 'd']
4795 * a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4797 * If <tt>range.last</tt> is negative, counts from the end:
4799 * a = ['a', 'b', 'c', 'd']
4800 * a.fill(0..-2) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "d"]
4801 * a = ['a', 'b', 'c', 'd']
4802 * a.fill(1..-2) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "d"]
4804 * If <tt>range.first</tt> and <tt>range.last</tt> are both negative,
4805 * both count from the end:
4807 * a = ['a', 'b', 'c', 'd']
4808 * a.fill(-1..-1) { |index| "new_#{index}" } # => ["a", "b", "c", "new_3"]
4809 * a = ['a', 'b', 'c', 'd']
4810 * a.fill(-2..-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4814 static VALUE
4815 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
4817 VALUE item = Qundef, arg1, arg2;
4818 long beg = 0, end = 0, len = 0;
4820 if (rb_block_given_p()) {
4821 rb_scan_args(argc, argv, "02", &arg1, &arg2);
4822 argc += 1; /* hackish */
4824 else {
4825 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
4827 switch (argc) {
4828 case 1:
4829 beg = 0;
4830 len = RARRAY_LEN(ary);
4831 break;
4832 case 2:
4833 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
4834 break;
4836 /* fall through */
4837 case 3:
4838 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
4839 if (beg < 0) {
4840 beg = RARRAY_LEN(ary) + beg;
4841 if (beg < 0) beg = 0;
4843 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
4844 break;
4846 rb_ary_modify(ary);
4847 if (len < 0) {
4848 return ary;
4850 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
4851 rb_raise(rb_eArgError, "argument too big");
4853 end = beg + len;
4854 if (RARRAY_LEN(ary) < end) {
4855 if (end >= ARY_CAPA(ary)) {
4856 ary_resize_capa(ary, end);
4858 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
4859 ARY_SET_LEN(ary, end);
4862 if (UNDEF_P(item)) {
4863 VALUE v;
4864 long i;
4866 for (i=beg; i<end; i++) {
4867 v = rb_yield(LONG2NUM(i));
4868 if (i>=RARRAY_LEN(ary)) break;
4869 ARY_SET(ary, i, v);
4872 else {
4873 ary_memfill(ary, beg, len, item);
4875 return ary;
4879 * call-seq:
4880 * array + other_array -> new_array
4882 * Returns a new +Array+ containing all elements of +array+
4883 * followed by all elements of +other_array+:
4885 * a = [0, 1] + [2, 3]
4886 * a # => [0, 1, 2, 3]
4888 * Related: #concat.
4891 VALUE
4892 rb_ary_plus(VALUE x, VALUE y)
4894 VALUE z;
4895 long len, xlen, ylen;
4897 y = to_ary(y);
4898 xlen = RARRAY_LEN(x);
4899 ylen = RARRAY_LEN(y);
4900 len = xlen + ylen;
4901 z = rb_ary_new2(len);
4903 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
4904 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
4905 ARY_SET_LEN(z, len);
4906 return z;
4909 static VALUE
4910 ary_append(VALUE x, VALUE y)
4912 long n = RARRAY_LEN(y);
4913 if (n > 0) {
4914 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
4916 RB_GC_GUARD(y);
4917 return x;
4921 * call-seq:
4922 * array.concat(*other_arrays) -> self
4924 * Adds to +array+ all elements from each +Array+ in +other_arrays+; returns +self+:
4926 * a = [0, 1]
4927 * a.concat([2, 3], [4, 5]) # => [0, 1, 2, 3, 4, 5]
4930 static VALUE
4931 rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
4933 rb_ary_modify_check(ary);
4935 if (argc == 1) {
4936 rb_ary_concat(ary, argv[0]);
4938 else if (argc > 1) {
4939 int i;
4940 VALUE args = rb_ary_hidden_new(argc);
4941 for (i = 0; i < argc; i++) {
4942 rb_ary_concat(args, argv[i]);
4944 ary_append(ary, args);
4947 ary_verify(ary);
4948 return ary;
4951 VALUE
4952 rb_ary_concat(VALUE x, VALUE y)
4954 return ary_append(x, to_ary(y));
4958 * call-seq:
4959 * array * n -> new_array
4960 * array * string_separator -> new_string
4962 * When non-negative argument Integer +n+ is given,
4963 * returns a new +Array+ built by concatenating the +n+ copies of +self+:
4965 * a = ['x', 'y']
4966 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
4968 * When String argument +string_separator+ is given,
4969 * equivalent to <tt>array.join(string_separator)</tt>:
4971 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
4975 static VALUE
4976 rb_ary_times(VALUE ary, VALUE times)
4978 VALUE ary2, tmp;
4979 const VALUE *ptr;
4980 long t, len;
4982 tmp = rb_check_string_type(times);
4983 if (!NIL_P(tmp)) {
4984 return rb_ary_join(ary, tmp);
4987 len = NUM2LONG(times);
4988 if (len == 0) {
4989 ary2 = ary_new(rb_cArray, 0);
4990 goto out;
4992 if (len < 0) {
4993 rb_raise(rb_eArgError, "negative argument");
4995 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
4996 rb_raise(rb_eArgError, "argument too big");
4998 len *= RARRAY_LEN(ary);
5000 ary2 = ary_new(rb_cArray, len);
5001 ARY_SET_LEN(ary2, len);
5003 ptr = RARRAY_CONST_PTR(ary);
5004 t = RARRAY_LEN(ary);
5005 if (0 < t) {
5006 ary_memcpy(ary2, 0, t, ptr);
5007 while (t <= len/2) {
5008 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5009 t *= 2;
5011 if (t < len) {
5012 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5015 out:
5016 return ary2;
5020 * call-seq:
5021 * array.assoc(obj) -> found_array or nil
5023 * Returns the first element in +self+ that is an +Array+
5024 * whose first element <tt>==</tt> +obj+:
5026 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5027 * a.assoc(4) # => [4, 5, 6]
5029 * Returns +nil+ if no such element is found.
5031 * Related: #rassoc.
5034 VALUE
5035 rb_ary_assoc(VALUE ary, VALUE key)
5037 long i;
5038 VALUE v;
5040 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5041 v = rb_check_array_type(RARRAY_AREF(ary, i));
5042 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5043 rb_equal(RARRAY_AREF(v, 0), key))
5044 return v;
5046 return Qnil;
5050 * call-seq:
5051 * array.rassoc(obj) -> found_array or nil
5053 * Returns the first element in +self+ that is an +Array+
5054 * whose second element <tt>==</tt> +obj+:
5056 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5057 * a.rassoc(4) # => [2, 4]
5059 * Returns +nil+ if no such element is found.
5061 * Related: #assoc.
5064 VALUE
5065 rb_ary_rassoc(VALUE ary, VALUE value)
5067 long i;
5068 VALUE v;
5070 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5071 v = rb_check_array_type(RARRAY_AREF(ary, i));
5072 if (RB_TYPE_P(v, T_ARRAY) &&
5073 RARRAY_LEN(v) > 1 &&
5074 rb_equal(RARRAY_AREF(v, 1), value))
5075 return v;
5077 return Qnil;
5080 static VALUE
5081 recursive_equal(VALUE ary1, VALUE ary2, int recur)
5083 long i, len1;
5084 const VALUE *p1, *p2;
5086 if (recur) return Qtrue; /* Subtle! */
5088 /* rb_equal() can evacuate ptrs */
5089 p1 = RARRAY_CONST_PTR(ary1);
5090 p2 = RARRAY_CONST_PTR(ary2);
5091 len1 = RARRAY_LEN(ary1);
5093 for (i = 0; i < len1; i++) {
5094 if (*p1 != *p2) {
5095 if (rb_equal(*p1, *p2)) {
5096 len1 = RARRAY_LEN(ary1);
5097 if (len1 != RARRAY_LEN(ary2))
5098 return Qfalse;
5099 if (len1 < i)
5100 return Qtrue;
5101 p1 = RARRAY_CONST_PTR(ary1) + i;
5102 p2 = RARRAY_CONST_PTR(ary2) + i;
5104 else {
5105 return Qfalse;
5108 p1++;
5109 p2++;
5111 return Qtrue;
5115 * call-seq:
5116 * array == other_array -> true or false
5118 * Returns +true+ if both <tt>array.size == other_array.size</tt>
5119 * and for each index +i+ in +array+, <tt>array[i] == other_array[i]</tt>:
5121 * a0 = [:foo, 'bar', 2]
5122 * a1 = [:foo, 'bar', 2.0]
5123 * a1 == a0 # => true
5124 * [] == [] # => true
5126 * Otherwise, returns +false+.
5128 * This method is different from method Array#eql?,
5129 * which compares elements using <tt>Object#eql?</tt>.
5132 static VALUE
5133 rb_ary_equal(VALUE ary1, VALUE ary2)
5135 if (ary1 == ary2) return Qtrue;
5136 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5137 if (!rb_respond_to(ary2, idTo_ary)) {
5138 return Qfalse;
5140 return rb_equal(ary2, ary1);
5142 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5143 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5144 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5147 static VALUE
5148 recursive_eql(VALUE ary1, VALUE ary2, int recur)
5150 long i;
5152 if (recur) return Qtrue; /* Subtle! */
5153 for (i=0; i<RARRAY_LEN(ary1); i++) {
5154 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5155 return Qfalse;
5157 return Qtrue;
5161 * call-seq:
5162 * array.eql?(other_array) -> true or false
5164 * Returns +true+ if +self+ and +other_array+ are the same size,
5165 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5167 * a0 = [:foo, 'bar', 2]
5168 * a1 = [:foo, 'bar', 2]
5169 * a1.eql?(a0) # => true
5171 * Otherwise, returns +false+.
5173 * This method is different from method Array#==,
5174 * which compares using method <tt>Object#==</tt>.
5177 static VALUE
5178 rb_ary_eql(VALUE ary1, VALUE ary2)
5180 if (ary1 == ary2) return Qtrue;
5181 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5182 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5183 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5184 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5187 VALUE
5188 rb_ary_hash_values(long len, const VALUE *elements)
5190 long i;
5191 st_index_t h;
5192 VALUE n;
5194 h = rb_hash_start(len);
5195 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5196 for (i=0; i<len; i++) {
5197 n = rb_hash(elements[i]);
5198 h = rb_hash_uint(h, NUM2LONG(n));
5200 h = rb_hash_end(h);
5201 return ST2FIX(h);
5205 * call-seq:
5206 * array.hash -> integer
5208 * Returns the integer hash value for +self+.
5210 * Two arrays with the same content will have the same hash code (and will compare using #eql?):
5212 * [0, 1, 2].hash == [0, 1, 2].hash # => true
5213 * [0, 1, 2].hash == [0, 1, 3].hash # => false
5217 static VALUE
5218 rb_ary_hash(VALUE ary)
5220 return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
5224 * call-seq:
5225 * array.include?(obj) -> true or false
5227 * Returns +true+ if for some index +i+ in +self+, <tt>obj == self[i]</tt>;
5228 * otherwise +false+:
5230 * [0, 1, 2].include?(2) # => true
5231 * [0, 1, 2].include?(3) # => false
5234 VALUE
5235 rb_ary_includes(VALUE ary, VALUE item)
5237 long i;
5238 VALUE e;
5240 for (i=0; i<RARRAY_LEN(ary); i++) {
5241 e = RARRAY_AREF(ary, i);
5242 if (rb_equal(e, item)) {
5243 return Qtrue;
5246 return Qfalse;
5249 static VALUE
5250 rb_ary_includes_by_eql(VALUE ary, VALUE item)
5252 long i;
5253 VALUE e;
5255 for (i=0; i<RARRAY_LEN(ary); i++) {
5256 e = RARRAY_AREF(ary, i);
5257 if (rb_eql(item, e)) {
5258 return Qtrue;
5261 return Qfalse;
5264 static VALUE
5265 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5267 long i, len;
5269 if (recur) return Qundef; /* Subtle! */
5270 len = RARRAY_LEN(ary1);
5271 if (len > RARRAY_LEN(ary2)) {
5272 len = RARRAY_LEN(ary2);
5274 for (i=0; i<len; i++) {
5275 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5276 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5277 if (v != INT2FIX(0)) {
5278 return v;
5281 return Qundef;
5285 * call-seq:
5286 * array <=> other_array -> -1, 0, or 1
5288 * Returns -1, 0, or 1 as +self+ is less than, equal to, or greater than +other_array+.
5289 * For each index +i+ in +self+, evaluates <tt>result = self[i] <=> other_array[i]</tt>.
5291 * Returns -1 if any result is -1:
5293 * [0, 1, 2] <=> [0, 1, 3] # => -1
5295 * Returns 1 if any result is 1:
5297 * [0, 1, 2] <=> [0, 1, 1] # => 1
5299 * When all results are zero:
5301 * - Returns -1 if +array+ is smaller than +other_array+:
5303 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5305 * - Returns 1 if +array+ is larger than +other_array+:
5307 * [0, 1, 2] <=> [0, 1] # => 1
5309 * - Returns 0 if +array+ and +other_array+ are the same size:
5311 * [0, 1, 2] <=> [0, 1, 2] # => 0
5315 VALUE
5316 rb_ary_cmp(VALUE ary1, VALUE ary2)
5318 long len;
5319 VALUE v;
5321 ary2 = rb_check_array_type(ary2);
5322 if (NIL_P(ary2)) return Qnil;
5323 if (ary1 == ary2) return INT2FIX(0);
5324 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5325 if (!UNDEF_P(v)) return v;
5326 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5327 if (len == 0) return INT2FIX(0);
5328 if (len > 0) return INT2FIX(1);
5329 return INT2FIX(-1);
5332 static VALUE
5333 ary_add_hash(VALUE hash, VALUE ary)
5335 long i;
5337 for (i=0; i<RARRAY_LEN(ary); i++) {
5338 VALUE elt = RARRAY_AREF(ary, i);
5339 rb_hash_add_new_element(hash, elt, elt);
5341 return hash;
5344 static inline VALUE
5345 ary_tmp_hash_new(VALUE ary)
5347 long size = RARRAY_LEN(ary);
5348 VALUE hash = rb_hash_new_with_size(size);
5350 RBASIC_CLEAR_CLASS(hash);
5351 return hash;
5354 static VALUE
5355 ary_make_hash(VALUE ary)
5357 VALUE hash = ary_tmp_hash_new(ary);
5358 return ary_add_hash(hash, ary);
5361 static VALUE
5362 ary_add_hash_by(VALUE hash, VALUE ary)
5364 long i;
5366 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5367 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
5368 rb_hash_add_new_element(hash, k, v);
5370 return hash;
5373 static VALUE
5374 ary_make_hash_by(VALUE ary)
5376 VALUE hash = ary_tmp_hash_new(ary);
5377 return ary_add_hash_by(hash, ary);
5381 * call-seq:
5382 * array - other_array -> new_array
5384 * Returns a new +Array+ containing only those elements from +array+
5385 * that are not found in +Array+ +other_array+;
5386 * items are compared using <tt>eql?</tt>;
5387 * the order from +array+ is preserved:
5389 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5390 * [0, 1, 2, 3] - [3, 0] # => [1, 2]
5391 * [0, 1, 2] - [4] # => [0, 1, 2]
5393 * Related: Array#difference.
5396 VALUE
5397 rb_ary_diff(VALUE ary1, VALUE ary2)
5399 VALUE ary3;
5400 VALUE hash;
5401 long i;
5403 ary2 = to_ary(ary2);
5404 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5405 ary3 = rb_ary_new();
5407 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5408 for (i=0; i<RARRAY_LEN(ary1); i++) {
5409 VALUE elt = rb_ary_elt(ary1, i);
5410 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5411 rb_ary_push(ary3, elt);
5413 return ary3;
5416 hash = ary_make_hash(ary2);
5417 for (i=0; i<RARRAY_LEN(ary1); i++) {
5418 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
5419 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5422 return ary3;
5426 * call-seq:
5427 * array.difference(*other_arrays) -> new_array
5429 * Returns a new +Array+ containing only those elements from +self+
5430 * that are not found in any of the Arrays +other_arrays+;
5431 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5433 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5434 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5435 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5437 * Returns a copy of +self+ if no arguments given.
5439 * Related: Array#-.
5442 static VALUE
5443 rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5445 VALUE ary_diff;
5446 long i, length;
5447 volatile VALUE t0;
5448 bool *is_hash = ALLOCV_N(bool, t0, argc);
5449 ary_diff = rb_ary_new();
5450 length = RARRAY_LEN(ary);
5452 for (i = 0; i < argc; i++) {
5453 argv[i] = to_ary(argv[i]);
5454 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5455 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
5458 for (i = 0; i < RARRAY_LEN(ary); i++) {
5459 int j;
5460 VALUE elt = rb_ary_elt(ary, i);
5461 for (j = 0; j < argc; j++) {
5462 if (is_hash[j]) {
5463 if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
5464 break;
5466 else {
5467 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5470 if (j == argc) rb_ary_push(ary_diff, elt);
5473 ALLOCV_END(t0);
5475 return ary_diff;
5480 * call-seq:
5481 * array & other_array -> new_array
5483 * Returns a new +Array+ containing each element found in both +array+ and +Array+ +other_array+;
5484 * duplicates are omitted; items are compared using <tt>eql?</tt>
5485 * (items must also implement +hash+ correctly):
5487 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5488 * [0, 1, 0, 1] & [0, 1] # => [0, 1]
5490 * Preserves order from +array+:
5492 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5494 * Related: Array#intersection.
5498 static VALUE
5499 rb_ary_and(VALUE ary1, VALUE ary2)
5501 VALUE hash, ary3, v;
5502 st_data_t vv;
5503 long i;
5505 ary2 = to_ary(ary2);
5506 ary3 = rb_ary_new();
5507 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5509 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5510 for (i=0; i<RARRAY_LEN(ary1); i++) {
5511 v = RARRAY_AREF(ary1, i);
5512 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5513 if (rb_ary_includes_by_eql(ary3, v)) continue;
5514 rb_ary_push(ary3, v);
5516 return ary3;
5519 hash = ary_make_hash(ary2);
5521 for (i=0; i<RARRAY_LEN(ary1); i++) {
5522 v = RARRAY_AREF(ary1, i);
5523 vv = (st_data_t)v;
5524 if (rb_hash_stlike_delete(hash, &vv, 0)) {
5525 rb_ary_push(ary3, v);
5529 return ary3;
5533 * call-seq:
5534 * array.intersection(*other_arrays) -> new_array
5536 * Returns a new +Array+ containing each element found both in +self+
5537 * and in all of the given Arrays +other_arrays+;
5538 * duplicates are omitted; items are compared using <tt>eql?</tt>
5539 * (items must also implement +hash+ correctly):
5541 * [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5542 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5544 * Preserves order from +self+:
5546 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5548 * Returns a copy of +self+ if no arguments given.
5550 * Related: Array#&.
5553 static VALUE
5554 rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5556 VALUE result = rb_ary_dup(ary);
5557 int i;
5559 for (i = 0; i < argc; i++) {
5560 result = rb_ary_and(result, argv[i]);
5563 return result;
5566 static int
5567 ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
5569 if (existing) return ST_STOP;
5570 *key = *value = (VALUE)arg;
5571 return ST_CONTINUE;
5574 static void
5575 rb_ary_union(VALUE ary_union, VALUE ary)
5577 long i;
5578 for (i = 0; i < RARRAY_LEN(ary); i++) {
5579 VALUE elt = rb_ary_elt(ary, i);
5580 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5581 rb_ary_push(ary_union, elt);
5585 static void
5586 rb_ary_union_hash(VALUE hash, VALUE ary2)
5588 long i;
5589 for (i = 0; i < RARRAY_LEN(ary2); i++) {
5590 VALUE elt = RARRAY_AREF(ary2, i);
5591 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
5592 RB_OBJ_WRITTEN(hash, Qundef, elt);
5598 * call-seq:
5599 * array | other_array -> new_array
5601 * Returns the union of +array+ and +Array+ +other_array+;
5602 * duplicates are removed; order is preserved;
5603 * items are compared using <tt>eql?</tt>:
5605 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5606 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5607 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5609 * Related: Array#union.
5612 static VALUE
5613 rb_ary_or(VALUE ary1, VALUE ary2)
5615 VALUE hash;
5617 ary2 = to_ary(ary2);
5618 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5619 VALUE ary3 = rb_ary_new();
5620 rb_ary_union(ary3, ary1);
5621 rb_ary_union(ary3, ary2);
5622 return ary3;
5625 hash = ary_make_hash(ary1);
5626 rb_ary_union_hash(hash, ary2);
5628 return rb_hash_values(hash);
5632 * call-seq:
5633 * array.union(*other_arrays) -> new_array
5635 * Returns a new +Array+ that is the union of +self+ and all given Arrays +other_arrays+;
5636 * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
5638 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5639 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5640 * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
5642 * Returns a copy of +self+ if no arguments given.
5644 * Related: Array#|.
5647 static VALUE
5648 rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
5650 int i;
5651 long sum;
5652 VALUE hash;
5654 sum = RARRAY_LEN(ary);
5655 for (i = 0; i < argc; i++) {
5656 argv[i] = to_ary(argv[i]);
5657 sum += RARRAY_LEN(argv[i]);
5660 if (sum <= SMALL_ARRAY_LEN) {
5661 VALUE ary_union = rb_ary_new();
5663 rb_ary_union(ary_union, ary);
5664 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
5666 return ary_union;
5669 hash = ary_make_hash(ary);
5670 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
5672 return rb_hash_values(hash);
5676 * call-seq:
5677 * ary.intersect?(other_ary) -> true or false
5679 * Returns +true+ if the array and +other_ary+ have at least one element in
5680 * common, otherwise returns +false+:
5682 * a = [ 1, 2, 3 ]
5683 * b = [ 3, 4, 5 ]
5684 * c = [ 5, 6, 7 ]
5685 * a.intersect?(b) #=> true
5686 * a.intersect?(c) #=> false
5688 * +Array+ elements are compared using <tt>eql?</tt>
5689 * (items must also implement +hash+ correctly).
5692 static VALUE
5693 rb_ary_intersect_p(VALUE ary1, VALUE ary2)
5695 VALUE hash, v, result, shorter, longer;
5696 st_data_t vv;
5697 long i;
5699 ary2 = to_ary(ary2);
5700 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
5702 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5703 for (i=0; i<RARRAY_LEN(ary1); i++) {
5704 v = RARRAY_AREF(ary1, i);
5705 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
5707 return Qfalse;
5710 shorter = ary1;
5711 longer = ary2;
5712 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
5713 longer = ary1;
5714 shorter = ary2;
5717 hash = ary_make_hash(shorter);
5718 result = Qfalse;
5720 for (i=0; i<RARRAY_LEN(longer); i++) {
5721 v = RARRAY_AREF(longer, i);
5722 vv = (st_data_t)v;
5723 if (rb_hash_stlike_lookup(hash, vv, 0)) {
5724 result = Qtrue;
5725 break;
5729 return result;
5732 static VALUE
5733 ary_max_generic(VALUE ary, long i, VALUE vmax)
5735 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5737 VALUE v;
5738 for (; i < RARRAY_LEN(ary); ++i) {
5739 v = RARRAY_AREF(ary, i);
5741 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
5742 vmax = v;
5746 return vmax;
5749 static VALUE
5750 ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
5752 const long n = RARRAY_LEN(ary);
5753 RUBY_ASSERT(i > 0 && i < n);
5754 RUBY_ASSERT(FIXNUM_P(vmax));
5756 VALUE v;
5757 for (; i < n; ++i) {
5758 v = RARRAY_AREF(ary, i);
5760 if (FIXNUM_P(v)) {
5761 if ((long)vmax < (long)v) {
5762 vmax = v;
5765 else {
5766 return ary_max_generic(ary, i, vmax);
5770 return vmax;
5773 static VALUE
5774 ary_max_opt_float(VALUE ary, long i, VALUE vmax)
5776 const long n = RARRAY_LEN(ary);
5777 RUBY_ASSERT(i > 0 && i < n);
5778 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax));
5780 VALUE v;
5781 for (; i < n; ++i) {
5782 v = RARRAY_AREF(ary, i);
5784 if (RB_FLOAT_TYPE_P(v)) {
5785 if (rb_float_cmp(vmax, v) < 0) {
5786 vmax = v;
5789 else {
5790 return ary_max_generic(ary, i, vmax);
5794 return vmax;
5797 static VALUE
5798 ary_max_opt_string(VALUE ary, long i, VALUE vmax)
5800 const long n = RARRAY_LEN(ary);
5801 RUBY_ASSERT(i > 0 && i < n);
5802 RUBY_ASSERT(STRING_P(vmax));
5804 VALUE v;
5805 for (; i < n; ++i) {
5806 v = RARRAY_AREF(ary, i);
5808 if (STRING_P(v)) {
5809 if (rb_str_cmp(vmax, v) < 0) {
5810 vmax = v;
5813 else {
5814 return ary_max_generic(ary, i, vmax);
5818 return vmax;
5822 * call-seq:
5823 * array.max -> element
5824 * array.max {|a, b| ... } -> element
5825 * array.max(n) -> new_array
5826 * array.max(n) {|a, b| ... } -> new_array
5828 * Returns one of the following:
5830 * - The maximum-valued element from +self+.
5831 * - A new +Array+ of maximum-valued elements selected from +self+.
5833 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5834 * with an Integer.
5836 * With no argument and no block, returns the element in +self+
5837 * having the maximum value per method <tt><=></tt>:
5839 * [0, 1, 2].max # => 2
5841 * With an argument Integer +n+ and no block, returns a new +Array+ with at most +n+ elements,
5842 * in descending order per method <tt><=></tt>:
5844 * [0, 1, 2, 3].max(3) # => [3, 2, 1]
5845 * [0, 1, 2, 3].max(6) # => [3, 2, 1, 0]
5847 * When a block is given, the block must return an Integer.
5849 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
5850 * returns the element having the maximum value per the block:
5852 * ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000"
5854 * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
5855 * in descending order per the block:
5857 * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
5860 static VALUE
5861 rb_ary_max(int argc, VALUE *argv, VALUE ary)
5863 VALUE result = Qundef, v;
5864 VALUE num;
5865 long i;
5867 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
5868 return rb_nmin_run(ary, num, 0, 1, 1);
5870 const long n = RARRAY_LEN(ary);
5871 if (rb_block_given_p()) {
5872 for (i = 0; i < RARRAY_LEN(ary); i++) {
5873 v = RARRAY_AREF(ary, i);
5874 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
5875 result = v;
5879 else if (n > 0) {
5880 result = RARRAY_AREF(ary, 0);
5881 if (n > 1) {
5882 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
5883 return ary_max_opt_fixnum(ary, 1, result);
5885 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
5886 return ary_max_opt_string(ary, 1, result);
5888 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
5889 return ary_max_opt_float(ary, 1, result);
5891 else {
5892 return ary_max_generic(ary, 1, result);
5896 if (UNDEF_P(result)) return Qnil;
5897 return result;
5900 static VALUE
5901 ary_min_generic(VALUE ary, long i, VALUE vmin)
5903 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
5905 VALUE v;
5906 for (; i < RARRAY_LEN(ary); ++i) {
5907 v = RARRAY_AREF(ary, i);
5909 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
5910 vmin = v;
5914 return vmin;
5917 static VALUE
5918 ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
5920 const long n = RARRAY_LEN(ary);
5921 RUBY_ASSERT(i > 0 && i < n);
5922 RUBY_ASSERT(FIXNUM_P(vmin));
5924 VALUE a;
5925 for (; i < n; ++i) {
5926 a = RARRAY_AREF(ary, i);
5928 if (FIXNUM_P(a)) {
5929 if ((long)vmin > (long)a) {
5930 vmin = a;
5933 else {
5934 return ary_min_generic(ary, i, vmin);
5938 return vmin;
5941 static VALUE
5942 ary_min_opt_float(VALUE ary, long i, VALUE vmin)
5944 const long n = RARRAY_LEN(ary);
5945 RUBY_ASSERT(i > 0 && i < n);
5946 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin));
5948 VALUE a;
5949 for (; i < n; ++i) {
5950 a = RARRAY_AREF(ary, i);
5952 if (RB_FLOAT_TYPE_P(a)) {
5953 if (rb_float_cmp(vmin, a) > 0) {
5954 vmin = a;
5957 else {
5958 return ary_min_generic(ary, i, vmin);
5962 return vmin;
5965 static VALUE
5966 ary_min_opt_string(VALUE ary, long i, VALUE vmin)
5968 const long n = RARRAY_LEN(ary);
5969 RUBY_ASSERT(i > 0 && i < n);
5970 RUBY_ASSERT(STRING_P(vmin));
5972 VALUE a;
5973 for (; i < n; ++i) {
5974 a = RARRAY_AREF(ary, i);
5976 if (STRING_P(a)) {
5977 if (rb_str_cmp(vmin, a) > 0) {
5978 vmin = a;
5981 else {
5982 return ary_min_generic(ary, i, vmin);
5986 return vmin;
5990 * call-seq:
5991 * array.min -> element
5992 * array.min { |a, b| ... } -> element
5993 * array.min(n) -> new_array
5994 * array.min(n) { |a, b| ... } -> new_array
5996 * Returns one of the following:
5998 * - The minimum-valued element from +self+.
5999 * - A new +Array+ of minimum-valued elements selected from +self+.
6001 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
6002 * with an Integer.
6004 * With no argument and no block, returns the element in +self+
6005 * having the minimum value per method <tt><=></tt>:
6007 * [0, 1, 2].min # => 0
6009 * With Integer argument +n+ and no block, returns a new +Array+ with at most +n+ elements,
6010 * in ascending order per method <tt><=></tt>:
6012 * [0, 1, 2, 3].min(3) # => [0, 1, 2]
6013 * [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
6015 * When a block is given, the block must return an Integer.
6017 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
6018 * returns the element having the minimum value per the block:
6020 * ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0"
6022 * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
6023 * in ascending order per the block:
6025 * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
6028 static VALUE
6029 rb_ary_min(int argc, VALUE *argv, VALUE ary)
6031 VALUE result = Qundef, v;
6032 VALUE num;
6033 long i;
6035 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6036 return rb_nmin_run(ary, num, 0, 0, 1);
6038 const long n = RARRAY_LEN(ary);
6039 if (rb_block_given_p()) {
6040 for (i = 0; i < RARRAY_LEN(ary); i++) {
6041 v = RARRAY_AREF(ary, i);
6042 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6043 result = v;
6047 else if (n > 0) {
6048 result = RARRAY_AREF(ary, 0);
6049 if (n > 1) {
6050 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6051 return ary_min_opt_fixnum(ary, 1, result);
6053 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6054 return ary_min_opt_string(ary, 1, result);
6056 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6057 return ary_min_opt_float(ary, 1, result);
6059 else {
6060 return ary_min_generic(ary, 1, result);
6064 if (UNDEF_P(result)) return Qnil;
6065 return result;
6069 * call-seq:
6070 * array.minmax -> [min_val, max_val]
6071 * array.minmax {|a, b| ... } -> [min_val, max_val]
6073 * Returns a new 2-element +Array+ containing the minimum and maximum values
6074 * from +self+, either per method <tt><=></tt> or per a given block:.
6076 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
6077 * with an Integer;
6078 * returns a new 2-element +Array+ containing the minimum and maximum values
6079 * from +self+, per method <tt><=></tt>:
6081 * [0, 1, 2].minmax # => [0, 2]
6083 * When a block is given, the block must return an Integer;
6084 * the block is called <tt>self.size-1</tt> times to compare elements;
6085 * returns a new 2-element +Array+ containing the minimum and maximum values
6086 * from +self+, per the block:
6088 * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
6091 static VALUE
6092 rb_ary_minmax(VALUE ary)
6094 if (rb_block_given_p()) {
6095 return rb_call_super(0, NULL);
6097 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6100 static int
6101 push_value(st_data_t key, st_data_t val, st_data_t ary)
6103 rb_ary_push((VALUE)ary, (VALUE)val);
6104 return ST_CONTINUE;
6108 * call-seq:
6109 * array.uniq! -> self or nil
6110 * array.uniq! {|element| ... } -> self or nil
6112 * Removes duplicate elements from +self+, the first occurrence always being retained;
6113 * returns +self+ if any elements removed, +nil+ otherwise.
6115 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6116 * to compare.
6118 * Returns +self+ if any elements removed:
6120 * a = [0, 0, 1, 1, 2, 2]
6121 * a.uniq! # => [0, 1, 2]
6123 * Returns +nil+ if no elements removed.
6125 * With a block given, calls the block for each element;
6126 * identifies (using method <tt>eql?</tt>) and removes
6127 * elements for which the block returns duplicate values.
6129 * Returns +self+ if any elements removed:
6131 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6132 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
6134 * Returns +nil+ if no elements removed.
6136 static VALUE
6137 rb_ary_uniq_bang(VALUE ary)
6139 VALUE hash;
6140 long hash_size;
6142 rb_ary_modify_check(ary);
6143 if (RARRAY_LEN(ary) <= 1)
6144 return Qnil;
6145 if (rb_block_given_p())
6146 hash = ary_make_hash_by(ary);
6147 else
6148 hash = ary_make_hash(ary);
6150 hash_size = RHASH_SIZE(hash);
6151 if (RARRAY_LEN(ary) == hash_size) {
6152 return Qnil;
6154 rb_ary_modify_check(ary);
6155 ARY_SET_LEN(ary, 0);
6156 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
6157 rb_ary_unshare(ary);
6158 FL_SET_EMBED(ary);
6160 ary_resize_capa(ary, hash_size);
6161 rb_hash_foreach(hash, push_value, ary);
6163 return ary;
6167 * call-seq:
6168 * array.uniq -> new_array
6169 * array.uniq {|element| ... } -> new_array
6171 * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
6172 * the first occurrence always being retained.
6174 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
6175 * to compare:
6177 * a = [0, 0, 1, 1, 2, 2]
6178 * a.uniq # => [0, 1, 2]
6180 * With a block given, calls the block for each element;
6181 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
6182 * that is, those elements for which the block returns the same value:
6184 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6185 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6189 static VALUE
6190 rb_ary_uniq(VALUE ary)
6192 VALUE hash, uniq;
6194 if (RARRAY_LEN(ary) <= 1) {
6195 hash = 0;
6196 uniq = rb_ary_dup(ary);
6198 else if (rb_block_given_p()) {
6199 hash = ary_make_hash_by(ary);
6200 uniq = rb_hash_values(hash);
6202 else {
6203 hash = ary_make_hash(ary);
6204 uniq = rb_hash_values(hash);
6207 return uniq;
6211 * call-seq:
6212 * array.compact! -> self or nil
6214 * Removes all +nil+ elements from +self+.
6216 * Returns +self+ if any elements removed, otherwise +nil+.
6219 static VALUE
6220 rb_ary_compact_bang(VALUE ary)
6222 VALUE *p, *t, *end;
6223 long n;
6225 rb_ary_modify(ary);
6226 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6227 end = p + RARRAY_LEN(ary);
6229 while (t < end) {
6230 if (NIL_P(*t)) t++;
6231 else *p++ = *t++;
6233 n = p - RARRAY_CONST_PTR(ary);
6234 if (RARRAY_LEN(ary) == n) {
6235 return Qnil;
6237 ary_resize_smaller(ary, n);
6239 return ary;
6243 * call-seq:
6244 * array.compact -> new_array
6246 * Returns a new +Array+ containing all non-+nil+ elements from +self+:
6248 * a = [nil, 0, nil, 1, nil, 2, nil]
6249 * a.compact # => [0, 1, 2]
6252 static VALUE
6253 rb_ary_compact(VALUE ary)
6255 ary = rb_ary_dup(ary);
6256 rb_ary_compact_bang(ary);
6257 return ary;
6261 * call-seq:
6262 * array.count -> an_integer
6263 * array.count(obj) -> an_integer
6264 * array.count {|element| ... } -> an_integer
6266 * Returns a count of specified elements.
6268 * With no argument and no block, returns the count of all elements:
6270 * [0, 1, 2].count # => 3
6271 * [].count # => 0
6273 * With argument +obj+, returns the count of elements <tt>==</tt> to +obj+:
6275 * [0, 1, 2, 0.0].count(0) # => 2
6276 * [0, 1, 2].count(3) # => 0
6278 * With no argument and a block given, calls the block with each element;
6279 * returns the count of elements for which the block returns a truthy value:
6281 * [0, 1, 2, 3].count {|element| element > 1} # => 2
6283 * With argument +obj+ and a block given, issues a warning, ignores the block,
6284 * and returns the count of elements <tt>==</tt> to +obj+.
6287 static VALUE
6288 rb_ary_count(int argc, VALUE *argv, VALUE ary)
6290 long i, n = 0;
6292 if (rb_check_arity(argc, 0, 1) == 0) {
6293 VALUE v;
6295 if (!rb_block_given_p())
6296 return LONG2NUM(RARRAY_LEN(ary));
6298 for (i = 0; i < RARRAY_LEN(ary); i++) {
6299 v = RARRAY_AREF(ary, i);
6300 if (RTEST(rb_yield(v))) n++;
6303 else {
6304 VALUE obj = argv[0];
6306 if (rb_block_given_p()) {
6307 rb_warn("given block not used");
6309 for (i = 0; i < RARRAY_LEN(ary); i++) {
6310 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6314 return LONG2NUM(n);
6317 static VALUE
6318 flatten(VALUE ary, int level)
6320 long i;
6321 VALUE stack, result, tmp = 0, elt;
6322 VALUE memo = Qfalse;
6324 for (i = 0; i < RARRAY_LEN(ary); i++) {
6325 elt = RARRAY_AREF(ary, i);
6326 tmp = rb_check_array_type(elt);
6327 if (!NIL_P(tmp)) {
6328 break;
6331 if (i == RARRAY_LEN(ary)) {
6332 return ary;
6335 result = ary_new(0, RARRAY_LEN(ary));
6336 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6337 ARY_SET_LEN(result, i);
6339 stack = ary_new(0, ARY_DEFAULT_SIZE);
6340 rb_ary_push(stack, ary);
6341 rb_ary_push(stack, LONG2NUM(i + 1));
6343 if (level < 0) {
6344 memo = rb_obj_hide(rb_ident_hash_new());
6345 rb_hash_aset(memo, ary, Qtrue);
6346 rb_hash_aset(memo, tmp, Qtrue);
6349 ary = tmp;
6350 i = 0;
6352 while (1) {
6353 while (i < RARRAY_LEN(ary)) {
6354 elt = RARRAY_AREF(ary, i++);
6355 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6356 rb_ary_push(result, elt);
6357 continue;
6359 tmp = rb_check_array_type(elt);
6360 if (RBASIC(result)->klass) {
6361 if (RTEST(memo)) {
6362 rb_hash_clear(memo);
6364 rb_raise(rb_eRuntimeError, "flatten reentered");
6366 if (NIL_P(tmp)) {
6367 rb_ary_push(result, elt);
6369 else {
6370 if (memo) {
6371 if (rb_hash_aref(memo, tmp) == Qtrue) {
6372 rb_hash_clear(memo);
6373 rb_raise(rb_eArgError, "tried to flatten recursive array");
6375 rb_hash_aset(memo, tmp, Qtrue);
6377 rb_ary_push(stack, ary);
6378 rb_ary_push(stack, LONG2NUM(i));
6379 ary = tmp;
6380 i = 0;
6383 if (RARRAY_LEN(stack) == 0) {
6384 break;
6386 if (memo) {
6387 rb_hash_delete(memo, ary);
6389 tmp = rb_ary_pop(stack);
6390 i = NUM2LONG(tmp);
6391 ary = rb_ary_pop(stack);
6394 if (memo) {
6395 rb_hash_clear(memo);
6398 RBASIC_SET_CLASS(result, rb_cArray);
6399 return result;
6403 * call-seq:
6404 * array.flatten! -> self or nil
6405 * array.flatten!(level) -> self or nil
6407 * Replaces each nested +Array+ in +self+ with the elements from that +Array+;
6408 * returns +self+ if any changes, +nil+ otherwise.
6410 * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
6412 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6413 * a.flatten!(1) # => [0, 1, [2, 3], 4, 5]
6414 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6415 * a.flatten!(2) # => [0, 1, 2, 3, 4, 5]
6416 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6417 * a.flatten!(3) # => [0, 1, 2, 3, 4, 5]
6418 * [0, 1, 2].flatten!(1) # => nil
6420 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6422 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6423 * a.flatten! # => [0, 1, 2, 3, 4, 5]
6424 * [0, 1, 2].flatten! # => nil
6425 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6426 * a.flatten!(-1) # => [0, 1, 2, 3, 4, 5]
6427 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6428 * a.flatten!(-2) # => [0, 1, 2, 3, 4, 5]
6429 * [0, 1, 2].flatten!(-1) # => nil
6433 static VALUE
6434 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6436 int mod = 0, level = -1;
6437 VALUE result, lv;
6439 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6440 rb_ary_modify_check(ary);
6441 if (!NIL_P(lv)) level = NUM2INT(lv);
6442 if (level == 0) return Qnil;
6444 result = flatten(ary, level);
6445 if (result == ary) {
6446 return Qnil;
6448 if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
6449 rb_ary_replace(ary, result);
6450 if (mod) ARY_SET_EMBED_LEN(result, 0);
6452 return ary;
6456 * call-seq:
6457 * array.flatten -> new_array
6458 * array.flatten(level) -> new_array
6460 * Returns a new +Array+ that is a recursive flattening of +self+:
6461 * - Each non-Array element is unchanged.
6462 * - Each +Array+ is replaced by its individual elements.
6464 * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
6466 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6467 * a.flatten(0) # => [0, [1, [2, 3], 4], 5]
6468 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6469 * a.flatten(1) # => [0, 1, [2, 3], 4, 5]
6470 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6471 * a.flatten(2) # => [0, 1, 2, 3, 4, 5]
6472 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6473 * a.flatten(3) # => [0, 1, 2, 3, 4, 5]
6475 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6477 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6478 * a.flatten # => [0, 1, 2, 3, 4, 5]
6479 * [0, 1, 2].flatten # => [0, 1, 2]
6480 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6481 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5]
6482 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6483 * a.flatten(-2) # => [0, 1, 2, 3, 4, 5]
6484 * [0, 1, 2].flatten(-1) # => [0, 1, 2]
6488 static VALUE
6489 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6491 int level = -1;
6492 VALUE result;
6494 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6495 level = NUM2INT(argv[0]);
6496 if (level == 0) return ary_make_shared_copy(ary);
6499 result = flatten(ary, level);
6500 if (result == ary) {
6501 result = ary_make_shared_copy(ary);
6504 return result;
6507 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6509 static VALUE
6510 rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6512 long i, len;
6514 rb_ary_modify(ary);
6515 i = len = RARRAY_LEN(ary);
6516 RARRAY_PTR_USE(ary, ptr, {
6517 while (i) {
6518 long j = RAND_UPTO(i);
6519 VALUE tmp;
6520 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6521 rb_raise(rb_eRuntimeError, "modified during shuffle");
6523 tmp = ptr[--i];
6524 ptr[i] = ptr[j];
6525 ptr[j] = tmp;
6527 }); /* WB: no new reference */
6528 return ary;
6531 static VALUE
6532 rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6534 ary = rb_ary_dup(ary);
6535 rb_ary_shuffle_bang(ec, ary, randgen);
6536 return ary;
6539 static VALUE
6540 ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
6542 VALUE result;
6543 long n, len, i, j, k, idx[10];
6544 long rnds[numberof(idx)];
6545 long memo_threshold;
6547 len = RARRAY_LEN(ary);
6548 if (!to_array) {
6549 if (len < 2)
6550 i = 0;
6551 else
6552 i = RAND_UPTO(len);
6554 return rb_ary_elt(ary, i);
6556 n = NUM2LONG(nv);
6557 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
6558 if (n > len) n = len;
6559 if (n <= numberof(idx)) {
6560 for (i = 0; i < n; ++i) {
6561 rnds[i] = RAND_UPTO(len - i);
6564 k = len;
6565 len = RARRAY_LEN(ary);
6566 if (len < k && n <= numberof(idx)) {
6567 for (i = 0; i < n; ++i) {
6568 if (rnds[i] >= len) return rb_ary_new_capa(0);
6571 if (n > len) n = len;
6572 switch (n) {
6573 case 0:
6574 return rb_ary_new_capa(0);
6575 case 1:
6576 i = rnds[0];
6577 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
6578 case 2:
6579 i = rnds[0];
6580 j = rnds[1];
6581 if (j >= i) j++;
6582 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
6583 case 3:
6584 i = rnds[0];
6585 j = rnds[1];
6586 k = rnds[2];
6588 long l = j, g = i;
6589 if (j >= i) l = i, g = ++j;
6590 if (k >= l && (++k >= g)) ++k;
6592 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
6594 memo_threshold =
6595 len < 2560 ? len / 128 :
6596 len < 5120 ? len / 64 :
6597 len < 10240 ? len / 32 :
6598 len / 16;
6599 if (n <= numberof(idx)) {
6600 long sorted[numberof(idx)];
6601 sorted[0] = idx[0] = rnds[0];
6602 for (i=1; i<n; i++) {
6603 k = rnds[i];
6604 for (j = 0; j < i; ++j) {
6605 if (k < sorted[j]) break;
6606 ++k;
6608 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
6609 sorted[j] = idx[i] = k;
6611 result = rb_ary_new_capa(n);
6612 RARRAY_PTR_USE(result, ptr_result, {
6613 for (i=0; i<n; i++) {
6614 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
6618 else if (n <= memo_threshold / 2) {
6619 long max_idx = 0;
6620 #undef RUBY_UNTYPED_DATA_WARNING
6621 #define RUBY_UNTYPED_DATA_WARNING 0
6622 VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
6623 st_table *memo = st_init_numtable_with_size(n);
6624 DATA_PTR(vmemo) = memo;
6625 result = rb_ary_new_capa(n);
6626 RARRAY_PTR_USE(result, ptr_result, {
6627 for (i=0; i<n; i++) {
6628 long r = RAND_UPTO(len-i) + i;
6629 ptr_result[i] = r;
6630 if (r > max_idx) max_idx = r;
6632 len = RARRAY_LEN(ary);
6633 if (len <= max_idx) n = 0;
6634 else if (n > len) n = len;
6635 RARRAY_PTR_USE(ary, ptr_ary, {
6636 for (i=0; i<n; i++) {
6637 long j2 = j = ptr_result[i];
6638 long i2 = i;
6639 st_data_t value;
6640 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
6641 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
6642 st_insert(memo, (st_data_t)j, (st_data_t)i2);
6643 ptr_result[i] = ptr_ary[j2];
6647 DATA_PTR(vmemo) = 0;
6648 st_free_table(memo);
6649 RB_GC_GUARD(vmemo);
6651 else {
6652 result = rb_ary_dup(ary);
6653 RBASIC_CLEAR_CLASS(result);
6654 RB_GC_GUARD(ary);
6655 RARRAY_PTR_USE(result, ptr_result, {
6656 for (i=0; i<n; i++) {
6657 j = RAND_UPTO(len-i) + i;
6658 nv = ptr_result[j];
6659 ptr_result[j] = ptr_result[i];
6660 ptr_result[i] = nv;
6663 RBASIC_SET_CLASS_RAW(result, rb_cArray);
6665 ARY_SET_LEN(result, n);
6667 return result;
6670 static VALUE
6671 ary_sample0(rb_execution_context_t *ec, VALUE ary)
6673 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
6676 static VALUE
6677 rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
6679 long mul;
6680 VALUE n = Qnil;
6681 if (args && (RARRAY_LEN(args) > 0)) {
6682 n = RARRAY_AREF(args, 0);
6684 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
6685 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
6686 mul = NUM2LONG(n);
6687 if (mul <= 0) return INT2FIX(0);
6688 n = LONG2FIX(mul);
6689 return rb_fix_mul_fix(rb_ary_length(self), n);
6693 * call-seq:
6694 * array.cycle {|element| ... } -> nil
6695 * array.cycle(count) {|element| ... } -> nil
6696 * array.cycle -> new_enumerator
6697 * array.cycle(count) -> new_enumerator
6699 * When called with positive Integer argument +count+ and a block,
6700 * calls the block with each element, then does so again,
6701 * until it has done so +count+ times; returns +nil+:
6703 * output = []
6704 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6705 * output # => [0, 1, 0, 1]
6707 * If +count+ is zero or negative, does not call the block:
6709 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6710 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6712 * When a block is given, and argument is omitted or +nil+, cycles forever:
6714 * # Prints 0 and 1 forever.
6715 * [0, 1].cycle {|element| puts element }
6716 * [0, 1].cycle(nil) {|element| puts element }
6718 * When no block is given, returns a new Enumerator:
6720 * [0, 1].cycle(2) # => #<Enumerator: [0, 1]:cycle(2)>
6721 * [0, 1].cycle # => # => #<Enumerator: [0, 1]:cycle>
6722 * [0, 1].cycle.first(5) # => [0, 1, 0, 1, 0]
6725 static VALUE
6726 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
6728 long n, i;
6730 rb_check_arity(argc, 0, 1);
6732 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
6733 if (argc == 0 || NIL_P(argv[0])) {
6734 n = -1;
6736 else {
6737 n = NUM2LONG(argv[0]);
6738 if (n <= 0) return Qnil;
6741 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
6742 for (i=0; i<RARRAY_LEN(ary); i++) {
6743 rb_yield(RARRAY_AREF(ary, i));
6746 return Qnil;
6750 * Build a ruby array of the corresponding values and yield it to the
6751 * associated block.
6752 * Return the class of +values+ for reentry check.
6754 static int
6755 yield_indexed_values(const VALUE values, const long r, const long *const p)
6757 const VALUE result = rb_ary_new2(r);
6758 long i;
6760 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
6761 ARY_SET_LEN(result, r);
6762 rb_yield(result);
6763 return !RBASIC(values)->klass;
6767 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6769 * When we have a complete permutation of array indices, copy the values
6770 * at those indices into a new array and yield that array.
6772 * n: the size of the set
6773 * r: the number of elements in each permutation
6774 * p: the array (of size r) that we're filling in
6775 * used: an array of booleans: whether a given index is already used
6776 * values: the Ruby array that holds the actual values to permute
6778 static void
6779 permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
6781 long i = 0, index = 0;
6783 for (;;) {
6784 const char *const unused = memchr(&used[i], 0, n-i);
6785 if (!unused) {
6786 if (!index) break;
6787 i = p[--index]; /* pop index */
6788 used[i++] = 0; /* index unused */
6790 else {
6791 i = unused - used;
6792 p[index] = i;
6793 used[i] = 1; /* mark index used */
6794 ++index;
6795 if (index < r-1) { /* if not done yet */
6796 p[index] = i = 0;
6797 continue;
6799 for (i = 0; i < n; ++i) {
6800 if (used[i]) continue;
6801 p[index] = i;
6802 if (!yield_indexed_values(values, r, p)) {
6803 rb_raise(rb_eRuntimeError, "permute reentered");
6806 i = p[--index]; /* pop index */
6807 used[i] = 0; /* index unused */
6808 p[index] = ++i;
6814 * Returns the product of from, from-1, ..., from - how_many + 1.
6815 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6817 static VALUE
6818 descending_factorial(long from, long how_many)
6820 VALUE cnt;
6821 if (how_many > 0) {
6822 cnt = LONG2FIX(from);
6823 while (--how_many > 0) {
6824 long v = --from;
6825 cnt = rb_int_mul(cnt, LONG2FIX(v));
6828 else {
6829 cnt = LONG2FIX(how_many == 0);
6831 return cnt;
6834 static VALUE
6835 binomial_coefficient(long comb, long size)
6837 VALUE r;
6838 long i;
6839 if (comb > size-comb) {
6840 comb = size-comb;
6842 if (comb < 0) {
6843 return LONG2FIX(0);
6845 else if (comb == 0) {
6846 return LONG2FIX(1);
6848 r = LONG2FIX(size);
6849 for (i = 1; i < comb; ++i) {
6850 r = rb_int_mul(r, LONG2FIX(size - i));
6851 r = rb_int_idiv(r, LONG2FIX(i + 1));
6853 return r;
6856 static VALUE
6857 rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
6859 long n = RARRAY_LEN(ary);
6860 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
6862 return descending_factorial(n, k);
6866 * call-seq:
6867 * array.permutation {|element| ... } -> self
6868 * array.permutation(n) {|element| ... } -> self
6869 * array.permutation -> new_enumerator
6870 * array.permutation(n) -> new_enumerator
6872 * When invoked with a block, yield all permutations of elements of +self+; returns +self+.
6873 * The order of permutations is indeterminate.
6875 * When a block and an in-range positive Integer argument +n+ (<tt>0 < n <= self.size</tt>)
6876 * are given, calls the block with all +n+-tuple permutations of +self+.
6878 * Example:
6880 * a = [0, 1, 2]
6881 * a.permutation(2) {|permutation| p permutation }
6883 * Output:
6885 * [0, 1]
6886 * [0, 2]
6887 * [1, 0]
6888 * [1, 2]
6889 * [2, 0]
6890 * [2, 1]
6892 * Another example:
6894 * a = [0, 1, 2]
6895 * a.permutation(3) {|permutation| p permutation }
6897 * Output:
6899 * [0, 1, 2]
6900 * [0, 2, 1]
6901 * [1, 0, 2]
6902 * [1, 2, 0]
6903 * [2, 0, 1]
6904 * [2, 1, 0]
6906 * When +n+ is zero, calls the block once with a new empty +Array+:
6908 * a = [0, 1, 2]
6909 * a.permutation(0) {|permutation| p permutation }
6911 * Output:
6913 * []
6915 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
6916 * does not call the block:
6918 * a = [0, 1, 2]
6919 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
6920 * a.permutation(4) {|permutation| fail 'Cannot happen' }
6922 * When a block given but no argument,
6923 * behaves the same as <tt>a.permutation(a.size)</tt>:
6925 * a = [0, 1, 2]
6926 * a.permutation {|permutation| p permutation }
6928 * Output:
6930 * [0, 1, 2]
6931 * [0, 2, 1]
6932 * [1, 0, 2]
6933 * [1, 2, 0]
6934 * [2, 0, 1]
6935 * [2, 1, 0]
6937 * Returns a new Enumerator if no block given:
6939 * a = [0, 1, 2]
6940 * a.permutation # => #<Enumerator: [0, 1, 2]:permutation>
6941 * a.permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
6945 static VALUE
6946 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
6948 long r, n, i;
6950 n = RARRAY_LEN(ary); /* Array length */
6951 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
6952 r = n;
6953 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
6954 r = NUM2LONG(argv[0]); /* Permutation size from argument */
6956 if (r < 0 || n < r) {
6957 /* no permutations: yield nothing */
6959 else if (r == 0) { /* exactly one permutation: the zero-length array */
6960 rb_yield(rb_ary_new2(0));
6962 else if (r == 1) { /* this is a special, easy case */
6963 for (i = 0; i < RARRAY_LEN(ary); i++) {
6964 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
6967 else { /* this is the general case */
6968 volatile VALUE t0;
6969 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
6970 char *used = (char*)(p + r);
6971 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
6972 RBASIC_CLEAR_CLASS(ary0);
6974 MEMZERO(used, char, n); /* initialize array */
6976 permute0(n, r, p, used, ary0); /* compute and yield permutations */
6977 ALLOCV_END(t0);
6978 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
6980 return ary;
6983 static void
6984 combinate0(const long len, const long n, long *const stack, const VALUE values)
6986 long lev = 0;
6988 MEMZERO(stack+1, long, n);
6989 stack[0] = -1;
6990 for (;;) {
6991 for (lev++; lev < n; lev++) {
6992 stack[lev+1] = stack[lev]+1;
6994 if (!yield_indexed_values(values, n, stack+1)) {
6995 rb_raise(rb_eRuntimeError, "combination reentered");
6997 do {
6998 if (lev == 0) return;
6999 stack[lev--]++;
7000 } while (stack[lev+1]+n == len+lev+1);
7004 static VALUE
7005 rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7007 long n = RARRAY_LEN(ary);
7008 long k = NUM2LONG(RARRAY_AREF(args, 0));
7010 return binomial_coefficient(k, n);
7014 * call-seq:
7015 * array.combination(n) {|element| ... } -> self
7016 * array.combination(n) -> new_enumerator
7018 * Calls the block, if given, with combinations of elements of +self+;
7019 * returns +self+. The order of combinations is indeterminate.
7021 * When a block and an in-range positive Integer argument +n+ (<tt>0 < n <= self.size</tt>)
7022 * are given, calls the block with all +n+-tuple combinations of +self+.
7024 * Example:
7026 * a = [0, 1, 2]
7027 * a.combination(2) {|combination| p combination }
7029 * Output:
7031 * [0, 1]
7032 * [0, 2]
7033 * [1, 2]
7035 * Another example:
7037 * a = [0, 1, 2]
7038 * a.combination(3) {|combination| p combination }
7040 * Output:
7042 * [0, 1, 2]
7044 * When +n+ is zero, calls the block once with a new empty +Array+:
7046 * a = [0, 1, 2]
7047 * a1 = a.combination(0) {|combination| p combination }
7049 * Output:
7051 * []
7053 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
7054 * does not call the block:
7056 * a = [0, 1, 2]
7057 * a.combination(-1) {|combination| fail 'Cannot happen' }
7058 * a.combination(4) {|combination| fail 'Cannot happen' }
7060 * Returns a new Enumerator if no block given:
7062 * a = [0, 1, 2]
7063 * a.combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
7067 static VALUE
7068 rb_ary_combination(VALUE ary, VALUE num)
7070 long i, n, len;
7072 n = NUM2LONG(num);
7073 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7074 len = RARRAY_LEN(ary);
7075 if (n < 0 || len < n) {
7076 /* yield nothing */
7078 else if (n == 0) {
7079 rb_yield(rb_ary_new2(0));
7081 else if (n == 1) {
7082 for (i = 0; i < RARRAY_LEN(ary); i++) {
7083 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7086 else {
7087 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7088 volatile VALUE t0;
7089 long *stack = ALLOCV_N(long, t0, n+1);
7091 RBASIC_CLEAR_CLASS(ary0);
7092 combinate0(len, n, stack, ary0);
7093 ALLOCV_END(t0);
7094 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7096 return ary;
7100 * Compute repeated permutations of +r+ elements of the set
7101 * <code>[0..n-1]</code>.
7103 * When we have a complete repeated permutation of array indices, copy the
7104 * values at those indices into a new array and yield that array.
7106 * n: the size of the set
7107 * r: the number of elements in each permutation
7108 * p: the array (of size r) that we're filling in
7109 * values: the Ruby array that holds the actual values to permute
7111 static void
7112 rpermute0(const long n, const long r, long *const p, const VALUE values)
7114 long i = 0, index = 0;
7116 p[index] = i;
7117 for (;;) {
7118 if (++index < r-1) {
7119 p[index] = i = 0;
7120 continue;
7122 for (i = 0; i < n; ++i) {
7123 p[index] = i;
7124 if (!yield_indexed_values(values, r, p)) {
7125 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7128 do {
7129 if (index <= 0) return;
7130 } while ((i = ++p[--index]) >= n);
7134 static VALUE
7135 rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7137 long n = RARRAY_LEN(ary);
7138 long k = NUM2LONG(RARRAY_AREF(args, 0));
7140 if (k < 0) {
7141 return LONG2FIX(0);
7143 if (n <= 0) {
7144 return LONG2FIX(!k);
7146 return rb_int_positive_pow(n, (unsigned long)k);
7150 * call-seq:
7151 * array.repeated_permutation(n) {|permutation| ... } -> self
7152 * array.repeated_permutation(n) -> new_enumerator
7154 * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
7155 * each permutation is an +Array+;
7156 * returns +self+. The order of the permutations is indeterminate.
7158 * When a block and a positive Integer argument +n+ are given, calls the block with each
7159 * +n+-tuple repeated permutation of the elements of +self+.
7160 * The number of permutations is <tt>self.size**n</tt>.
7162 * +n+ = 1:
7164 * a = [0, 1, 2]
7165 * a.repeated_permutation(1) {|permutation| p permutation }
7167 * Output:
7169 * [0]
7170 * [1]
7171 * [2]
7173 * +n+ = 2:
7175 * a.repeated_permutation(2) {|permutation| p permutation }
7177 * Output:
7179 * [0, 0]
7180 * [0, 1]
7181 * [0, 2]
7182 * [1, 0]
7183 * [1, 1]
7184 * [1, 2]
7185 * [2, 0]
7186 * [2, 1]
7187 * [2, 2]
7189 * If +n+ is zero, calls the block once with an empty +Array+.
7191 * If +n+ is negative, does not call the block:
7193 * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7195 * Returns a new Enumerator if no block given:
7197 * a = [0, 1, 2]
7198 * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
7200 * Using Enumerators, it's convenient to show the permutations and counts
7201 * for some values of +n+:
7203 * e = a.repeated_permutation(0)
7204 * e.size # => 1
7205 * e.to_a # => [[]]
7206 * e = a.repeated_permutation(1)
7207 * e.size # => 3
7208 * e.to_a # => [[0], [1], [2]]
7209 * e = a.repeated_permutation(2)
7210 * e.size # => 9
7211 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7214 static VALUE
7215 rb_ary_repeated_permutation(VALUE ary, VALUE num)
7217 long r, n, i;
7219 n = RARRAY_LEN(ary); /* Array length */
7220 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7221 r = NUM2LONG(num); /* Permutation size from argument */
7223 if (r < 0) {
7224 /* no permutations: yield nothing */
7226 else if (r == 0) { /* exactly one permutation: the zero-length array */
7227 rb_yield(rb_ary_new2(0));
7229 else if (r == 1) { /* this is a special, easy case */
7230 for (i = 0; i < RARRAY_LEN(ary); i++) {
7231 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7234 else { /* this is the general case */
7235 volatile VALUE t0;
7236 long *p = ALLOCV_N(long, t0, r);
7237 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7238 RBASIC_CLEAR_CLASS(ary0);
7240 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7241 ALLOCV_END(t0);
7242 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7244 return ary;
7247 static void
7248 rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7250 long i = 0, index = 0;
7252 p[index] = i;
7253 for (;;) {
7254 if (++index < r-1) {
7255 p[index] = i;
7256 continue;
7258 for (; i < n; ++i) {
7259 p[index] = i;
7260 if (!yield_indexed_values(values, r, p)) {
7261 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7264 do {
7265 if (index <= 0) return;
7266 } while ((i = ++p[--index]) >= n);
7270 static VALUE
7271 rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7273 long n = RARRAY_LEN(ary);
7274 long k = NUM2LONG(RARRAY_AREF(args, 0));
7275 if (k == 0) {
7276 return LONG2FIX(1);
7278 return binomial_coefficient(k, n + k - 1);
7282 * call-seq:
7283 * array.repeated_combination(n) {|combination| ... } -> self
7284 * array.repeated_combination(n) -> new_enumerator
7286 * Calls the block with each repeated combination of length +n+ of the elements of +self+;
7287 * each combination is an +Array+;
7288 * returns +self+. The order of the combinations is indeterminate.
7290 * When a block and a positive Integer argument +n+ are given, calls the block with each
7291 * +n+-tuple repeated combination of the elements of +self+.
7292 * The number of combinations is <tt>(n+1)(n+2)/2</tt>.
7294 * +n+ = 1:
7296 * a = [0, 1, 2]
7297 * a.repeated_combination(1) {|combination| p combination }
7299 * Output:
7301 * [0]
7302 * [1]
7303 * [2]
7305 * +n+ = 2:
7307 * a.repeated_combination(2) {|combination| p combination }
7309 * Output:
7311 * [0, 0]
7312 * [0, 1]
7313 * [0, 2]
7314 * [1, 1]
7315 * [1, 2]
7316 * [2, 2]
7318 * If +n+ is zero, calls the block once with an empty +Array+.
7320 * If +n+ is negative, does not call the block:
7322 * a.repeated_combination(-1) {|combination| fail 'Cannot happen' }
7324 * Returns a new Enumerator if no block given:
7326 * a = [0, 1, 2]
7327 * a.repeated_combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
7329 * Using Enumerators, it's convenient to show the combinations and counts
7330 * for some values of +n+:
7332 * e = a.repeated_combination(0)
7333 * e.size # => 1
7334 * e.to_a # => [[]]
7335 * e = a.repeated_combination(1)
7336 * e.size # => 3
7337 * e.to_a # => [[0], [1], [2]]
7338 * e = a.repeated_combination(2)
7339 * e.size # => 6
7340 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7344 static VALUE
7345 rb_ary_repeated_combination(VALUE ary, VALUE num)
7347 long n, i, len;
7349 n = NUM2LONG(num); /* Combination size from argument */
7350 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7351 len = RARRAY_LEN(ary);
7352 if (n < 0) {
7353 /* yield nothing */
7355 else if (n == 0) {
7356 rb_yield(rb_ary_new2(0));
7358 else if (n == 1) {
7359 for (i = 0; i < RARRAY_LEN(ary); i++) {
7360 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7363 else if (len == 0) {
7364 /* yield nothing */
7366 else {
7367 volatile VALUE t0;
7368 long *p = ALLOCV_N(long, t0, n);
7369 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
7370 RBASIC_CLEAR_CLASS(ary0);
7372 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7373 ALLOCV_END(t0);
7374 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7376 return ary;
7380 * call-seq:
7381 * array.product(*other_arrays) -> new_array
7382 * array.product(*other_arrays) {|combination| ... } -> self
7384 * Computes and returns or yields all combinations of elements from all the Arrays,
7385 * including both +self+ and +other_arrays+:
7387 * - The number of combinations is the product of the sizes of all the arrays,
7388 * including both +self+ and +other_arrays+.
7389 * - The order of the returned combinations is indeterminate.
7391 * When no block is given, returns the combinations as an +Array+ of Arrays:
7393 * a = [0, 1, 2]
7394 * a1 = [3, 4]
7395 * a2 = [5, 6]
7396 * p = a.product(a1)
7397 * p.size # => 6 # a.size * a1.size
7398 * p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]]
7399 * p = a.product(a1, a2)
7400 * p.size # => 12 # a.size * a1.size * a2.size
7401 * p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
7403 * If any argument is an empty +Array+, returns an empty +Array+.
7405 * If no argument is given, returns an +Array+ of 1-element Arrays,
7406 * each containing an element of +self+:
7408 * a.product # => [[0], [1], [2]]
7410 * When a block is given, yields each combination as an +Array+; returns +self+:
7412 * a.product(a1) {|combination| p combination }
7414 * Output:
7416 * [0, 3]
7417 * [0, 4]
7418 * [1, 3]
7419 * [1, 4]
7420 * [2, 3]
7421 * [2, 4]
7423 * If any argument is an empty +Array+, does not call the block:
7425 * a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
7427 * If no argument is given, yields each element of +self+ as a 1-element +Array+:
7429 * a.product {|combination| p combination }
7431 * Output:
7433 * [0]
7434 * [1]
7435 * [2]
7439 static VALUE
7440 rb_ary_product(int argc, VALUE *argv, VALUE ary)
7442 int n = argc+1; /* How many arrays we're operating on */
7443 volatile VALUE t0 = rb_ary_hidden_new(n);
7444 volatile VALUE t1 = Qundef;
7445 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7446 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7447 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7448 long i,j;
7449 long resultlen = 1;
7451 RBASIC_CLEAR_CLASS(t0);
7453 /* initialize the arrays of arrays */
7454 ARY_SET_LEN(t0, n);
7455 arrays[0] = ary;
7456 for (i = 1; i < n; i++) arrays[i] = Qnil;
7457 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7459 /* initialize the counters for the arrays */
7460 for (i = 0; i < n; i++) counters[i] = 0;
7462 /* Otherwise, allocate and fill in an array of results */
7463 if (rb_block_given_p()) {
7464 /* Make defensive copies of arrays; exit if any is empty */
7465 for (i = 0; i < n; i++) {
7466 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7467 arrays[i] = ary_make_shared_copy(arrays[i]);
7470 else {
7471 /* Compute the length of the result array; return [] if any is empty */
7472 for (i = 0; i < n; i++) {
7473 long k = RARRAY_LEN(arrays[i]);
7474 if (k == 0) {
7475 result = rb_ary_new2(0);
7476 goto done;
7478 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7479 rb_raise(rb_eRangeError, "too big to product");
7480 resultlen *= k;
7482 result = rb_ary_new2(resultlen);
7484 for (;;) {
7485 int m;
7486 /* fill in one subarray */
7487 VALUE subarray = rb_ary_new2(n);
7488 for (j = 0; j < n; j++) {
7489 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7492 /* put it on the result array */
7493 if (NIL_P(result)) {
7494 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7495 rb_yield(subarray);
7496 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7497 rb_raise(rb_eRuntimeError, "product reentered");
7499 else {
7500 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7503 else {
7504 rb_ary_push(result, subarray);
7508 * Increment the last counter. If it overflows, reset to 0
7509 * and increment the one before it.
7511 m = n-1;
7512 counters[m]++;
7513 while (counters[m] == RARRAY_LEN(arrays[m])) {
7514 counters[m] = 0;
7515 /* If the first counter overflows, we are done */
7516 if (--m < 0) goto done;
7517 counters[m]++;
7521 done:
7522 ALLOCV_END(t1);
7524 return NIL_P(result) ? ary : result;
7528 * call-seq:
7529 * array.take(n) -> new_array
7531 * Returns a new +Array+ containing the first +n+ element of +self+,
7532 * where +n+ is a non-negative Integer;
7533 * does not modify +self+.
7535 * Examples:
7537 * a = [0, 1, 2, 3, 4, 5]
7538 * a.take(1) # => [0]
7539 * a.take(2) # => [0, 1]
7540 * a.take(50) # => [0, 1, 2, 3, 4, 5]
7541 * a # => [0, 1, 2, 3, 4, 5]
7545 static VALUE
7546 rb_ary_take(VALUE obj, VALUE n)
7548 long len = NUM2LONG(n);
7549 if (len < 0) {
7550 rb_raise(rb_eArgError, "attempt to take negative size");
7552 return rb_ary_subseq(obj, 0, len);
7556 * call-seq:
7557 * array.take_while {|element| ... } -> new_array
7558 * array.take_while -> new_enumerator
7560 * Returns a new +Array+ containing zero or more leading elements of +self+;
7561 * does not modify +self+.
7563 * With a block given, calls the block with each successive element of +self+;
7564 * stops if the block returns +false+ or +nil+;
7565 * returns a new +Array+ containing those elements for which the block returned a truthy value:
7567 * a = [0, 1, 2, 3, 4, 5]
7568 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7569 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7570 * a # => [0, 1, 2, 3, 4, 5]
7572 * With no block given, returns a new Enumerator:
7574 * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
7578 static VALUE
7579 rb_ary_take_while(VALUE ary)
7581 long i;
7583 RETURN_ENUMERATOR(ary, 0, 0);
7584 for (i = 0; i < RARRAY_LEN(ary); i++) {
7585 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7587 return rb_ary_take(ary, LONG2FIX(i));
7591 * call-seq:
7592 * array.drop(n) -> new_array
7594 * Returns a new +Array+ containing all but the first +n+ element of +self+,
7595 * where +n+ is a non-negative Integer;
7596 * does not modify +self+.
7598 * Examples:
7600 * a = [0, 1, 2, 3, 4, 5]
7601 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7602 * a.drop(1) # => [1, 2, 3, 4, 5]
7603 * a.drop(2) # => [2, 3, 4, 5]
7607 static VALUE
7608 rb_ary_drop(VALUE ary, VALUE n)
7610 VALUE result;
7611 long pos = NUM2LONG(n);
7612 if (pos < 0) {
7613 rb_raise(rb_eArgError, "attempt to drop negative size");
7616 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7617 if (NIL_P(result)) result = rb_ary_new();
7618 return result;
7622 * call-seq:
7623 * array.drop_while {|element| ... } -> new_array
7624 * array.drop_while -> new_enumerator
7626 * Returns a new +Array+ containing zero or more trailing elements of +self+;
7627 * does not modify +self+.
7629 * With a block given, calls the block with each successive element of +self+;
7630 * stops if the block returns +false+ or +nil+;
7631 * returns a new +Array+ _omitting_ those elements for which the block returned a truthy value:
7633 * a = [0, 1, 2, 3, 4, 5]
7634 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7636 * With no block given, returns a new Enumerator:
7638 * [0, 1].drop_while # => # => #<Enumerator: [0, 1]:drop_while>
7642 static VALUE
7643 rb_ary_drop_while(VALUE ary)
7645 long i;
7647 RETURN_ENUMERATOR(ary, 0, 0);
7648 for (i = 0; i < RARRAY_LEN(ary); i++) {
7649 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7651 return rb_ary_drop(ary, LONG2FIX(i));
7655 * call-seq:
7656 * array.any? -> true or false
7657 * array.any? {|element| ... } -> true or false
7658 * array.any?(obj) -> true or false
7660 * Returns +true+ if any element of +self+ meets a given criterion.
7662 * If +self+ has no element, returns +false+ and argument or block
7663 * are not used.
7665 * With no block given and no argument, returns +true+ if +self+ has any truthy element,
7666 * +false+ otherwise:
7668 * [nil, 0, false].any? # => true
7669 * [nil, false].any? # => false
7670 * [].any? # => false
7672 * With a block given and no argument, calls the block with each element in +self+;
7673 * returns +true+ if the block returns any truthy value, +false+ otherwise:
7675 * [0, 1, 2].any? {|element| element > 1 } # => true
7676 * [0, 1, 2].any? {|element| element > 2 } # => false
7678 * If argument +obj+ is given, returns +true+ if +obj+.<tt>===</tt> any element,
7679 * +false+ otherwise:
7681 * ['food', 'drink'].any?(/foo/) # => true
7682 * ['food', 'drink'].any?(/bar/) # => false
7683 * [].any?(/foo/) # => false
7684 * [0, 1, 2].any?(1) # => true
7685 * [0, 1, 2].any?(3) # => false
7687 * Related: Enumerable#any?
7690 static VALUE
7691 rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
7693 long i, len = RARRAY_LEN(ary);
7695 rb_check_arity(argc, 0, 1);
7696 if (!len) return Qfalse;
7697 if (argc) {
7698 if (rb_block_given_p()) {
7699 rb_warn("given block not used");
7701 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7702 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
7705 else if (!rb_block_given_p()) {
7706 for (i = 0; i < len; ++i) {
7707 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
7710 else {
7711 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7712 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
7715 return Qfalse;
7719 * call-seq:
7720 * array.all? -> true or false
7721 * array.all? {|element| ... } -> true or false
7722 * array.all?(obj) -> true or false
7724 * Returns +true+ if all elements of +self+ meet a given criterion.
7726 * If +self+ has no element, returns +true+ and argument or block
7727 * are not used.
7729 * With no block given and no argument, returns +true+ if +self+ contains only truthy elements,
7730 * +false+ otherwise:
7732 * [0, 1, :foo].all? # => true
7733 * [0, nil, 2].all? # => false
7734 * [].all? # => true
7736 * With a block given and no argument, calls the block with each element in +self+;
7737 * returns +true+ if the block returns only truthy values, +false+ otherwise:
7739 * [0, 1, 2].all? { |element| element < 3 } # => true
7740 * [0, 1, 2].all? { |element| element < 2 } # => false
7742 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> every element, +false+ otherwise:
7744 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7745 * ['food', 'drink'].all?(/bar/) # => false
7746 * [].all?(/foo/) # => true
7747 * [0, 0, 0].all?(0) # => true
7748 * [0, 1, 2].all?(1) # => false
7750 * Related: Enumerable#all?
7753 static VALUE
7754 rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
7756 long i, len = RARRAY_LEN(ary);
7758 rb_check_arity(argc, 0, 1);
7759 if (!len) return Qtrue;
7760 if (argc) {
7761 if (rb_block_given_p()) {
7762 rb_warn("given block not used");
7764 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7765 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
7768 else if (!rb_block_given_p()) {
7769 for (i = 0; i < len; ++i) {
7770 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
7773 else {
7774 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7775 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
7778 return Qtrue;
7782 * call-seq:
7783 * array.none? -> true or false
7784 * array.none? {|element| ... } -> true or false
7785 * array.none?(obj) -> true or false
7787 * Returns +true+ if no element of +self+ meet a given criterion.
7789 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7790 * +false+ otherwise:
7792 * [nil, false].none? # => true
7793 * [nil, 0, false].none? # => false
7794 * [].none? # => true
7796 * With a block given and no argument, calls the block with each element in +self+;
7797 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7799 * [0, 1, 2].none? {|element| element > 3 } # => true
7800 * [0, 1, 2].none? {|element| element > 1 } # => false
7802 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> no element, +false+ otherwise:
7804 * ['food', 'drink'].none?(/bar/) # => true
7805 * ['food', 'drink'].none?(/foo/) # => false
7806 * [].none?(/foo/) # => true
7807 * [0, 1, 2].none?(3) # => true
7808 * [0, 1, 2].none?(1) # => false
7810 * Related: Enumerable#none?
7813 static VALUE
7814 rb_ary_none_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 * array.one? -> true or false
7844 * array.one? {|element| ... } -> true or false
7845 * array.one?(obj) -> true or false
7847 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7849 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7850 * +false+ otherwise:
7852 * [nil, 0].one? # => true
7853 * [0, 0].one? # => false
7854 * [nil, nil].one? # => false
7855 * [].one? # => false
7857 * With a block given and no argument, calls the block with each element in +self+;
7858 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7860 * [0, 1, 2].one? {|element| element > 0 } # => false
7861 * [0, 1, 2].one? {|element| element > 1 } # => true
7862 * [0, 1, 2].one? {|element| element > 2 } # => false
7864 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> exactly one element,
7865 * +false+ otherwise:
7867 * [0, 1, 2].one?(0) # => true
7868 * [0, 0, 1].one?(0) # => false
7869 * [1, 1, 2].one?(0) # => false
7870 * ['food', 'drink'].one?(/bar/) # => false
7871 * ['food', 'drink'].one?(/foo/) # => true
7872 * [].one?(/foo/) # => false
7874 * Related: Enumerable#one?
7877 static VALUE
7878 rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
7880 long i, len = RARRAY_LEN(ary);
7881 VALUE result = Qfalse;
7883 rb_check_arity(argc, 0, 1);
7884 if (!len) return Qfalse;
7885 if (argc) {
7886 if (rb_block_given_p()) {
7887 rb_warn("given block not used");
7889 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7890 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
7891 if (result) return Qfalse;
7892 result = Qtrue;
7896 else if (!rb_block_given_p()) {
7897 for (i = 0; i < len; ++i) {
7898 if (RTEST(RARRAY_AREF(ary, i))) {
7899 if (result) return Qfalse;
7900 result = Qtrue;
7904 else {
7905 for (i = 0; i < RARRAY_LEN(ary); ++i) {
7906 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
7907 if (result) return Qfalse;
7908 result = Qtrue;
7912 return result;
7916 * call-seq:
7917 * array.dig(index, *identifiers) -> object
7919 * Finds and returns the object in nested objects
7920 * that is specified by +index+ and +identifiers+.
7921 * The nested objects may be instances of various classes.
7922 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
7924 * Examples:
7926 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
7927 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
7928 * a.dig(1, 2) # => [:bat, :bam]
7929 * a.dig(1, 2, 0) # => :bat
7930 * a.dig(1, 2, 3) # => nil
7934 static VALUE
7935 rb_ary_dig(int argc, VALUE *argv, VALUE self)
7937 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
7938 self = rb_ary_at(self, *argv);
7939 if (!--argc) return self;
7940 ++argv;
7941 return rb_obj_dig(argc, argv, self, Qnil);
7944 static inline VALUE
7945 finish_exact_sum(long n, VALUE r, VALUE v, int z)
7947 if (n != 0)
7948 v = rb_fix_plus(LONG2FIX(n), v);
7949 if (!UNDEF_P(r)) {
7950 v = rb_rational_plus(r, v);
7952 else if (!n && z) {
7953 v = rb_fix_plus(LONG2FIX(0), v);
7955 return v;
7959 * call-seq:
7960 * array.sum(init = 0) -> object
7961 * array.sum(init = 0) {|element| ... } -> object
7963 * When no block is given, returns the object equivalent to:
7965 * sum = init
7966 * array.each {|element| sum += element }
7967 * sum
7969 * For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
7971 * Examples:
7973 * a = [0, 1, 2, 3]
7974 * a.sum # => 6
7975 * a.sum(100) # => 106
7977 * The elements need not be numeric, but must be <tt>+</tt>-compatible
7978 * with each other and with +init+:
7980 * a = ['abc', 'def', 'ghi']
7981 * a.sum('jkl') # => "jklabcdefghi"
7983 * When a block is given, it is called with each element
7984 * and the block's return value (instead of the element itself) is used as the addend:
7986 * a = ['zero', 1, :two]
7987 * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
7988 * s # => "Coerced and concatenated: zero1two"
7990 * Notes:
7992 * - Array#join and Array#flatten may be faster than Array#sum
7993 * for an +Array+ of Strings or an +Array+ of Arrays.
7994 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
7998 static VALUE
7999 rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8001 VALUE e, v, r;
8002 long i, n;
8003 int block_given;
8005 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8007 block_given = rb_block_given_p();
8009 if (RARRAY_LEN(ary) == 0)
8010 return v;
8012 n = 0;
8013 r = Qundef;
8015 if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8016 i = 0;
8017 goto init_is_a_value;
8020 for (i = 0; i < RARRAY_LEN(ary); i++) {
8021 e = RARRAY_AREF(ary, i);
8022 if (block_given)
8023 e = rb_yield(e);
8024 if (FIXNUM_P(e)) {
8025 n += FIX2LONG(e); /* should not overflow long type */
8026 if (!FIXABLE(n)) {
8027 v = rb_big_plus(LONG2NUM(n), v);
8028 n = 0;
8031 else if (RB_BIGNUM_TYPE_P(e))
8032 v = rb_big_plus(e, v);
8033 else if (RB_TYPE_P(e, T_RATIONAL)) {
8034 if (UNDEF_P(r))
8035 r = e;
8036 else
8037 r = rb_rational_plus(r, e);
8039 else
8040 goto not_exact;
8042 v = finish_exact_sum(n, r, v, argc!=0);
8043 return v;
8045 not_exact:
8046 v = finish_exact_sum(n, r, v, i!=0);
8048 if (RB_FLOAT_TYPE_P(e)) {
8050 * Kahan-Babuska balancing compensated summation algorithm
8051 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8053 double f, c;
8054 double x, t;
8056 f = NUM2DBL(v);
8057 c = 0.0;
8058 goto has_float_value;
8059 for (; i < RARRAY_LEN(ary); i++) {
8060 e = RARRAY_AREF(ary, i);
8061 if (block_given)
8062 e = rb_yield(e);
8063 if (RB_FLOAT_TYPE_P(e))
8064 has_float_value:
8065 x = RFLOAT_VALUE(e);
8066 else if (FIXNUM_P(e))
8067 x = FIX2LONG(e);
8068 else if (RB_BIGNUM_TYPE_P(e))
8069 x = rb_big2dbl(e);
8070 else if (RB_TYPE_P(e, T_RATIONAL))
8071 x = rb_num2dbl(e);
8072 else
8073 goto not_float;
8075 if (isnan(f)) continue;
8076 if (isnan(x)) {
8077 f = x;
8078 continue;
8080 if (isinf(x)) {
8081 if (isinf(f) && signbit(x) != signbit(f))
8082 f = NAN;
8083 else
8084 f = x;
8085 continue;
8087 if (isinf(f)) continue;
8089 t = f + x;
8090 if (fabs(f) >= fabs(x))
8091 c += ((f - t) + x);
8092 else
8093 c += ((x - t) + f);
8094 f = t;
8096 f += c;
8097 return DBL2NUM(f);
8099 not_float:
8100 v = DBL2NUM(f);
8103 goto has_some_value;
8104 init_is_a_value:
8105 for (; i < RARRAY_LEN(ary); i++) {
8106 e = RARRAY_AREF(ary, i);
8107 if (block_given)
8108 e = rb_yield(e);
8109 has_some_value:
8110 v = rb_funcall(v, idPLUS, 1, e);
8112 return v;
8115 /* :nodoc: */
8116 static VALUE
8117 rb_ary_deconstruct(VALUE ary)
8119 return ary;
8123 * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
8124 * Any object (even another array) may be an array element,
8125 * and an array can contain objects of different types.
8127 * == +Array+ Indexes
8129 * +Array+ indexing starts at 0, as in C or Java.
8131 * A positive index is an offset from the first element:
8133 * - Index 0 indicates the first element.
8134 * - Index 1 indicates the second element.
8135 * - ...
8137 * A negative index is an offset, backwards, from the end of the array:
8139 * - Index -1 indicates the last element.
8140 * - Index -2 indicates the next-to-last element.
8141 * - ...
8143 * A non-negative index is <i>in range</i> if and only if it is smaller than
8144 * the size of the array. For a 3-element array:
8146 * - Indexes 0 through 2 are in range.
8147 * - Index 3 is out of range.
8149 * A negative index is <i>in range</i> if and only if its absolute value is
8150 * not larger than the size of the array. For a 3-element array:
8152 * - Indexes -1 through -3 are in range.
8153 * - Index -4 is out of range.
8155 * Although the effective index into an array is always an integer,
8156 * some methods (both within and outside of class +Array+)
8157 * accept one or more non-integer arguments that are
8158 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8161 * == Creating Arrays
8163 * You can create an +Array+ object explicitly with:
8165 * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
8167 * [1, 'one', :one, [2, 'two', :two]]
8169 * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8171 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8172 * %w[1 % *] # => ["1", "%", "*"]
8174 * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8176 * %i[foo bar baz] # => [:foo, :bar, :baz]
8177 * %i[1 % *] # => [:"1", :%, :*]
8179 * - \Method Kernel#Array:
8181 * Array(["a", "b"]) # => ["a", "b"]
8182 * Array(1..5) # => [1, 2, 3, 4, 5]
8183 * Array(key: :value) # => [[:key, :value]]
8184 * Array(nil) # => []
8185 * Array(1) # => [1]
8186 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8188 * - \Method Array.new:
8190 * Array.new # => []
8191 * Array.new(3) # => [nil, nil, nil]
8192 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8193 * Array.new(3, true) # => [true, true, true]
8195 * Note that the last example above populates the array
8196 * with references to the same object.
8197 * This is recommended only in cases where that object is a natively immutable object
8198 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8200 * Another way to create an array with various objects, using a block;
8201 * this usage is safe for mutable objects such as hashes, strings or
8202 * other arrays:
8204 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8206 * Here is a way to create a multi-dimensional array:
8208 * Array.new(3) {Array.new(3)}
8209 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8211 * A number of Ruby methods, both in the core and in the standard library,
8212 * provide instance method +to_a+, which converts an object to an array.
8214 * - ARGF#to_a
8215 * - Array#to_a
8216 * - Enumerable#to_a
8217 * - Hash#to_a
8218 * - MatchData#to_a
8219 * - NilClass#to_a
8220 * - OptionParser#to_a
8221 * - Range#to_a
8222 * - Set#to_a
8223 * - Struct#to_a
8224 * - Time#to_a
8225 * - Benchmark::Tms#to_a
8226 * - CSV::Table#to_a
8227 * - Enumerator::Lazy#to_a
8228 * - Gem::List#to_a
8229 * - Gem::NameTuple#to_a
8230 * - Gem::Platform#to_a
8231 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8232 * - Gem::SourceList#to_a
8233 * - OpenSSL::X509::Extension#to_a
8234 * - OpenSSL::X509::Name#to_a
8235 * - Racc::ISet#to_a
8236 * - Rinda::RingFinger#to_a
8237 * - Ripper::Lexer::Elem#to_a
8238 * - RubyVM::InstructionSequence#to_a
8239 * - YAML::DBM#to_a
8241 * == Example Usage
8243 * In addition to the methods it mixes in through the Enumerable module, the
8244 * +Array+ class has proprietary methods for accessing, searching and otherwise
8245 * manipulating arrays.
8247 * Some of the more common ones are illustrated below.
8249 * == Accessing Elements
8251 * Elements in an array can be retrieved using the Array#[] method. It can
8252 * take a single integer argument (a numeric index), a pair of arguments
8253 * (start and length) or a range. Negative indices start counting from the end,
8254 * with -1 being the last element.
8256 * arr = [1, 2, 3, 4, 5, 6]
8257 * arr[2] #=> 3
8258 * arr[100] #=> nil
8259 * arr[-3] #=> 4
8260 * arr[2, 3] #=> [3, 4, 5]
8261 * arr[1..4] #=> [2, 3, 4, 5]
8262 * arr[1..-3] #=> [2, 3, 4]
8264 * Another way to access a particular array element is by using the #at method
8266 * arr.at(0) #=> 1
8268 * The #slice method works in an identical manner to Array#[].
8270 * To raise an error for indices outside of the array bounds or else to
8271 * provide a default value when that happens, you can use #fetch.
8273 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8274 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8275 * arr.fetch(100, "oops") #=> "oops"
8277 * The special methods #first and #last will return the first and last
8278 * elements of an array, respectively.
8280 * arr.first #=> 1
8281 * arr.last #=> 6
8283 * To return the first +n+ elements of an array, use #take
8285 * arr.take(3) #=> [1, 2, 3]
8287 * #drop does the opposite of #take, by returning the elements after +n+
8288 * elements have been dropped:
8290 * arr.drop(3) #=> [4, 5, 6]
8292 * == Obtaining Information about an +Array+
8294 * Arrays keep track of their own length at all times. To query an array
8295 * about the number of elements it contains, use #length, #count or #size.
8297 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8298 * browsers.length #=> 5
8299 * browsers.count #=> 5
8301 * To check whether an array contains any elements at all
8303 * browsers.empty? #=> false
8305 * To check whether a particular item is included in the array
8307 * browsers.include?('Konqueror') #=> false
8309 * == Adding Items to Arrays
8311 * Items can be added to the end of an array by using either #push or #<<
8313 * arr = [1, 2, 3, 4]
8314 * arr.push(5) #=> [1, 2, 3, 4, 5]
8315 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8317 * #unshift will add a new item to the beginning of an array.
8319 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8321 * With #insert you can add a new element to an array at any position.
8323 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8325 * Using the #insert method, you can also insert multiple values at once:
8327 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8328 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8330 * == Removing Items from an +Array+
8332 * The method #pop removes the last element in an array and returns it:
8334 * arr = [1, 2, 3, 4, 5, 6]
8335 * arr.pop #=> 6
8336 * arr #=> [1, 2, 3, 4, 5]
8338 * To retrieve and at the same time remove the first item, use #shift:
8340 * arr.shift #=> 1
8341 * arr #=> [2, 3, 4, 5]
8343 * To delete an element at a particular index:
8345 * arr.delete_at(2) #=> 4
8346 * arr #=> [2, 3, 5]
8348 * To delete a particular element anywhere in an array, use #delete:
8350 * arr = [1, 2, 2, 3]
8351 * arr.delete(2) #=> 2
8352 * arr #=> [1,3]
8354 * A useful method if you need to remove +nil+ values from an array is
8355 * #compact:
8357 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8358 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8359 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8360 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8361 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8363 * Another common need is to remove duplicate elements from an array.
8365 * It has the non-destructive #uniq, and destructive method #uniq!
8367 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8368 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8370 * == Iterating over Arrays
8372 * Like all classes that include the Enumerable module, +Array+ has an each
8373 * method, which defines what elements should be iterated over and how. In
8374 * case of Array's #each, all elements in the +Array+ instance are yielded to
8375 * the supplied block in sequence.
8377 * Note that this operation leaves the array unchanged.
8379 * arr = [1, 2, 3, 4, 5]
8380 * arr.each {|a| print a -= 10, " "}
8381 * # prints: -9 -8 -7 -6 -5
8382 * #=> [1, 2, 3, 4, 5]
8384 * Another sometimes useful iterator is #reverse_each which will iterate over
8385 * the elements in the array in reverse order.
8387 * words = %w[first second third fourth fifth sixth]
8388 * str = ""
8389 * words.reverse_each {|word| str += "#{word} "}
8390 * p str #=> "sixth fifth fourth third second first "
8392 * The #map method can be used to create a new array based on the original
8393 * array, but with the values modified by the supplied block:
8395 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8396 * arr #=> [1, 2, 3, 4, 5]
8397 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8398 * arr #=> [1, 4, 9, 16, 25]
8401 * == Selecting Items from an +Array+
8403 * Elements can be selected from an array according to criteria defined in a
8404 * block. The selection can happen in a destructive or a non-destructive
8405 * manner. While the destructive operations will modify the array they were
8406 * called on, the non-destructive methods usually return a new array with the
8407 * selected elements, but leave the original array unchanged.
8409 * === Non-destructive Selection
8411 * arr = [1, 2, 3, 4, 5, 6]
8412 * arr.select {|a| a > 3} #=> [4, 5, 6]
8413 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8414 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8415 * arr #=> [1, 2, 3, 4, 5, 6]
8417 * === Destructive Selection
8419 * #select! and #reject! are the corresponding destructive methods to #select
8420 * and #reject
8422 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8423 * opposite result when supplied with the same block:
8425 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8426 * arr #=> [4, 5, 6]
8428 * arr = [1, 2, 3, 4, 5, 6]
8429 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8430 * arr #=> [1, 2, 3]
8432 * == What's Here
8434 * First, what's elsewhere. \Class +Array+:
8436 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8437 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8438 * which provides dozens of additional methods.
8440 * Here, class +Array+ provides methods that are useful for:
8442 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8443 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8444 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8445 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8446 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8447 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8448 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8449 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8450 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8451 * - {And more....}[rdoc-ref:Array@Other+Methods]
8453 * === Methods for Creating an +Array+
8455 * - ::[]: Returns a new array populated with given objects.
8456 * - ::new: Returns a new array.
8457 * - ::try_convert: Returns a new array created from a given object.
8459 * === Methods for Querying
8461 * - #length, #size: Returns the count of elements.
8462 * - #include?: Returns whether any element <tt>==</tt> a given object.
8463 * - #empty?: Returns whether there are no elements.
8464 * - #all?: Returns whether all elements meet a given criterion.
8465 * - #any?: Returns whether any element meets a given criterion.
8466 * - #none?: Returns whether no element <tt>==</tt> a given object.
8467 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8468 * - #count: Returns the count of elements that meet a given criterion.
8469 * - #find_index, #index: Returns the index of the first element that meets a given criterion.
8470 * - #rindex: Returns the index of the last element that meets a given criterion.
8471 * - #hash: Returns the integer hash code.
8473 * === Methods for Comparing
8475 * - #<=>: Returns -1, 0, or 1 * as +self+ is less than, equal to, or
8476 * greater than a given object.
8477 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
8478 * in a given object.
8479 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8480 * element in a given object.
8482 * === Methods for Fetching
8484 * These methods do not modify +self+.
8486 * - #[]: Returns one or more elements.
8487 * - #fetch: Returns the element at a given offset.
8488 * - #first: Returns one or more leading elements.
8489 * - #last: Returns one or more trailing elements.
8490 * - #max: Returns one or more maximum-valued elements,
8491 * as determined by <tt><=></tt> or a given block.
8492 * - #min: Returns one or more minimum-valued elements,
8493 * as determined by <tt><=></tt> or a given block.
8494 * - #minmax: Returns the minimum-valued and maximum-valued elements,
8495 * as determined by <tt><=></tt> or a given block.
8496 * - #assoc: Returns the first element that is an array
8497 * whose first element <tt>==</tt> a given object.
8498 * - #rassoc: Returns the first element that is an array
8499 * whose second element <tt>==</tt> a given object.
8500 * - #at: Returns the element at a given offset.
8501 * - #values_at: Returns the elements at given offsets.
8502 * - #dig: Returns the object in nested objects
8503 * that is specified by a given index and additional arguments.
8504 * - #drop: Returns trailing elements as determined by a given index.
8505 * - #take: Returns leading elements as determined by a given index.
8506 * - #drop_while: Returns trailing elements as determined by a given block.
8507 * - #take_while: Returns leading elements as determined by a given block.
8508 * - #slice: Returns consecutive elements as determined by a given argument.
8509 * - #sort: Returns all elements in an order determined by <tt><=></tt> or a given block.
8510 * - #reverse: Returns all elements in reverse order.
8511 * - #compact: Returns an array containing all non-+nil+ elements.
8512 * - #select, #filter: Returns an array containing elements selected by a given block.
8513 * - #uniq: Returns an array containing non-duplicate elements.
8514 * - #rotate: Returns all elements with some rotated from one end to the other.
8515 * - #bsearch: Returns an element selected via a binary search
8516 * as determined by a given block.
8517 * - #bsearch_index: Returns the index of an element selected via a binary search
8518 * as determined by a given block.
8519 * - #sample: Returns one or more random elements.
8520 * - #shuffle: Returns elements in a random order.
8522 * === Methods for Assigning
8524 * These methods add, replace, or reorder elements in +self+.
8526 * - #[]=: Assigns specified elements with a given object.
8527 * - #push, #append, #<<: Appends trailing elements.
8528 * - #unshift, #prepend: Prepends leading elements.
8529 * - #insert: Inserts given objects at a given offset; does not replace elements.
8530 * - #concat: Appends all elements from given arrays.
8531 * - #fill: Replaces specified elements with specified objects.
8532 * - #replace: Replaces the content of +self+ with the content of a given array.
8533 * - #reverse!: Replaces +self+ with its elements reversed.
8534 * - #rotate!: Replaces +self+ with its elements rotated.
8535 * - #shuffle!: Replaces +self+ with its elements in random order.
8536 * - #sort!: Replaces +self+ with its elements sorted,
8537 * as determined by <tt><=></tt> or a given block.
8538 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8540 * === Methods for Deleting
8542 * Each of these methods removes elements from +self+:
8544 * - #pop: Removes and returns the last element.
8545 * - #shift: Removes and returns the first element.
8546 * - #compact!: Removes all +nil+ elements.
8547 * - #delete: Removes elements equal to a given object.
8548 * - #delete_at: Removes the element at a given offset.
8549 * - #delete_if: Removes elements specified by a given block.
8550 * - #keep_if: Removes elements not specified by a given block.
8551 * - #reject!: Removes elements specified by a given block.
8552 * - #select!, #filter!: Removes elements not specified by a given block.
8553 * - #slice!: Removes and returns a sequence of elements.
8554 * - #uniq!: Removes duplicates.
8556 * === Methods for Combining
8558 * - #&: Returns an array containing elements found both in +self+ and a given array.
8559 * - #intersection: Returns an array containing elements found both in +self+
8560 * and in each given array.
8561 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8562 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8563 * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
8564 * duplicates removed.
8565 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
8566 * duplicates removed.
8567 * - #difference: Returns an array containing all elements of +self+ that are not found
8568 * in any of the given arrays..
8569 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8571 * === Methods for Iterating
8573 * - #each: Passes each element to a given block.
8574 * - #reverse_each: Passes each element, in reverse order, to a given block.
8575 * - #each_index: Passes each element index to a given block.
8576 * - #cycle: Calls a given block with each element, then does so again,
8577 * for a specified number of times, or forever.
8578 * - #combination: Calls a given block with combinations of elements of +self+;
8579 * a combination does not use the same element more than once.
8580 * - #permutation: Calls a given block with permutations of elements of +self+;
8581 * a permutation does not use the same element more than once.
8582 * - #repeated_combination: Calls a given block with combinations of elements of +self+;
8583 * a combination may use the same element more than once.
8584 * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
8585 * a permutation may use the same element more than once.
8587 * === Methods for Converting
8589 * - #map, #collect: Returns an array containing the block return-value for each element.
8590 * - #map!, #collect!: Replaces each element with a block return-value.
8591 * - #flatten: Returns an array that is a recursive flattening of +self+.
8592 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8593 * - #inspect, #to_s: Returns a new String containing the elements.
8594 * - #join: Returns a newsString containing the elements joined by the field separator.
8595 * - #to_a: Returns +self+ or a new array containing all elements.
8596 * - #to_ary: Returns +self+.
8597 * - #to_h: Returns a new hash formed from the elements.
8598 * - #transpose: Transposes +self+, which must be an array of arrays.
8599 * - #zip: Returns a new array of arrays containing +self+ and given arrays;
8600 * follow the link for details.
8602 * === Other Methods
8604 * - #*: Returns one of the following:
8606 * - With integer argument +n+, a new array that is the concatenation
8607 * of +n+ copies of +self+.
8608 * - With string argument +field_separator+, a new string that is equivalent to
8609 * <tt>join(field_separator)</tt>.
8611 * - #abbrev: Returns a hash of unambiguous abbreviations for elements.
8612 * - #pack: Packs the elements into a binary sequence.
8613 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8616 void
8617 Init_Array(void)
8619 rb_cArray = rb_define_class("Array", rb_cObject);
8620 rb_include_module(rb_cArray, rb_mEnumerable);
8622 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
8623 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
8624 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
8625 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
8626 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
8627 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
8629 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
8630 rb_define_alias(rb_cArray, "to_s", "inspect");
8631 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
8632 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
8633 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
8635 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
8636 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
8637 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
8639 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
8640 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
8641 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
8642 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
8643 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
8644 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
8645 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
8646 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
8647 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
8648 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
8649 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
8650 rb_define_alias(rb_cArray, "append", "push");
8651 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
8652 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
8653 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
8654 rb_define_alias(rb_cArray, "prepend", "unshift");
8655 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
8656 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
8657 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
8658 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
8659 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
8660 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
8661 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
8662 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
8663 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
8664 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
8665 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
8666 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
8667 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
8668 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
8669 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
8670 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
8671 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
8672 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
8673 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
8674 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
8675 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8676 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
8677 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8678 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
8679 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
8680 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
8681 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
8682 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
8683 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
8684 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
8685 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
8686 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
8687 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
8688 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
8689 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
8690 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
8691 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
8692 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
8693 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
8695 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
8696 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
8698 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
8699 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
8701 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
8702 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
8704 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
8705 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
8706 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
8708 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
8709 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
8710 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
8712 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
8713 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
8714 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
8715 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
8716 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
8717 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
8718 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
8719 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
8720 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
8721 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
8722 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
8723 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
8724 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
8726 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
8727 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
8728 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
8729 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
8730 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
8731 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
8732 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
8733 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
8734 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
8735 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
8736 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
8737 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
8739 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
8742 #include "array.rbinc"