1 /**********************************************************************
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"
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"
28 #include "ruby/encoding.h"
30 #include "ruby/util.h"
38 #include "ruby_assert.h"
41 VALUE rb_cArray_empty_frozen
;
45 * 1: RARRAY_EMBED_FLAG
46 * The array is embedded (its contents follow the header, rather than
47 * being on a separately allocated buffer).
48 * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
49 * The array is shared. The buffer this array points to is owned by
50 * another array (the shared root).
51 * 3-9: RARRAY_EMBED_LEN
52 * The length of the array when RARRAY_EMBED_FLAG is set.
53 * 12: RARRAY_SHARED_ROOT_FLAG
54 * The array is a shared root that does reference counting. The buffer
55 * this array points to is owned by this array but may be pointed to
57 * Note: Frozen arrays may be a shared root without this flag being
58 * set. Frozen arrays do not have reference counting because
59 * they cannot be modified. Not updating the reference count
60 * improves copy-on-write performance. Their reference count is
61 * assumed to be infinity.
62 * 14: RARRAY_PTR_IN_USE_FLAG
63 * The buffer of the array is in use. This is only used during
67 /* for OPTIMIZED_CMP: */
70 #define ARY_DEFAULT_SIZE 16
71 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
72 #define SMALL_ARRAY_LEN 16
74 RBIMPL_ATTR_MAYBE_UNUSED()
76 should_be_T_ARRAY(VALUE ary
)
78 return RB_TYPE_P(ary
, T_ARRAY
);
81 #define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
82 #define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
83 #define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
84 RARRAY(a)->as.heap.aux.capa)
86 #define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
87 #define ARY_EMBED_LEN(a) \
88 (RUBY_ASSERT(ARY_EMBED_P(a)), \
89 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
90 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
91 #define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
93 #define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
94 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
96 #define FL_SET_EMBED(a) do { \
97 RUBY_ASSERT(!ARY_SHARED_P(a)); \
98 FL_SET((a), RARRAY_EMBED_FLAG); \
102 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
103 #define FL_SET_SHARED(ary) do { \
104 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
105 FL_SET((ary), RARRAY_SHARED_FLAG); \
107 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
109 #define ARY_SET_PTR(ary, p) do { \
110 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
111 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
112 RARRAY(ary)->as.heap.ptr = (p); \
114 #define ARY_SET_EMBED_LEN(ary, n) do { \
116 RUBY_ASSERT(ARY_EMBED_P(ary)); \
117 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
118 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
120 #define ARY_SET_HEAP_LEN(ary, n) do { \
121 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
122 RARRAY(ary)->as.heap.len = (n); \
124 #define ARY_SET_LEN(ary, n) do { \
125 if (ARY_EMBED_P(ary)) { \
126 ARY_SET_EMBED_LEN((ary), (n)); \
129 ARY_SET_HEAP_LEN((ary), (n)); \
131 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
133 #define ARY_INCREASE_PTR(ary, n) do { \
134 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
135 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
136 RARRAY(ary)->as.heap.ptr += (n); \
138 #define ARY_INCREASE_LEN(ary, n) do { \
139 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
140 if (ARY_EMBED_P(ary)) { \
141 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
144 RARRAY(ary)->as.heap.len += (n); \
148 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
149 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
150 #define ARY_SET_CAPA(ary, n) do { \
151 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
152 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
153 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
154 RARRAY(ary)->as.heap.aux.capa = (n); \
157 #define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
158 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
159 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
160 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
161 RUBY_ASSERT((value) >= 0); \
162 RARRAY(ary)->as.heap.aux.capa = (value); \
164 #define FL_SET_SHARED_ROOT(ary) do { \
165 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
166 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
167 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
171 ARY_SET(VALUE a
, long i
, VALUE v
)
173 RUBY_ASSERT(!ARY_SHARED_P(a
));
174 RUBY_ASSERT(!OBJ_FROZEN(a
));
176 RARRAY_ASET(a
, i
, v
);
181 ary_embed_capa(VALUE ary
)
183 size_t size
= rb_gc_obj_slot_size(ary
) - offsetof(struct RArray
, as
.ary
);
184 RUBY_ASSERT(size
% sizeof(VALUE
) == 0);
185 return size
/ sizeof(VALUE
);
189 ary_embed_size(long capa
)
191 return offsetof(struct RArray
, as
.ary
) + (sizeof(VALUE
) * capa
);
195 ary_embeddable_p(long capa
)
197 return rb_gc_size_allocatable_p(ary_embed_size(capa
));
201 rb_ary_embeddable_p(VALUE ary
)
203 /* An array cannot be turned embeddable when the array is:
204 * - Shared root: other objects may point to the buffer of this array
205 * so we cannot make it embedded.
206 * - Frozen: this array may also be a shared root without the shared root
208 * - Shared: we don't want to re-embed an array that points to a shared
209 * root (to save memory).
211 return !(ARY_SHARED_ROOT_P(ary
) || OBJ_FROZEN(ary
) || ARY_SHARED_P(ary
));
215 rb_ary_size_as_embedded(VALUE ary
)
219 if (ARY_EMBED_P(ary
)) {
220 real_size
= ary_embed_size(ARY_EMBED_LEN(ary
));
222 else if (rb_ary_embeddable_p(ary
)) {
223 real_size
= ary_embed_size(ARY_HEAP_CAPA(ary
));
226 real_size
= sizeof(struct RArray
);
233 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
236 ary_verify_(VALUE ary
, const char *file
, int line
)
238 RUBY_ASSERT(RB_TYPE_P(ary
, T_ARRAY
));
240 if (ARY_SHARED_P(ary
)) {
241 VALUE root
= ARY_SHARED_ROOT(ary
);
242 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
243 const VALUE
*root_ptr
= RARRAY_CONST_PTR(root
);
244 long len
= ARY_HEAP_LEN(ary
), root_len
= RARRAY_LEN(root
);
245 RUBY_ASSERT(ARY_SHARED_ROOT_P(root
) || OBJ_FROZEN(root
));
246 RUBY_ASSERT(root_ptr
<= ptr
&& ptr
+ len
<= root_ptr
+ root_len
);
249 else if (ARY_EMBED_P(ary
)) {
250 RUBY_ASSERT(!ARY_SHARED_P(ary
));
251 RUBY_ASSERT(RARRAY_LEN(ary
) <= ary_embed_capa(ary
));
254 const VALUE
*ptr
= RARRAY_CONST_PTR(ary
);
255 long i
, len
= RARRAY_LEN(ary
);
257 if (len
> 1) len
= 1; /* check only HEAD */
258 for (i
=0; i
<len
; i
++) {
259 v
= ptr
[i
]; /* access check */
268 rb_ary_verify(VALUE ary
)
273 #define ary_verify(ary) ((void)0)
277 rb_ary_ptr_use_start(VALUE ary
)
280 FL_SET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
282 return (VALUE
*)RARRAY_CONST_PTR(ary
);
286 rb_ary_ptr_use_end(VALUE ary
)
289 FL_UNSET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
294 rb_mem_clear(VALUE
*mem
, long size
)
302 ary_mem_clear(VALUE ary
, long beg
, long size
)
304 RARRAY_PTR_USE(ary
, ptr
, {
305 rb_mem_clear(ptr
+ beg
, size
);
310 memfill(register VALUE
*mem
, register long size
, register VALUE val
)
318 ary_memfill(VALUE ary
, long beg
, long size
, VALUE val
)
320 RARRAY_PTR_USE(ary
, ptr
, {
321 memfill(ptr
+ beg
, size
, val
);
322 RB_OBJ_WRITTEN(ary
, Qundef
, val
);
327 ary_memcpy0(VALUE ary
, long beg
, long argc
, const VALUE
*argv
, VALUE buff_owner_ary
)
329 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary
));
331 if (argc
> (int)(128/sizeof(VALUE
)) /* is magic number (cache line size) */) {
332 rb_gc_writebarrier_remember(buff_owner_ary
);
333 RARRAY_PTR_USE(ary
, ptr
, {
334 MEMCPY(ptr
+beg
, argv
, VALUE
, argc
);
339 RARRAY_PTR_USE(ary
, ptr
, {
340 for (i
=0; i
<argc
; i
++) {
341 RB_OBJ_WRITE(buff_owner_ary
, &ptr
[i
+beg
], argv
[i
]);
348 ary_memcpy(VALUE ary
, long beg
, long argc
, const VALUE
*argv
)
350 ary_memcpy0(ary
, beg
, argc
, argv
, ary
);
354 ary_heap_alloc_buffer(size_t capa
)
356 return ALLOC_N(VALUE
, capa
);
360 ary_heap_free_ptr(VALUE ary
, const VALUE
*ptr
, long size
)
362 ruby_sized_xfree((void *)ptr
, size
);
366 ary_heap_free(VALUE ary
)
368 ary_heap_free_ptr(ary
, ARY_HEAP_PTR(ary
), ARY_HEAP_SIZE(ary
));
372 ary_heap_realloc(VALUE ary
, size_t new_capa
)
374 RUBY_ASSERT(!OBJ_FROZEN(ary
));
375 SIZED_REALLOC_N(RARRAY(ary
)->as
.heap
.ptr
, VALUE
, new_capa
, ARY_HEAP_CAPA(ary
));
382 rb_ary_make_embedded(VALUE ary
)
384 RUBY_ASSERT(rb_ary_embeddable_p(ary
));
385 if (!ARY_EMBED_P(ary
)) {
386 const VALUE
*buf
= ARY_HEAP_PTR(ary
);
387 long len
= ARY_HEAP_LEN(ary
);
390 ARY_SET_EMBED_LEN(ary
, len
);
392 MEMCPY((void *)ARY_EMBED_PTR(ary
), (void *)buf
, VALUE
, len
);
394 ary_heap_free_ptr(ary
, buf
, len
* sizeof(VALUE
));
399 ary_resize_capa(VALUE ary
, long capacity
)
401 RUBY_ASSERT(RARRAY_LEN(ary
) <= capacity
);
402 RUBY_ASSERT(!OBJ_FROZEN(ary
));
403 RUBY_ASSERT(!ARY_SHARED_P(ary
));
405 if (capacity
> ary_embed_capa(ary
)) {
406 size_t new_capa
= capacity
;
407 if (ARY_EMBED_P(ary
)) {
408 long len
= ARY_EMBED_LEN(ary
);
409 VALUE
*ptr
= ary_heap_alloc_buffer(capacity
);
411 MEMCPY(ptr
, ARY_EMBED_PTR(ary
), VALUE
, len
);
413 ARY_SET_PTR(ary
, ptr
);
414 ARY_SET_HEAP_LEN(ary
, len
);
417 new_capa
= ary_heap_realloc(ary
, capacity
);
419 ARY_SET_CAPA(ary
, new_capa
);
422 if (!ARY_EMBED_P(ary
)) {
423 long len
= ARY_HEAP_LEN(ary
);
424 long old_capa
= ARY_HEAP_CAPA(ary
);
425 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
427 if (len
> capacity
) len
= capacity
;
428 MEMCPY((VALUE
*)RARRAY(ary
)->as
.ary
, ptr
, VALUE
, len
);
429 ary_heap_free_ptr(ary
, ptr
, old_capa
);
432 ARY_SET_LEN(ary
, len
);
440 ary_shrink_capa(VALUE ary
)
442 long capacity
= ARY_HEAP_LEN(ary
);
443 long old_capa
= ARY_HEAP_CAPA(ary
);
444 RUBY_ASSERT(!ARY_SHARED_P(ary
));
445 RUBY_ASSERT(old_capa
>= capacity
);
446 if (old_capa
> capacity
) {
447 size_t new_capa
= ary_heap_realloc(ary
, capacity
);
448 ARY_SET_CAPA(ary
, new_capa
);
455 ary_double_capa(VALUE ary
, long min
)
457 long new_capa
= ARY_CAPA(ary
) / 2;
459 if (new_capa
< ARY_DEFAULT_SIZE
) {
460 new_capa
= ARY_DEFAULT_SIZE
;
462 if (new_capa
>= ARY_MAX_SIZE
- min
) {
463 new_capa
= (ARY_MAX_SIZE
- min
) / 2;
466 ary_resize_capa(ary
, new_capa
);
472 rb_ary_decrement_share(VALUE shared_root
)
474 if (!OBJ_FROZEN(shared_root
)) {
475 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
476 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
- 1);
481 rb_ary_unshare(VALUE ary
)
483 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
484 rb_ary_decrement_share(shared_root
);
485 FL_UNSET_SHARED(ary
);
489 rb_ary_reset(VALUE ary
)
491 if (ARY_OWNS_HEAP_P(ary
)) {
494 else if (ARY_SHARED_P(ary
)) {
499 ARY_SET_EMBED_LEN(ary
, 0);
503 rb_ary_increment_share(VALUE shared_root
)
505 if (!OBJ_FROZEN(shared_root
)) {
506 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
507 RUBY_ASSERT(num
>= 0);
508 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
+ 1);
514 rb_ary_set_shared(VALUE ary
, VALUE shared_root
)
516 RUBY_ASSERT(!ARY_EMBED_P(ary
));
517 RUBY_ASSERT(!OBJ_FROZEN(ary
));
518 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root
) || OBJ_FROZEN(shared_root
));
520 rb_ary_increment_share(shared_root
);
522 RB_OBJ_WRITE(ary
, &RARRAY(ary
)->as
.heap
.aux
.shared_root
, shared_root
);
524 RB_DEBUG_COUNTER_INC(obj_ary_shared_create
);
528 rb_ary_modify_check(VALUE ary
)
530 rb_check_frozen(ary
);
535 rb_ary_cancel_sharing(VALUE ary
)
537 if (ARY_SHARED_P(ary
)) {
538 long shared_len
, len
= RARRAY_LEN(ary
);
539 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
541 ary_verify(shared_root
);
543 if (len
<= ary_embed_capa(ary
)) {
544 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
545 FL_UNSET_SHARED(ary
);
547 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
);
548 rb_ary_decrement_share(shared_root
);
549 ARY_SET_EMBED_LEN(ary
, len
);
551 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root
) && len
> ((shared_len
= RARRAY_LEN(shared_root
))>>1)) {
552 long shift
= RARRAY_CONST_PTR(ary
) - RARRAY_CONST_PTR(shared_root
);
553 FL_UNSET_SHARED(ary
);
554 ARY_SET_PTR(ary
, RARRAY_CONST_PTR(shared_root
));
555 ARY_SET_CAPA(ary
, shared_len
);
556 RARRAY_PTR_USE(ary
, ptr
, {
557 MEMMOVE(ptr
, ptr
+shift
, VALUE
, len
);
559 FL_SET_EMBED(shared_root
);
560 rb_ary_decrement_share(shared_root
);
563 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
564 MEMCPY(ptr
, ARY_HEAP_PTR(ary
), VALUE
, len
);
566 ARY_SET_CAPA(ary
, len
);
567 ARY_SET_PTR(ary
, ptr
);
570 rb_gc_writebarrier_remember(ary
);
576 rb_ary_modify(VALUE ary
)
578 rb_ary_modify_check(ary
);
579 rb_ary_cancel_sharing(ary
);
583 ary_ensure_room_for_push(VALUE ary
, long add_len
)
585 long old_len
= RARRAY_LEN(ary
);
586 long new_len
= old_len
+ add_len
;
589 if (old_len
> ARY_MAX_SIZE
- add_len
) {
590 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
592 if (ARY_SHARED_P(ary
)) {
593 if (new_len
> ary_embed_capa(ary
)) {
594 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
595 if (ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
596 if (ARY_HEAP_PTR(ary
) - RARRAY_CONST_PTR(shared_root
) + new_len
<= RARRAY_LEN(shared_root
)) {
597 rb_ary_modify_check(ary
);
600 ary_verify(shared_root
);
604 /* if array is shared, then it is likely it participate in push/shift pattern */
606 capa
= ARY_CAPA(ary
);
607 if (new_len
> capa
- (capa
>> 6)) {
608 ary_double_capa(ary
, new_len
);
619 rb_ary_modify_check(ary
);
621 capa
= ARY_CAPA(ary
);
622 if (new_len
> capa
) {
623 ary_double_capa(ary
, new_len
);
634 * Freezes +self+ (if not already frozen); returns +self+:
637 * a.frozen? # => false
639 * a.frozen? # => true
641 * No further changes may be made to +self+;
642 * raises FrozenError if a change is attempted.
644 * Related: Kernel#frozen?.
648 rb_ary_freeze(VALUE ary
)
650 RUBY_ASSERT(RB_TYPE_P(ary
, T_ARRAY
));
652 if (OBJ_FROZEN(ary
)) return ary
;
654 if (!ARY_EMBED_P(ary
) && !ARY_SHARED_P(ary
) && !ARY_SHARED_ROOT_P(ary
)) {
655 ary_shrink_capa(ary
);
658 return rb_obj_freeze(ary
);
661 /* This can be used to take a snapshot of an array (with
662 e.g. rb_ary_replace) and check later whether the array has been
663 modified from the snapshot. The snapshot is cheap, though if
664 something does modify the array it will pay the cost of copying
665 it. If Array#pop or Array#shift has been called, the array will
666 be still shared with the snapshot, but the array length will
669 rb_ary_shared_with_p(VALUE ary1
, VALUE ary2
)
671 if (!ARY_EMBED_P(ary1
) && ARY_SHARED_P(ary1
) &&
672 !ARY_EMBED_P(ary2
) && ARY_SHARED_P(ary2
) &&
673 ARY_SHARED_ROOT(ary1
) == ARY_SHARED_ROOT(ary2
) &&
674 ARY_HEAP_LEN(ary1
) == ARY_HEAP_LEN(ary2
)) {
681 ary_alloc_embed(VALUE klass
, long capa
)
683 size_t size
= ary_embed_size(capa
);
684 RUBY_ASSERT(rb_gc_size_allocatable_p(size
));
685 NEWOBJ_OF(ary
, struct RArray
, klass
,
686 T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
689 * FL_SET_EMBED((VALUE)ary);
690 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
696 ary_alloc_heap(VALUE klass
)
698 NEWOBJ_OF(ary
, struct RArray
, klass
,
699 T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
700 sizeof(struct RArray
), 0);
705 empty_ary_alloc(VALUE klass
)
707 RUBY_DTRACE_CREATE_HOOK(ARRAY
, 0);
708 return ary_alloc_embed(klass
, 0);
712 ary_new(VALUE klass
, long capa
)
717 rb_raise(rb_eArgError
, "negative array size (or size too big)");
719 if (capa
> ARY_MAX_SIZE
) {
720 rb_raise(rb_eArgError
, "array size too big");
723 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
725 if (ary_embeddable_p(capa
)) {
726 ary
= ary_alloc_embed(klass
, capa
);
729 ary
= ary_alloc_heap(klass
);
730 ARY_SET_CAPA(ary
, capa
);
731 RUBY_ASSERT(!ARY_EMBED_P(ary
));
733 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
734 ARY_SET_HEAP_LEN(ary
, 0);
741 rb_ary_new_capa(long capa
)
743 return ary_new(rb_cArray
, capa
);
749 return rb_ary_new_capa(0);
753 (rb_ary_new_from_args
)(long n
, ...)
759 ary
= rb_ary_new2(n
);
762 for (i
=0; i
<n
; i
++) {
763 ARY_SET(ary
, i
, va_arg(ar
, VALUE
));
772 rb_ary_tmp_new_from_values(VALUE klass
, long n
, const VALUE
*elts
)
776 ary
= ary_new(klass
, n
);
778 ary_memcpy(ary
, 0, n
, elts
);
786 rb_ary_new_from_values(long n
, const VALUE
*elts
)
788 return rb_ary_tmp_new_from_values(rb_cArray
, n
, elts
);
792 ec_ary_alloc_embed(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
794 size_t size
= ary_embed_size(capa
);
795 RUBY_ASSERT(rb_gc_size_allocatable_p(size
));
796 NEWOBJ_OF(ary
, struct RArray
, klass
,
797 T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
800 * FL_SET_EMBED((VALUE)ary);
801 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
807 ec_ary_alloc_heap(rb_execution_context_t
*ec
, VALUE klass
)
809 NEWOBJ_OF(ary
, struct RArray
, klass
,
810 T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0),
811 sizeof(struct RArray
), ec
);
816 ec_ary_new(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
821 rb_raise(rb_eArgError
, "negative array size (or size too big)");
823 if (capa
> ARY_MAX_SIZE
) {
824 rb_raise(rb_eArgError
, "array size too big");
827 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
829 if (ary_embeddable_p(capa
)) {
830 ary
= ec_ary_alloc_embed(ec
, klass
, capa
);
833 ary
= ec_ary_alloc_heap(ec
, klass
);
834 ARY_SET_CAPA(ary
, capa
);
835 RUBY_ASSERT(!ARY_EMBED_P(ary
));
837 ARY_SET_PTR(ary
, ary_heap_alloc_buffer(capa
));
838 ARY_SET_HEAP_LEN(ary
, 0);
845 rb_ec_ary_new_from_values(rb_execution_context_t
*ec
, long n
, const VALUE
*elts
)
849 ary
= ec_ary_new(ec
, rb_cArray
, n
);
851 ary_memcpy(ary
, 0, n
, elts
);
859 rb_ary_hidden_new(long capa
)
861 VALUE ary
= ary_new(0, capa
);
866 rb_ary_hidden_new_fill(long capa
)
868 VALUE ary
= rb_ary_hidden_new(capa
);
869 ary_memfill(ary
, 0, capa
, Qnil
);
870 ARY_SET_LEN(ary
, capa
);
875 rb_ary_free(VALUE ary
)
877 if (ARY_OWNS_HEAP_P(ary
)) {
878 if (USE_DEBUG_COUNTER
&&
879 !ARY_SHARED_ROOT_P(ary
) &&
880 ARY_HEAP_CAPA(ary
) > RARRAY_LEN(ary
)) {
881 RB_DEBUG_COUNTER_INC(obj_ary_extracapa
);
884 RB_DEBUG_COUNTER_INC(obj_ary_ptr
);
888 RB_DEBUG_COUNTER_INC(obj_ary_embed
);
891 if (ARY_SHARED_P(ary
)) {
892 RB_DEBUG_COUNTER_INC(obj_ary_shared
);
894 if (ARY_SHARED_ROOT_P(ary
) && ARY_SHARED_ROOT_OCCUPIED(ary
)) {
895 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied
);
899 static VALUE fake_ary_flags
;
902 init_fake_ary_flags(void)
904 struct RArray fake_ary
= {0};
905 fake_ary
.basic
.flags
= T_ARRAY
;
906 VALUE ary
= (VALUE
)&fake_ary
;
908 return fake_ary
.basic
.flags
;
912 rb_setup_fake_ary(struct RArray
*fake_ary
, const VALUE
*list
, long len
)
914 fake_ary
->basic
.flags
= fake_ary_flags
;
915 RBASIC_CLEAR_CLASS((VALUE
)fake_ary
);
917 // bypass frozen checks
918 fake_ary
->as
.heap
.ptr
= list
;
919 fake_ary
->as
.heap
.len
= len
;
920 fake_ary
->as
.heap
.aux
.capa
= len
;
921 return (VALUE
)fake_ary
;
925 rb_ary_memsize(VALUE ary
)
927 if (ARY_OWNS_HEAP_P(ary
)) {
928 return ARY_CAPA(ary
) * sizeof(VALUE
);
936 ary_make_shared(VALUE ary
)
940 if (ARY_SHARED_P(ary
)) {
941 return ARY_SHARED_ROOT(ary
);
943 else if (ARY_SHARED_ROOT_P(ary
)) {
946 else if (OBJ_FROZEN(ary
)) {
950 long capa
= ARY_CAPA(ary
);
951 long len
= RARRAY_LEN(ary
);
953 /* Shared roots cannot be embedded because the reference count
954 * (refcnt) is stored in as.heap.aux.capa. */
955 VALUE shared
= ary_alloc_heap(0);
956 FL_SET_SHARED_ROOT(shared
);
958 if (ARY_EMBED_P(ary
)) {
959 VALUE
*ptr
= ary_heap_alloc_buffer(capa
);
960 ARY_SET_PTR(shared
, ptr
);
961 ary_memcpy(shared
, 0, len
, RARRAY_CONST_PTR(ary
));
964 ARY_SET_HEAP_LEN(ary
, len
);
965 ARY_SET_PTR(ary
, ptr
);
968 ARY_SET_PTR(shared
, RARRAY_CONST_PTR(ary
));
971 ARY_SET_LEN(shared
, capa
);
972 ary_mem_clear(shared
, len
, capa
- len
);
973 rb_ary_set_shared(ary
, shared
);
983 ary_make_substitution(VALUE ary
)
985 long len
= RARRAY_LEN(ary
);
987 if (ary_embeddable_p(len
)) {
988 VALUE subst
= rb_ary_new_capa(len
);
989 RUBY_ASSERT(ARY_EMBED_P(subst
));
991 ary_memcpy(subst
, 0, len
, RARRAY_CONST_PTR(ary
));
992 ARY_SET_EMBED_LEN(subst
, len
);
996 return rb_ary_increment_share(ary_make_shared(ary
));
1001 rb_assoc_new(VALUE car
, VALUE cdr
)
1003 return rb_ary_new3(2, car
, cdr
);
1007 rb_to_array_type(VALUE ary
)
1009 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
1011 #define to_ary rb_to_array_type
1014 rb_check_array_type(VALUE ary
)
1016 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
1020 rb_check_to_array(VALUE ary
)
1022 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1026 rb_to_array(VALUE ary
)
1028 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1033 * Array.try_convert(object) -> object, new_array, or nil
1035 * Attempts to return an array, based on the given +object+.
1037 * If +object+ is an array, returns +object+.
1039 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1040 * calls <tt>object.to_ary</tt>:
1041 * if the return value is an array or +nil+, returns that value;
1042 * if not, raises TypeError.
1044 * Otherwise returns +nil+.
1046 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1050 rb_ary_s_try_convert(VALUE dummy
, VALUE ary
)
1052 return rb_check_array_type(ary
);
1057 rb_ary_s_new(int argc
, VALUE
*argv
, VALUE klass
)
1061 if (klass
== rb_cArray
) {
1063 if (argc
> 0 && FIXNUM_P(argv
[0])) {
1064 size
= FIX2LONG(argv
[0]);
1065 if (size
< 0) size
= 0;
1068 ary
= ary_new(klass
, size
);
1070 rb_obj_call_init_kw(ary
, argc
, argv
, RB_PASS_CALLED_KEYWORDS
);
1073 ary
= rb_class_new_instance_pass_kw(argc
, argv
, klass
);
1081 * Array.new -> new_empty_array
1082 * Array.new(array) -> new_array
1083 * Array.new(size, default_value = nil) -> new_array
1084 * Array.new(size = 0) {|index| ... } -> new_array
1086 * Returns a new array.
1088 * With no block and no argument given, returns a new empty array:
1092 * With no block and array argument given, returns a new array with the same elements:
1094 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1096 * With no block and integer argument given, returns a new array containing
1097 * that many instances of the given +default_value+:
1099 * Array.new(0) # => []
1100 * Array.new(3) # => [nil, nil, nil]
1101 * Array.new(2, 3) # => [3, 3]
1103 * With a block given, returns an array of the given +size+;
1104 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1105 * the element at that +index+ in the returned array is the blocks return value:
1107 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1109 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1111 * array = Array.new(2, {})
1112 * array # => [{}, {}]
1114 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1116 * If you want the elements of the array to be distinct, you should pass a block:
1118 * array = Array.new(2) { {} }
1119 * array # => [{}, {}]
1121 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1123 * Raises TypeError if the first argument is not either an array
1124 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1125 * Raises ArgumentError if the first argument is a negative integer.
1127 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1131 rb_ary_initialize(int argc
, VALUE
*argv
, VALUE ary
)
1139 RUBY_ASSERT(ARY_EMBED_P(ary
));
1140 RUBY_ASSERT(ARY_EMBED_LEN(ary
) == 0);
1141 if (rb_block_given_p()) {
1142 rb_warning("given block not used");
1146 rb_scan_args(argc
, argv
, "02", &size
, &val
);
1147 if (argc
== 1 && !FIXNUM_P(size
)) {
1148 val
= rb_check_array_type(size
);
1150 rb_ary_replace(ary
, val
);
1155 len
= NUM2LONG(size
);
1156 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1158 rb_raise(rb_eArgError
, "negative array size");
1160 if (len
> ARY_MAX_SIZE
) {
1161 rb_raise(rb_eArgError
, "array size too big");
1163 /* recheck after argument conversion */
1165 ary_resize_capa(ary
, len
);
1166 if (rb_block_given_p()) {
1170 rb_warn("block supersedes default value argument");
1172 for (i
=0; i
<len
; i
++) {
1173 rb_ary_store(ary
, i
, rb_yield(LONG2NUM(i
)));
1174 ARY_SET_LEN(ary
, i
+ 1);
1178 ary_memfill(ary
, 0, len
, val
);
1179 ARY_SET_LEN(ary
, len
);
1185 * Returns a new array, populated with the given objects:
1187 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1189 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1191 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1195 rb_ary_s_create(int argc
, VALUE
*argv
, VALUE klass
)
1197 VALUE ary
= ary_new(klass
, argc
);
1198 if (argc
> 0 && argv
) {
1199 ary_memcpy(ary
, 0, argc
, argv
);
1200 ARY_SET_LEN(ary
, argc
);
1207 rb_ary_store(VALUE ary
, long idx
, VALUE val
)
1209 long len
= RARRAY_LEN(ary
);
1214 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
1218 else if (idx
>= ARY_MAX_SIZE
) {
1219 rb_raise(rb_eIndexError
, "index %ld too big", idx
);
1223 if (idx
>= ARY_CAPA(ary
)) {
1224 ary_double_capa(ary
, idx
);
1227 ary_mem_clear(ary
, len
, idx
- len
+ 1);
1231 ARY_SET_LEN(ary
, idx
+ 1);
1233 ARY_SET(ary
, idx
, val
);
1237 ary_make_partial(VALUE ary
, VALUE klass
, long offset
, long len
)
1239 RUBY_ASSERT(offset
>= 0);
1240 RUBY_ASSERT(len
>= 0);
1241 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1243 VALUE result
= ary_alloc_heap(klass
);
1244 size_t embed_capa
= ary_embed_capa(result
);
1245 if ((size_t)len
<= embed_capa
) {
1246 FL_SET_EMBED(result
);
1247 ary_memcpy(result
, 0, len
, RARRAY_CONST_PTR(ary
) + offset
);
1248 ARY_SET_EMBED_LEN(result
, len
);
1251 VALUE shared
= ary_make_shared(ary
);
1253 /* The ary_make_shared call may allocate, which can trigger a GC
1254 * compaction. This can cause the array to be embedded because it has
1256 FL_UNSET_EMBED(result
);
1258 ARY_SET_PTR(result
, RARRAY_CONST_PTR(ary
));
1259 ARY_SET_LEN(result
, RARRAY_LEN(ary
));
1260 rb_ary_set_shared(result
, shared
);
1262 ARY_INCREASE_PTR(result
, offset
);
1263 ARY_SET_LEN(result
, len
);
1273 ary_make_partial_step(VALUE ary
, VALUE klass
, long offset
, long len
, long step
)
1275 RUBY_ASSERT(offset
>= 0);
1276 RUBY_ASSERT(len
>= 0);
1277 RUBY_ASSERT(offset
+len
<= RARRAY_LEN(ary
));
1278 RUBY_ASSERT(step
!= 0);
1280 const long orig_len
= len
;
1282 if (step
> 0 && step
>= len
) {
1283 VALUE result
= ary_new(klass
, 1);
1284 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1285 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1287 RB_OBJ_WRITE(result
, ptr
, values
[offset
]);
1288 ARY_SET_EMBED_LEN(result
, 1);
1291 else if (step
< 0 && step
< -len
) {
1295 long ustep
= (step
< 0) ? -step
: step
;
1296 len
= roomof(len
, ustep
);
1299 long j
= offset
+ ((step
> 0) ? 0 : (orig_len
- 1));
1301 VALUE result
= ary_new(klass
, len
);
1302 if (ARY_EMBED_P(result
)) {
1303 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1304 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1306 for (i
= 0; i
< len
; ++i
) {
1307 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1310 ARY_SET_EMBED_LEN(result
, len
);
1313 const VALUE
*values
= RARRAY_CONST_PTR(ary
);
1315 RARRAY_PTR_USE(result
, ptr
, {
1316 for (i
= 0; i
< len
; ++i
) {
1317 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1321 ARY_SET_LEN(result
, len
);
1328 ary_make_shared_copy(VALUE ary
)
1330 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
1333 enum ary_take_pos_flags
1340 ary_take_first_or_last_n(VALUE ary
, long n
, enum ary_take_pos_flags last
)
1342 long len
= RARRAY_LEN(ary
);
1349 rb_raise(rb_eArgError
, "negative array size");
1354 return ary_make_partial(ary
, rb_cArray
, offset
, n
);
1358 ary_take_first_or_last(int argc
, const VALUE
*argv
, VALUE ary
, enum ary_take_pos_flags last
)
1360 argc
= rb_check_arity(argc
, 0, 1);
1361 /* the case optional argument is omitted should be handled in
1362 * callers of this function. if another arity case is added,
1363 * this arity check needs to rewrite. */
1364 RUBY_ASSERT_ALWAYS(argc
== 1);
1365 return ary_take_first_or_last_n(ary
, NUM2LONG(argv
[0]), last
);
1370 * self << object -> self
1372 * Appends +object+ as the last element in +self+; returns +self+:
1374 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1376 * Appends +object+ as a single element, even if it is another array:
1378 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1380 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1384 rb_ary_push(VALUE ary
, VALUE item
)
1386 long idx
= RARRAY_LEN((ary_verify(ary
), ary
));
1387 VALUE target_ary
= ary_ensure_room_for_push(ary
, 1);
1388 RARRAY_PTR_USE(ary
, ptr
, {
1389 RB_OBJ_WRITE(target_ary
, &ptr
[idx
], item
);
1391 ARY_SET_LEN(ary
, idx
+ 1);
1397 rb_ary_cat(VALUE ary
, const VALUE
*argv
, long len
)
1399 long oldlen
= RARRAY_LEN(ary
);
1400 VALUE target_ary
= ary_ensure_room_for_push(ary
, len
);
1401 ary_memcpy0(ary
, oldlen
, len
, argv
, target_ary
);
1402 ARY_SET_LEN(ary
, oldlen
+ len
);
1408 * push(*objects) -> self
1409 * append(*objects) -> self
1411 * Appends each argument in +objects+ to +self+; returns +self+:
1413 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1414 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1416 * Appends each argument as a single element, even if it is another array:
1418 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1419 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1421 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1425 rb_ary_push_m(int argc
, VALUE
*argv
, VALUE ary
)
1427 return rb_ary_cat(ary
, argv
, argc
);
1431 rb_ary_pop(VALUE ary
)
1434 rb_ary_modify_check(ary
);
1435 n
= RARRAY_LEN(ary
);
1436 if (n
== 0) return Qnil
;
1437 if (ARY_OWNS_HEAP_P(ary
) &&
1438 n
* 3 < ARY_CAPA(ary
) &&
1439 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
)
1441 ary_resize_capa(ary
, n
* 2);
1444 ARY_SET_LEN(ary
, n
);
1446 return RARRAY_AREF(ary
, n
);
1451 * pop -> object or nil
1452 * pop(count) -> new_array
1454 * Removes and returns trailing elements of +self+.
1456 * With no argument given, removes and returns the last element, if available;
1457 * otherwise returns +nil+:
1459 * a = [:foo, 'bar', 2]
1461 * a # => [:foo, "bar"]
1464 * With non-negative integer argument +count+ given,
1465 * returns a new array containing the trailing +count+ elements of +self+, as available:
1467 * a = [:foo, 'bar', 2]
1468 * a.pop(2) # => ["bar", 2]
1471 * a = [:foo, 'bar', 2]
1472 * a.pop(50) # => [:foo, "bar", 2]
1475 * Related: Array#push;
1476 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1480 rb_ary_pop_m(int argc
, VALUE
*argv
, VALUE ary
)
1485 return rb_ary_pop(ary
);
1488 rb_ary_modify_check(ary
);
1489 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
1490 ARY_INCREASE_LEN(ary
, -RARRAY_LEN(result
));
1496 rb_ary_shift(VALUE ary
)
1499 long len
= RARRAY_LEN(ary
);
1502 rb_ary_modify_check(ary
);
1506 top
= RARRAY_AREF(ary
, 0);
1508 rb_ary_behead(ary
, 1);
1515 * shift -> object or nil
1516 * shift(count) -> new_array or nil
1518 * Removes and returns leading elements from +self+.
1520 * With no argument, removes and returns one element, if available,
1521 * or +nil+ otherwise:
1528 * With non-negative numeric argument +count+ given,
1529 * removes and returns the first +count+ elements:
1532 * a.shift(2) # => [0, 1]
1534 * a.shift(1.1) # => [2]
1536 * a.shift(0) # => []
1539 * If +count+ is large,
1540 * removes and returns all elements:
1543 * a.shift(50) # => [0, 1, 2, 3]
1546 * If +self+ is empty, returns a new empty array.
1548 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1552 rb_ary_shift_m(int argc
, VALUE
*argv
, VALUE ary
)
1558 return rb_ary_shift(ary
);
1561 rb_ary_modify_check(ary
);
1562 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1563 n
= RARRAY_LEN(result
);
1564 rb_ary_behead(ary
,n
);
1570 rb_ary_behead(VALUE ary
, long n
)
1576 rb_ary_modify_check(ary
);
1578 if (!ARY_SHARED_P(ary
)) {
1579 if (ARY_EMBED_P(ary
) || RARRAY_LEN(ary
) < ARY_DEFAULT_SIZE
) {
1580 RARRAY_PTR_USE(ary
, ptr
, {
1581 MEMMOVE(ptr
, ptr
+ n
, VALUE
, RARRAY_LEN(ary
) - n
);
1582 }); /* WB: no new reference */
1583 ARY_INCREASE_LEN(ary
, -n
);
1588 ary_mem_clear(ary
, 0, n
);
1589 ary_make_shared(ary
);
1591 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
))) {
1592 ary_mem_clear(ary
, 0, n
);
1595 ARY_INCREASE_PTR(ary
, n
);
1596 ARY_INCREASE_LEN(ary
, -n
);
1603 make_room_for_unshift(VALUE ary
, const VALUE
*head
, VALUE
*sharedp
, int argc
, long capa
, long len
)
1605 if (head
- sharedp
< argc
) {
1606 long room
= capa
- len
- argc
;
1609 MEMMOVE((VALUE
*)sharedp
+ argc
+ room
, head
, VALUE
, len
);
1610 head
= sharedp
+ argc
+ room
;
1612 ARY_SET_PTR(ary
, head
- argc
);
1613 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
)));
1616 return ARY_SHARED_ROOT(ary
);
1620 ary_modify_for_unshift(VALUE ary
, int argc
)
1622 long len
= RARRAY_LEN(ary
);
1623 long new_len
= len
+ argc
;
1625 const VALUE
*head
, *sharedp
;
1628 capa
= ARY_CAPA(ary
);
1629 if (capa
- (capa
>> 6) <= new_len
) {
1630 ary_double_capa(ary
, new_len
);
1633 /* use shared array for big "queues" */
1634 if (new_len
> ARY_DEFAULT_SIZE
* 4 && !ARY_EMBED_P(ary
)) {
1637 /* make a room for unshifted items */
1638 capa
= ARY_CAPA(ary
);
1639 ary_make_shared(ary
);
1641 head
= sharedp
= RARRAY_CONST_PTR(ary
);
1642 return make_room_for_unshift(ary
, head
, (void *)sharedp
, argc
, capa
, len
);
1646 RARRAY_PTR_USE(ary
, ptr
, {
1647 MEMMOVE(ptr
+ argc
, ptr
, VALUE
, len
);
1656 ary_ensure_room_for_unshift(VALUE ary
, int argc
)
1658 long len
= RARRAY_LEN(ary
);
1659 long new_len
= len
+ argc
;
1661 if (len
> ARY_MAX_SIZE
- argc
) {
1662 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
1664 else if (! ARY_SHARED_P(ary
)) {
1665 return ary_modify_for_unshift(ary
, argc
);
1668 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
1669 long capa
= RARRAY_LEN(shared_root
);
1671 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
1672 return ary_modify_for_unshift(ary
, argc
);
1674 else if (new_len
> capa
) {
1675 return ary_modify_for_unshift(ary
, argc
);
1678 const VALUE
* head
= RARRAY_CONST_PTR(ary
);
1679 void *sharedp
= (void *)RARRAY_CONST_PTR(shared_root
);
1681 rb_ary_modify_check(ary
);
1682 return make_room_for_unshift(ary
, head
, sharedp
, argc
, capa
, len
);
1689 * unshift(*objects) -> self
1690 * prepend(*objects) -> self
1692 * Prepends the given +objects+ to +self+:
1694 * a = [:foo, 'bar', 2]
1695 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1697 * Related: Array#shift;
1698 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1702 rb_ary_unshift_m(int argc
, VALUE
*argv
, VALUE ary
)
1704 long len
= RARRAY_LEN(ary
);
1708 rb_ary_modify_check(ary
);
1712 target_ary
= ary_ensure_room_for_unshift(ary
, argc
);
1713 ary_memcpy0(ary
, 0, argc
, argv
, target_ary
);
1714 ARY_SET_LEN(ary
, len
+ argc
);
1719 rb_ary_unshift(VALUE ary
, VALUE item
)
1721 return rb_ary_unshift_m(1, &item
, ary
);
1724 /* faster version - use this if you don't need to treat negative offset */
1726 rb_ary_elt(VALUE ary
, long offset
)
1728 long len
= RARRAY_LEN(ary
);
1729 if (len
== 0) return Qnil
;
1730 if (offset
< 0 || len
<= offset
) {
1733 return RARRAY_AREF(ary
, offset
);
1737 rb_ary_entry(VALUE ary
, long offset
)
1739 return rb_ary_entry_internal(ary
, offset
);
1743 rb_ary_subseq_step(VALUE ary
, long beg
, long len
, long step
)
1746 long alen
= RARRAY_LEN(ary
);
1748 if (beg
> alen
) return Qnil
;
1749 if (beg
< 0 || len
< 0) return Qnil
;
1751 if (alen
< len
|| alen
< beg
+ len
) {
1755 if (len
== 0) return ary_new(klass
, 0);
1757 rb_raise(rb_eArgError
, "slice step cannot be zero");
1759 return ary_make_partial(ary
, klass
, beg
, len
);
1761 return ary_make_partial_step(ary
, klass
, beg
, len
, step
);
1765 rb_ary_subseq(VALUE ary
, long beg
, long len
)
1767 return rb_ary_subseq_step(ary
, beg
, len
, 1);
1770 static VALUE
rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
);
1774 * self[index] -> object or nil
1775 * self[start, length] -> object or nil
1776 * self[range] -> object or nil
1777 * self[aseq] -> object or nil
1778 * slice(index) -> object or nil
1779 * slice(start, length) -> object or nil
1780 * slice(range) -> object or nil
1781 * slice(aseq) -> object or nil
1783 * Returns elements from +self+; does not modify +self+.
1787 * a = [:foo, 'bar', 2]
1789 * # Single argument index: returns one element.
1790 * a[0] # => :foo # Zero-based index.
1791 * a[-1] # => 2 # Negative index counts backwards from end.
1793 * # Arguments start and length: returns an array.
1794 * a[1, 2] # => ["bar", 2]
1795 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1797 * # Single argument range: returns an array.
1798 * a[0..1] # => [:foo, "bar"]
1799 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1800 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1802 * When a single integer argument +index+ is given, returns the element at offset +index+:
1804 * a = [:foo, 'bar', 2]
1807 * a # => [:foo, "bar", 2]
1809 * If +index+ is negative, counts backwards from the end of +self+:
1811 * a = [:foo, 'bar', 2]
1815 * If +index+ is out of range, returns +nil+.
1817 * When two Integer arguments +start+ and +length+ are given,
1818 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1820 * a = [:foo, 'bar', 2]
1821 * a[0, 2] # => [:foo, "bar"]
1822 * a[1, 2] # => ["bar", 2]
1824 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1825 * returns all elements from offset +start+ to the end:
1827 * a = [:foo, 'bar', 2]
1828 * a[0, 4] # => [:foo, "bar", 2]
1829 * a[1, 3] # => ["bar", 2]
1832 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1833 * returns a new empty +Array+.
1835 * If +length+ is negative, returns +nil+.
1837 * When a single Range argument +range+ is given,
1838 * treats <tt>range.min</tt> as +start+ above
1839 * and <tt>range.size</tt> as +length+ above:
1841 * a = [:foo, 'bar', 2]
1842 * a[0..1] # => [:foo, "bar"]
1843 * a[1..2] # => ["bar", 2]
1845 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1847 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1849 * a = [:foo, 'bar', 2]
1850 * a[0..-1] # => [:foo, "bar", 2]
1851 * a[0..-2] # => [:foo, "bar"]
1852 * a[0..-3] # => [:foo]
1854 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1856 * a = [:foo, 'bar', 2]
1858 * a[-2..2] # => ["bar", 2]
1859 * a[-3..2] # => [:foo, "bar", 2]
1861 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1863 * a = [:foo, 'bar', 2]
1868 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1869 * returns an +Array+ of elements corresponding to the indexes produced by
1872 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1873 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1875 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1876 * is larger than array size, throws RangeError.
1878 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1879 * a[(1..11).step(2)]
1880 * # RangeError (((1..11).step(2)) out of range)
1882 * # RangeError (((7..).step(2)) out of range)
1884 * If given a single argument, and its type is not one of the listed, tries to
1885 * convert it to Integer, and raises if it is impossible:
1887 * a = [:foo, 'bar', 2]
1888 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1891 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1895 rb_ary_aref(int argc
, const VALUE
*argv
, VALUE ary
)
1897 rb_check_arity(argc
, 1, 2);
1899 return rb_ary_aref2(ary
, argv
[0], argv
[1]);
1901 return rb_ary_aref1(ary
, argv
[0]);
1905 rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
)
1907 long beg
= NUM2LONG(b
);
1908 long len
= NUM2LONG(e
);
1910 beg
+= RARRAY_LEN(ary
);
1912 return rb_ary_subseq(ary
, beg
, len
);
1916 rb_ary_aref1(VALUE ary
, VALUE arg
)
1918 long beg
, len
, step
;
1920 /* special case - speeding up */
1921 if (FIXNUM_P(arg
)) {
1922 return rb_ary_entry(ary
, FIX2LONG(arg
));
1924 /* check if idx is Range or ArithmeticSequence */
1925 switch (rb_arithmetic_sequence_beg_len_step(arg
, &beg
, &len
, &step
, RARRAY_LEN(ary
), 0)) {
1931 return rb_ary_subseq_step(ary
, beg
, len
, step
);
1934 return rb_ary_entry(ary
, NUM2LONG(arg
));
1939 * at(index) -> object or nil
1941 * Returns the element of +self+ specified by the given +index+
1942 * or +nil+ if there is no such element;
1943 * +index+ must be an
1944 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1946 * For non-negative +index+, returns the element of +self+ at offset +index+:
1948 * a = [:foo, 'bar', 2]
1953 * For negative +index+, counts backwards from the end of +self+:
1955 * a.at(-2) # => "bar"
1957 * Related: Array#[];
1958 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1962 rb_ary_at(VALUE ary
, VALUE pos
)
1964 return rb_ary_entry(ary
, NUM2LONG(pos
));
1969 rb_ary_first(int argc
, VALUE
*argv
, VALUE ary
)
1972 if (RARRAY_LEN(ary
) == 0) return Qnil
;
1973 return RARRAY_AREF(ary
, 0);
1976 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1982 ary_first(VALUE self
)
1984 return (RARRAY_LEN(self
) == 0) ? Qnil
: RARRAY_AREF(self
, 0);
1988 ary_last(VALUE self
)
1990 long len
= RARRAY_LEN(self
);
1991 return (len
== 0) ? Qnil
: RARRAY_AREF(self
, len
-1);
1995 rb_ary_last(int argc
, const VALUE
*argv
, VALUE ary
) // used by parse.y
1998 return ary_last(ary
);
2001 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
2007 * fetch(index) -> element
2008 * fetch(index, default_value) -> element or default_value
2009 * fetch(index) {|index| ... } -> element or block_return_value
2011 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2012 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2014 * With the single argument +index+ and no block,
2015 * returns the element at offset +index+:
2017 * a = [:foo, 'bar', 2]
2018 * a.fetch(1) # => "bar"
2019 * a.fetch(1.1) # => "bar"
2021 * If +index+ is negative, counts from the end of the array:
2023 * a = [:foo, 'bar', 2]
2024 * a.fetch(-1) # => 2
2025 * a.fetch(-2) # => "bar"
2027 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2028 * returns +default_value+ if +index+ is out-of-range:
2030 * a = [:foo, 'bar', 2]
2031 * a.fetch(1, nil) # => "bar"
2032 * a.fetch(3, :foo) # => :foo
2034 * With argument +index+ and a block,
2035 * returns the element at offset +index+ if index is in range
2036 * (and the block is not called); otherwise calls the block with index and returns its return value:
2038 * a = [:foo, 'bar', 2]
2039 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2040 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2042 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2046 rb_ary_fetch(int argc
, VALUE
*argv
, VALUE ary
)
2052 rb_scan_args(argc
, argv
, "11", &pos
, &ifnone
);
2053 block_given
= rb_block_given_p();
2054 if (block_given
&& argc
== 2) {
2055 rb_warn("block supersedes default value argument");
2057 idx
= NUM2LONG(pos
);
2060 idx
+= RARRAY_LEN(ary
);
2062 if (idx
< 0 || RARRAY_LEN(ary
) <= idx
) {
2063 if (block_given
) return rb_yield(pos
);
2065 rb_raise(rb_eIndexError
, "index %ld outside of array bounds: %ld...%ld",
2066 idx
- (idx
< 0 ? RARRAY_LEN(ary
) : 0), -RARRAY_LEN(ary
), RARRAY_LEN(ary
));
2070 return RARRAY_AREF(ary
, idx
);
2075 * find_index(object) -> integer or nil
2076 * find_index {|element| ... } -> integer or nil
2077 * find_index -> new_enumerator
2078 * index(object) -> integer or nil
2079 * index {|element| ... } -> integer or nil
2080 * index -> new_enumerator
2082 * Returns the zero-based integer index of a specified element, or +nil+.
2084 * With only argument +object+ given,
2085 * returns the index of the first element +element+
2086 * for which <tt>object == element</tt>:
2088 * a = [:foo, 'bar', 2, 'bar']
2089 * a.index('bar') # => 1
2091 * Returns +nil+ if no such element found.
2093 * With only a block given,
2094 * calls the block with each successive element;
2095 * returns the index of the first element for which the block returns a truthy value:
2097 * a = [:foo, 'bar', 2, 'bar']
2098 * a.index {|element| element == 'bar' } # => 1
2100 * Returns +nil+ if the block never returns a truthy value.
2102 * With neither an argument nor a block given, returns a new Enumerator.
2104 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2108 rb_ary_index(int argc
, VALUE
*argv
, VALUE ary
)
2114 RETURN_ENUMERATOR(ary
, 0, 0);
2115 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2116 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
2122 rb_check_arity(argc
, 0, 1);
2124 if (rb_block_given_p())
2125 rb_warn("given block not used");
2126 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2127 VALUE e
= RARRAY_AREF(ary
, i
);
2128 if (rb_equal(e
, val
)) {
2137 * rindex(object) -> integer or nil
2138 * rindex {|element| ... } -> integer or nil
2139 * rindex -> new_enumerator
2141 * Returns the index of the last element for which <tt>object == element</tt>.
2143 * With argument +object+ given, returns the index of the last such element found:
2145 * a = [:foo, 'bar', 2, 'bar']
2146 * a.rindex('bar') # => 3
2148 * Returns +nil+ if no such object found.
2150 * With a block given, calls the block with each successive element;
2151 * returns the index of the last element for which the block returns a truthy value:
2153 * a = [:foo, 'bar', 2, 'bar']
2154 * a.rindex {|element| element == 'bar' } # => 3
2156 * Returns +nil+ if the block never returns a truthy value.
2158 * When neither an argument nor a block is given, returns a new Enumerator.
2160 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2164 rb_ary_rindex(int argc
, VALUE
*argv
, VALUE ary
)
2167 long i
= RARRAY_LEN(ary
), len
;
2170 RETURN_ENUMERATOR(ary
, 0, 0);
2172 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
))))
2174 if (i
> (len
= RARRAY_LEN(ary
))) {
2180 rb_check_arity(argc
, 0, 1);
2182 if (rb_block_given_p())
2183 rb_warn("given block not used");
2185 VALUE e
= RARRAY_AREF(ary
, i
);
2186 if (rb_equal(e
, val
)) {
2189 if (i
> RARRAY_LEN(ary
)) {
2197 rb_ary_to_ary(VALUE obj
)
2199 VALUE tmp
= rb_check_array_type(obj
);
2201 if (!NIL_P(tmp
)) return tmp
;
2202 return rb_ary_new3(1, obj
);
2206 rb_ary_splice(VALUE ary
, long beg
, long len
, const VALUE
*rptr
, long rlen
)
2211 if (len
< 0) rb_raise(rb_eIndexError
, "negative length (%ld)", len
);
2212 olen
= RARRAY_LEN(ary
);
2216 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2220 if (olen
< len
|| olen
< beg
+ len
) {
2225 const VALUE
*optr
= RARRAY_CONST_PTR(ary
);
2226 rofs
= (rptr
>= optr
&& rptr
< optr
+ olen
) ? rptr
- optr
: -1;
2231 if (beg
> ARY_MAX_SIZE
- rlen
) {
2232 rb_raise(rb_eIndexError
, "index %ld too big", beg
);
2234 target_ary
= ary_ensure_room_for_push(ary
, rlen
-len
); /* len is 0 or negative */
2236 ary_mem_clear(ary
, olen
, beg
- olen
);
2238 if (rofs
!= -1) rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2239 ary_memcpy0(ary
, beg
, rlen
, rptr
, target_ary
);
2241 ARY_SET_LEN(ary
, len
);
2246 if (olen
- len
> ARY_MAX_SIZE
- rlen
) {
2247 rb_raise(rb_eIndexError
, "index %ld too big", olen
+ rlen
- len
);
2250 alen
= olen
+ rlen
- len
;
2251 if (alen
>= ARY_CAPA(ary
)) {
2252 ary_double_capa(ary
, alen
);
2256 RARRAY_PTR_USE(ary
, ptr
,
2257 MEMMOVE(ptr
+ beg
+ rlen
, ptr
+ beg
+ len
,
2258 VALUE
, olen
- (beg
+ len
)));
2259 ARY_SET_LEN(ary
, alen
);
2263 rb_gc_writebarrier_remember(ary
);
2266 /* In this case, we're copying from a region in this array, so
2267 * we don't need to fire the write barrier. */
2268 rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2271 /* do not use RARRAY_PTR() because it can causes GC.
2272 * ary can contain T_NONE object because it is not cleared.
2274 RARRAY_PTR_USE(ary
, ptr
,
2275 MEMMOVE(ptr
+ beg
, rptr
, VALUE
, rlen
));
2281 rb_ary_set_len(VALUE ary
, long len
)
2285 rb_ary_modify_check(ary
);
2286 if (ARY_SHARED_P(ary
)) {
2287 rb_raise(rb_eRuntimeError
, "can't set length of shared ");
2289 if (len
> (capa
= (long)ARY_CAPA(ary
))) {
2290 rb_bug("probable buffer overflow: %ld for %ld", len
, capa
);
2292 ARY_SET_LEN(ary
, len
);
2296 rb_ary_resize(VALUE ary
, long len
)
2301 olen
= RARRAY_LEN(ary
);
2302 if (len
== olen
) return ary
;
2303 if (len
> ARY_MAX_SIZE
) {
2304 rb_raise(rb_eIndexError
, "index %ld too big", len
);
2307 if (len
>= ARY_CAPA(ary
)) {
2308 ary_double_capa(ary
, len
);
2310 ary_mem_clear(ary
, olen
, len
- olen
);
2311 ARY_SET_LEN(ary
, len
);
2313 else if (ARY_EMBED_P(ary
)) {
2314 ARY_SET_EMBED_LEN(ary
, len
);
2316 else if (len
<= ary_embed_capa(ary
)) {
2317 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
2318 long ptr_capa
= ARY_HEAP_SIZE(ary
);
2319 bool is_malloc_ptr
= !ARY_SHARED_P(ary
);
2323 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
); /* WB: no new reference */
2324 ARY_SET_EMBED_LEN(ary
, len
);
2326 if (is_malloc_ptr
) ruby_sized_xfree((void *)ptr
, ptr_capa
);
2329 if (olen
> len
+ ARY_DEFAULT_SIZE
) {
2330 size_t new_capa
= ary_heap_realloc(ary
, len
);
2331 ARY_SET_CAPA(ary
, new_capa
);
2333 ARY_SET_HEAP_LEN(ary
, len
);
2340 ary_aset_by_rb_ary_store(VALUE ary
, long key
, VALUE val
)
2342 rb_ary_store(ary
, key
, val
);
2347 ary_aset_by_rb_ary_splice(VALUE ary
, long beg
, long len
, VALUE val
)
2349 VALUE rpl
= rb_ary_to_ary(val
);
2350 rb_ary_splice(ary
, beg
, len
, RARRAY_CONST_PTR(rpl
), RARRAY_LEN(rpl
));
2357 * self[index] = object -> object
2358 * self[start, length] = object -> object
2359 * self[range] = object -> object
2361 * Assigns elements in +self+, based on the given +object+; returns +object+.
2365 * a_orig = [:foo, 'bar', 2]
2367 * # With argument index.
2369 * a[0] = 'foo' # => "foo"
2370 * a # => ["foo", "bar", 2]
2372 * a[7] = 'foo' # => "foo"
2373 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2375 * # With arguments start and length.
2377 * a[0, 2] = 'foo' # => "foo"
2380 * a[6, 50] = 'foo' # => "foo"
2381 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2383 * # With argument range.
2385 * a[0..1] = 'foo' # => "foo"
2388 * a[6..50] = 'foo' # => "foo"
2389 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2391 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2393 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2395 * a = [:foo, 'bar', 2]
2396 * a[0] = 'foo' # => "foo"
2397 * a # => ["foo", "bar", 2]
2399 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2401 * a = [:foo, 'bar', 2]
2402 * a[7] = 'foo' # => "foo"
2403 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2405 * If +index+ is negative, counts backwards from the end of the array:
2407 * a = [:foo, 'bar', 2]
2408 * a[-1] = 'two' # => "two"
2409 * a # => [:foo, "bar", "two"]
2411 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2412 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2413 * and assigns +object+ at offset +start+:
2415 * a = [:foo, 'bar', 2]
2416 * a[0, 2] = 'foo' # => "foo"
2419 * If +start+ is negative, counts backwards from the end of the array:
2421 * a = [:foo, 'bar', 2]
2422 * a[-2, 2] = 'foo' # => "foo"
2423 * a # => [:foo, "foo"]
2425 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2426 * extends the array with +nil+, assigns +object+ at offset +start+,
2427 * and ignores +length+:
2429 * a = [:foo, 'bar', 2]
2430 * a[6, 50] = 'foo' # => "foo"
2431 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2433 * If +length+ is zero, shifts elements at and following offset +start+
2434 * and assigns +object+ at offset +start+:
2436 * a = [:foo, 'bar', 2]
2437 * a[1, 0] = 'foo' # => "foo"
2438 * a # => [:foo, "foo", "bar", 2]
2440 * If +length+ is too large for the existing array, does not extend the array:
2442 * a = [:foo, 'bar', 2]
2443 * a[1, 5] = 'foo' # => "foo"
2444 * a # => [:foo, "foo"]
2446 * When Range argument +range+ is given and +object+ is not an +Array+,
2447 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2448 * and assigns +object+ at offset +start+:
2450 * a = [:foo, 'bar', 2]
2451 * a[0..1] = 'foo' # => "foo"
2454 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2456 * a = [:foo, 'bar', 2]
2457 * a[-2..2] = 'foo' # => "foo"
2458 * a # => [:foo, "foo"]
2460 * If the array length is less than <tt>range.begin</tt>,
2461 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2462 * and ignores +length+:
2464 * a = [:foo, 'bar', 2]
2465 * a[6..50] = 'foo' # => "foo"
2466 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2468 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2469 * and assigns +object+ at offset +start+:
2471 * a = [:foo, 'bar', 2]
2472 * a[1..0] = 'foo' # => "foo"
2473 * a # => [:foo, "foo", "bar", 2]
2475 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2476 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2478 * a = [:foo, 'bar', 2]
2479 * a[1..-1] = 'foo' # => "foo"
2480 * a # => [:foo, "foo"]
2481 * a = [:foo, 'bar', 2]
2482 * a[1..-2] = 'foo' # => "foo"
2483 * a # => [:foo, "foo", 2]
2484 * a = [:foo, 'bar', 2]
2485 * a[1..-3] = 'foo' # => "foo"
2486 * a # => [:foo, "foo", "bar", 2]
2487 * a = [:foo, 'bar', 2]
2489 * If <tt>range.end</tt> is too large for the existing array,
2490 * replaces array elements, but does not extend the array with +nil+ values:
2492 * a = [:foo, 'bar', 2]
2493 * a[1..5] = 'foo' # => "foo"
2494 * a # => [:foo, "foo"]
2496 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2500 rb_ary_aset(int argc
, VALUE
*argv
, VALUE ary
)
2502 long offset
, beg
, len
;
2504 rb_check_arity(argc
, 2, 3);
2505 rb_ary_modify_check(ary
);
2507 beg
= NUM2LONG(argv
[0]);
2508 len
= NUM2LONG(argv
[1]);
2509 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[2]);
2511 if (FIXNUM_P(argv
[0])) {
2512 offset
= FIX2LONG(argv
[0]);
2513 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2515 if (rb_range_beg_len(argv
[0], &beg
, &len
, RARRAY_LEN(ary
), 1)) {
2516 /* check if idx is Range */
2517 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[1]);
2520 offset
= NUM2LONG(argv
[0]);
2521 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2526 * insert(index, *objects) -> self
2528 * Inserts the given +objects+ as elements of +self+;
2531 * When +index+ is non-negative, inserts +objects+
2532 * _before_ the element at offset +index+:
2534 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2535 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2537 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2539 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2540 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2542 * When +index+ is negative, inserts +objects+
2543 * _after_ the element at offset <tt>index + self.size</tt>:
2545 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2546 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2548 * With no +objects+ given, does nothing:
2550 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2551 * a.insert(1) # => ["a", "b", "c"]
2552 * a.insert(50) # => ["a", "b", "c"]
2553 * a.insert(-50) # => ["a", "b", "c"]
2555 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2557 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2561 rb_ary_insert(int argc
, VALUE
*argv
, VALUE ary
)
2565 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2566 rb_ary_modify_check(ary
);
2567 pos
= NUM2LONG(argv
[0]);
2568 if (argc
== 1) return ary
;
2570 pos
= RARRAY_LEN(ary
);
2573 long minpos
= -RARRAY_LEN(ary
) - 1;
2575 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2580 rb_ary_splice(ary
, pos
, 0, argv
+ 1, argc
- 1);
2585 rb_ary_length(VALUE ary
);
2588 ary_enum_length(VALUE ary
, VALUE args
, VALUE eobj
)
2590 return rb_ary_length(ary
);
2593 // Primitive to avoid a race condition in Array#each.
2594 // Return `true` and write `value` and `index` if the element exists.
2596 ary_fetch_next(VALUE self
, VALUE
*index
, VALUE
*value
)
2598 long i
= NUM2LONG(*index
);
2599 if (i
>= RARRAY_LEN(self
)) {
2602 *value
= RARRAY_AREF(self
, i
);
2603 *index
= LONG2NUM(i
+ 1);
2608 rb_ary_each(VALUE ary
)
2612 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2613 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2614 rb_yield(RARRAY_AREF(ary
, i
));
2621 * each_index {|index| ... } -> self
2622 * each_index -> new_enumerator
2624 * With a block given, iterates over the elements of +self+,
2625 * passing each <i>array index</i> to the block;
2628 * a = [:foo, 'bar', 2]
2629 * a.each_index {|index| puts "#{index} #{a[index]}" }
2637 * Allows the array to be modified during iteration:
2639 * a = [:foo, 'bar', 2]
2640 * a.each_index {|index| puts index; a.clear if index > 0 }
2648 * With no block given, returns a new Enumerator.
2650 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2654 rb_ary_each_index(VALUE ary
)
2657 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2659 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2660 rb_yield(LONG2NUM(i
));
2667 * reverse_each {|element| ... } -> self
2668 * reverse_each -> Enumerator
2670 * When a block given, iterates backwards over the elements of +self+,
2671 * passing, in reverse order, each element to the block;
2675 * [0, 1, 2].reverse_each {|element| a.push(element) }
2678 * Allows the array to be modified during iteration:
2680 * a = ['a', 'b', 'c']
2681 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2684 * When no block given, returns a new Enumerator.
2686 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2690 rb_ary_reverse_each(VALUE ary
)
2694 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2695 len
= RARRAY_LEN(ary
);
2698 rb_yield(RARRAY_AREF(ary
, len
));
2699 nlen
= RARRAY_LEN(ary
);
2712 * Returns the count of elements in +self+:
2714 * [0, 1, 2].length # => 3
2717 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2721 rb_ary_length(VALUE ary
)
2723 long len
= RARRAY_LEN(ary
);
2724 return LONG2NUM(len
);
2729 * array.empty? -> true or false
2731 * Returns +true+ if the count of elements in +self+ is zero,
2732 * +false+ otherwise.
2734 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2738 rb_ary_empty_p(VALUE ary
)
2740 return RBOOL(RARRAY_LEN(ary
) == 0);
2744 rb_ary_dup(VALUE ary
)
2746 long len
= RARRAY_LEN(ary
);
2747 VALUE dup
= rb_ary_new2(len
);
2748 ary_memcpy(dup
, 0, len
, RARRAY_CONST_PTR(ary
));
2749 ARY_SET_LEN(dup
, len
);
2757 rb_ary_resurrect(VALUE ary
)
2759 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
2762 extern VALUE rb_output_fs
;
2764 static void ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
);
2767 recursive_join(VALUE obj
, VALUE argp
, int recur
)
2769 VALUE
*arg
= (VALUE
*)argp
;
2772 VALUE result
= arg
[2];
2773 int *first
= (int *)arg
[3];
2776 rb_raise(rb_eArgError
, "recursive array join");
2779 ary_join_1(obj
, ary
, sep
, 0, result
, first
);
2785 ary_join_0(VALUE ary
, VALUE sep
, long max
, VALUE result
)
2790 if (max
> 0) rb_enc_copy(result
, RARRAY_AREF(ary
, 0));
2791 for (i
=0; i
<max
; i
++) {
2792 val
= RARRAY_AREF(ary
, i
);
2793 if (!RB_TYPE_P(val
, T_STRING
)) break;
2794 if (i
> 0 && !NIL_P(sep
))
2795 rb_str_buf_append(result
, sep
);
2796 rb_str_buf_append(result
, val
);
2802 ary_join_1_str(VALUE dst
, VALUE src
, int *first
)
2804 rb_str_buf_append(dst
, src
);
2806 rb_enc_copy(dst
, src
);
2812 ary_join_1_ary(VALUE obj
, VALUE ary
, VALUE sep
, VALUE result
, VALUE val
, int *first
)
2815 rb_raise(rb_eArgError
, "recursive array join");
2824 args
[3] = (VALUE
)first
;
2825 rb_exec_recursive(recursive_join
, obj
, (VALUE
)args
);
2830 ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
)
2834 for (; i
<RARRAY_LEN(ary
); i
++) {
2835 if (i
> 0 && !NIL_P(sep
))
2836 rb_str_buf_append(result
, sep
);
2838 val
= RARRAY_AREF(ary
, i
);
2839 if (RB_TYPE_P(val
, T_STRING
)) {
2840 ary_join_1_str(result
, val
, first
);
2842 else if (RB_TYPE_P(val
, T_ARRAY
)) {
2843 ary_join_1_ary(val
, ary
, sep
, result
, val
, first
);
2845 else if (!NIL_P(tmp
= rb_check_string_type(val
))) {
2846 ary_join_1_str(result
, tmp
, first
);
2848 else if (!NIL_P(tmp
= rb_check_array_type(val
))) {
2849 ary_join_1_ary(val
, ary
, sep
, result
, tmp
, first
);
2852 ary_join_1_str(result
, rb_obj_as_string(val
), first
);
2858 rb_ary_join(VALUE ary
, VALUE sep
)
2861 VALUE val
, tmp
, result
;
2863 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new(0, 0);
2867 len
+= RSTRING_LEN(sep
) * (RARRAY_LEN(ary
) - 1);
2869 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2870 val
= RARRAY_AREF(ary
, i
);
2871 tmp
= rb_check_string_type(val
);
2873 if (NIL_P(tmp
) || tmp
!= val
) {
2875 long n
= RARRAY_LEN(ary
);
2877 result
= rb_str_buf_new(len
+ (n
-i
)*10);
2878 rb_enc_associate(result
, rb_usascii_encoding());
2879 i
= ary_join_0(ary
, sep
, i
, result
);
2881 ary_join_1(ary
, ary
, sep
, i
, result
, &first
);
2885 len
+= RSTRING_LEN(tmp
);
2888 result
= rb_str_new(0, len
);
2889 rb_str_set_len(result
, 0);
2891 ary_join_0(ary
, sep
, RARRAY_LEN(ary
), result
);
2898 * array.join(separator = $,) -> new_string
2900 * Returns the new string formed by joining the converted elements of +self+;
2901 * for each element +element+:
2903 * - Converts recursively using <tt>element.join(separator)</tt>
2904 * if +element+ is a <tt>kind_of?(Array)</tt>.
2905 * - Otherwise, converts using <tt>element.to_s</tt>.
2907 * With no argument given, joins using the output field separator, <tt>$,</tt>:
2909 * a = [:foo, 'bar', 2]
2911 * a.join # => "foobar2"
2913 * With string argument +separator+ given, joins using that separator:
2915 * a = [:foo, 'bar', 2]
2916 * a.join("\n") # => "foo\nbar\n2"
2918 * Joins recursively for nested arrays:
2920 * a = [:foo, [:bar, [:baz, :bat]]]
2921 * a.join # => "foobarbazbat"
2923 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2926 rb_ary_join_m(int argc
, VALUE
*argv
, VALUE ary
)
2930 if (rb_check_arity(argc
, 0, 1) == 0 || NIL_P(sep
= argv
[0])) {
2933 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
2937 return rb_ary_join(ary
, sep
);
2941 inspect_ary(VALUE ary
, VALUE dummy
, int recur
)
2946 if (recur
) return rb_usascii_str_new_cstr("[...]");
2947 str
= rb_str_buf_new2("[");
2948 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2949 s
= rb_inspect(RARRAY_AREF(ary
, i
));
2950 if (i
> 0) rb_str_buf_cat2(str
, ", ");
2951 else rb_enc_copy(str
, s
);
2952 rb_str_buf_append(str
, s
);
2954 rb_str_buf_cat2(str
, "]");
2960 * inspect -> new_string
2961 * to_s -> new_string
2963 * Returns the new string formed by calling method <tt>#inspect</tt>
2964 * on each array element:
2966 * a = [:foo, 'bar', 2]
2967 * a.inspect # => "[:foo, \"bar\", 2]"
2969 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2973 rb_ary_inspect(VALUE ary
)
2975 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new2("[]");
2976 return rb_exec_recursive(inspect_ary
, ary
, 0);
2980 rb_ary_to_s(VALUE ary
)
2982 return rb_ary_inspect(ary
);
2987 * to_a -> self or new_array
2989 * When +self+ is an instance of +Array+, returns +self+.
2991 * Otherwise, returns a new array containing the elements of +self+:
2993 * class MyArray < Array; end
2994 * my_a = MyArray.new(['foo', 'bar', 'two'])
2996 * a # => ["foo", "bar", "two"]
2997 * a.class # => Array # Not MyArray.
2999 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3003 rb_ary_to_a(VALUE ary
)
3005 if (rb_obj_class(ary
) != rb_cArray
) {
3006 VALUE dup
= rb_ary_new2(RARRAY_LEN(ary
));
3007 rb_ary_replace(dup
, ary
);
3016 * to_h {|element| ... } -> new_hash
3018 * Returns a new hash formed from +self+.
3020 * With no block given, each element of +self+ must be a 2-element sub-array;
3021 * forms each sub-array into a key-value pair in the new hash:
3023 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3024 * a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3027 * With a block given, the block must return a 2-element array;
3028 * calls the block with each element of +self+;
3029 * forms each returned array into a key-value pair in the returned hash:
3031 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3032 * a.to_h {|element| [element, element.class] }
3033 * # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
3035 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3039 rb_ary_to_h(VALUE ary
)
3042 VALUE hash
= rb_hash_new_with_size(RARRAY_LEN(ary
));
3043 int block_given
= rb_block_given_p();
3045 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
3046 const VALUE e
= rb_ary_elt(ary
, i
);
3047 const VALUE elt
= block_given
? rb_yield_force_blockarg(e
) : e
;
3048 const VALUE key_value_pair
= rb_check_array_type(elt
);
3049 if (NIL_P(key_value_pair
)) {
3050 rb_raise(rb_eTypeError
, "wrong element type %"PRIsVALUE
" at %ld (expected array)",
3051 rb_obj_class(elt
), i
);
3053 if (RARRAY_LEN(key_value_pair
) != 2) {
3054 rb_raise(rb_eArgError
, "wrong array length at %ld (expected 2, was %ld)",
3055 i
, RARRAY_LEN(key_value_pair
));
3057 rb_hash_aset(hash
, RARRAY_AREF(key_value_pair
, 0), RARRAY_AREF(key_value_pair
, 1));
3064 * array.to_ary -> self
3070 rb_ary_to_ary_m(VALUE ary
)
3076 ary_reverse(VALUE
*p1
, VALUE
*p2
)
3086 rb_ary_reverse(VALUE ary
)
3089 long len
= RARRAY_LEN(ary
);
3093 RARRAY_PTR_USE(ary
, p1
, {
3094 p2
= p1
+ len
- 1; /* points last item */
3095 ary_reverse(p1
, p2
);
3096 }); /* WB: no new reference */
3105 * Reverses the order of the elements of +self+;
3109 * a.reverse! # => [2, 1, 0]
3112 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3116 rb_ary_reverse_bang(VALUE ary
)
3118 return rb_ary_reverse(ary
);
3123 * reverse -> new_array
3125 * Returns a new array containing the elements of +self+ in reverse order:
3127 * [0, 1, 2].reverse # => [2, 1, 0]
3129 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3133 rb_ary_reverse_m(VALUE ary
)
3135 long len
= RARRAY_LEN(ary
);
3136 VALUE dup
= rb_ary_new2(len
);
3139 const VALUE
*p1
= RARRAY_CONST_PTR(ary
);
3140 VALUE
*p2
= (VALUE
*)RARRAY_CONST_PTR(dup
) + len
- 1;
3141 do *p2
-- = *p1
++; while (--len
> 0);
3143 ARY_SET_LEN(dup
, RARRAY_LEN(ary
));
3148 rotate_count(long cnt
, long len
)
3150 return (cnt
< 0) ? (len
- (~cnt
% len
) - 1) : (cnt
% len
);
3154 ary_rotate_ptr(VALUE
*ptr
, long len
, long cnt
)
3158 memmove(ptr
, ptr
+ 1, sizeof(VALUE
)*(len
- 1));
3159 *(ptr
+ len
- 1) = tmp
;
3161 else if (cnt
== len
- 1) {
3162 VALUE tmp
= *(ptr
+ len
- 1);
3163 memmove(ptr
+ 1, ptr
, sizeof(VALUE
)*(len
- 1));
3168 if (cnt
< len
) ary_reverse(ptr
+ cnt
, ptr
+ len
);
3169 if (--cnt
> 0) ary_reverse(ptr
, ptr
+ cnt
);
3170 if (len
> 0) ary_reverse(ptr
, ptr
+ len
);
3175 rb_ary_rotate(VALUE ary
, long cnt
)
3180 long len
= RARRAY_LEN(ary
);
3181 if (len
> 1 && (cnt
= rotate_count(cnt
, len
)) > 0) {
3182 RARRAY_PTR_USE(ary
, ptr
, ary_rotate_ptr(ptr
, len
, cnt
));
3191 * rotate!(count = 1) -> self
3193 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3195 * With non-negative numeric +count+,
3196 * rotates +count+ elements from the beginning to the end:
3198 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3199 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3201 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3203 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3205 * If +count+ is zero, rotates no elements:
3207 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3209 * With a negative numeric +count+, rotates in the opposite direction,
3210 * from end to beginning:
3212 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3214 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3216 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3218 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3222 rb_ary_rotate_bang(int argc
, VALUE
*argv
, VALUE ary
)
3224 long n
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3225 rb_ary_rotate(ary
, n
);
3231 * rotate(count = 1) -> new_array
3233 * Returns a new array formed from +self+ with elements
3234 * rotated from one end to the other.
3236 * With non-negative numeric +count+,
3237 * rotates elements from the beginning to the end:
3239 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3240 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3242 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3244 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3246 * With a +count+ of zero, rotates no elements:
3248 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3250 * With negative numeric +count+, rotates in the opposite direction,
3251 * from the end to the beginning:
3253 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3255 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3257 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3259 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3263 rb_ary_rotate_m(int argc
, VALUE
*argv
, VALUE ary
)
3268 long cnt
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3270 len
= RARRAY_LEN(ary
);
3271 rotated
= rb_ary_new2(len
);
3273 cnt
= rotate_count(cnt
, len
);
3274 ptr
= RARRAY_CONST_PTR(ary
);
3276 ary_memcpy(rotated
, 0, len
, ptr
+ cnt
);
3277 ary_memcpy(rotated
, len
, cnt
, ptr
);
3279 ARY_SET_LEN(rotated
, RARRAY_LEN(ary
));
3283 struct ary_sort_data
{
3289 sort_reentered(VALUE ary
)
3291 if (RBASIC(ary
)->klass
) {
3292 rb_raise(rb_eRuntimeError
, "sort reentered");
3298 sort_returned(struct ary_sort_data
*data
)
3300 if (rb_obj_frozen_p(data
->receiver
)) {
3301 rb_raise(rb_eFrozenError
, "array frozen during sort");
3303 sort_reentered(data
->ary
);
3307 sort_1(const void *ap
, const void *bp
, void *dummy
)
3309 struct ary_sort_data
*data
= dummy
;
3310 VALUE retval
= sort_reentered(data
->ary
);
3311 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3317 retval
= rb_yield_values2(2, args
);
3318 n
= rb_cmpint(retval
, a
, b
);
3319 sort_returned(data
);
3324 sort_2(const void *ap
, const void *bp
, void *dummy
)
3326 struct ary_sort_data
*data
= dummy
;
3327 VALUE retval
= sort_reentered(data
->ary
);
3328 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3331 if (FIXNUM_P(a
) && FIXNUM_P(b
) && CMP_OPTIMIZABLE(INTEGER
)) {
3332 if ((long)a
> (long)b
) return 1;
3333 if ((long)a
< (long)b
) return -1;
3336 if (STRING_P(a
) && STRING_P(b
) && CMP_OPTIMIZABLE(STRING
)) {
3337 return rb_str_cmp(a
, b
);
3339 if (RB_FLOAT_TYPE_P(a
) && CMP_OPTIMIZABLE(FLOAT
)) {
3340 return rb_float_cmp(a
, b
);
3343 retval
= rb_funcallv(a
, id_cmp
, 1, &b
);
3344 n
= rb_cmpint(retval
, a
, b
);
3345 sort_returned(data
);
3353 * sort! {|a, b| ... } -> self
3355 * Like Array#sort, but returns +self+ with its elements sorted in place.
3357 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3361 rb_ary_sort_bang(VALUE ary
)
3364 RUBY_ASSERT(!ARY_SHARED_P(ary
));
3365 if (RARRAY_LEN(ary
) > 1) {
3366 VALUE tmp
= ary_make_substitution(ary
); /* only ary refers tmp */
3367 struct ary_sort_data data
;
3368 long len
= RARRAY_LEN(ary
);
3369 RBASIC_CLEAR_CLASS(tmp
);
3371 data
.receiver
= ary
;
3372 RARRAY_PTR_USE(tmp
, ptr
, {
3373 ruby_qsort(ptr
, len
, sizeof(VALUE
),
3374 rb_block_given_p()?sort_1
:sort_2
, &data
);
3375 }); /* WB: no new reference */
3377 if (ARY_EMBED_P(tmp
)) {
3378 if (ARY_SHARED_P(ary
)) { /* ary might be destructively operated in the given block */
3379 rb_ary_unshare(ary
);
3382 if (ARY_EMBED_LEN(tmp
) > ARY_CAPA(ary
)) {
3383 ary_resize_capa(ary
, ARY_EMBED_LEN(tmp
));
3385 ary_memcpy(ary
, 0, ARY_EMBED_LEN(tmp
), ARY_EMBED_PTR(tmp
));
3386 ARY_SET_LEN(ary
, ARY_EMBED_LEN(tmp
));
3389 if (!ARY_EMBED_P(ary
) && ARY_HEAP_PTR(ary
) == ARY_HEAP_PTR(tmp
)) {
3390 FL_UNSET_SHARED(ary
);
3391 ARY_SET_CAPA(ary
, RARRAY_LEN(tmp
));
3394 RUBY_ASSERT(!ARY_SHARED_P(tmp
));
3395 if (ARY_EMBED_P(ary
)) {
3396 FL_UNSET_EMBED(ary
);
3398 else if (ARY_SHARED_P(ary
)) {
3399 /* ary might be destructively operated in the given block */
3400 rb_ary_unshare(ary
);
3405 ARY_SET_PTR(ary
, ARY_HEAP_PTR(tmp
));
3406 ARY_SET_HEAP_LEN(ary
, len
);
3407 ARY_SET_CAPA(ary
, ARY_HEAP_LEN(tmp
));
3409 /* tmp was lost ownership for the ptr */
3410 FL_UNSET(tmp
, FL_FREEZE
);
3412 ARY_SET_EMBED_LEN(tmp
, 0);
3413 FL_SET(tmp
, FL_FREEZE
);
3415 /* tmp will be GC'ed. */
3416 RBASIC_SET_CLASS_RAW(tmp
, rb_cArray
); /* rb_cArray must be marked */
3425 * sort {|a, b| ... } -> new_array
3427 * Returns a new array containing the elements of +self+, sorted.
3429 * With no block given, compares elements using operator <tt>#<=></tt>
3432 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3434 * With a block given, calls the block with each combination of pairs of elements from +self+;
3435 * for each pair +a+ and +b+, the block should return a numeric:
3437 * - Negative when +b+ is to follow +a+.
3438 * - Zero when +a+ and +b+ are equivalent.
3439 * - Positive when +a+ is to follow +b+.
3444 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3445 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3447 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3448 * and may be unstable.
3450 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3454 rb_ary_sort(VALUE ary
)
3456 ary
= rb_ary_dup(ary
);
3457 rb_ary_sort_bang(ary
);
3461 static VALUE
rb_ary_bsearch_index(VALUE ary
);
3465 * bsearch {|element| ... } -> found_element or nil
3466 * bsearch -> new_enumerator
3468 * Returns the element from +self+ found by a binary search,
3469 * or +nil+ if the search found no suitable element.
3471 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3473 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3477 rb_ary_bsearch(VALUE ary
)
3479 VALUE index_result
= rb_ary_bsearch_index(ary
);
3481 if (FIXNUM_P(index_result
)) {
3482 return rb_ary_entry(ary
, FIX2LONG(index_result
));
3484 return index_result
;
3489 * bsearch_index {|element| ... } -> integer or nil
3490 * bsearch_index -> new_enumerator
3492 * Returns the integer index of the element from +self+ found by a binary search,
3493 * or +nil+ if the search found no suitable element.
3495 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3497 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3501 rb_ary_bsearch_index(VALUE ary
)
3503 long low
= 0, high
= RARRAY_LEN(ary
), mid
;
3504 int smaller
= 0, satisfied
= 0;
3507 RETURN_ENUMERATOR(ary
, 0, 0);
3508 while (low
< high
) {
3509 mid
= low
+ ((high
- low
) / 2);
3510 val
= rb_ary_entry(ary
, mid
);
3513 if (v
== INT2FIX(0)) return INT2FIX(mid
);
3514 smaller
= (SIGNED_VALUE
)v
< 0; /* Fixnum preserves its sign-bit */
3516 else if (v
== Qtrue
) {
3520 else if (!RTEST(v
)) {
3523 else if (rb_obj_is_kind_of(v
, rb_cNumeric
)) {
3524 const VALUE zero
= INT2FIX(0);
3525 switch (rb_cmpint(rb_funcallv(v
, id_cmp
, 1, &zero
), v
, zero
)) {
3526 case 0: return INT2FIX(mid
);
3527 case 1: smaller
= 0; break;
3528 case -1: smaller
= 1;
3532 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
3533 " (must be numeric, true, false or nil)",
3543 if (!satisfied
) return Qnil
;
3544 return INT2FIX(low
);
3549 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, dummy
))
3556 * sort_by! {|element| ... } -> self
3557 * sort_by! -> new_enumerator
3559 * With a block given, sorts the elements of +self+ in place;
3562 * Calls the block with each successive element;
3563 * sorts elements based on the values returned from the block:
3565 * a = ['aaaa', 'bbb', 'cc', 'd']
3566 * a.sort_by! {|element| element.size }
3567 * a # => ["d", "cc", "bbb", "aaaa"]
3569 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3571 * With no block given, returns a new Enumerator.
3573 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3577 rb_ary_sort_by_bang(VALUE ary
)
3581 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3583 sorted
= rb_block_call(ary
, rb_intern("sort_by"), 0, 0, sort_by_i
, 0);
3584 rb_ary_replace(ary
, sorted
);
3591 * collect {|element| ... } -> new_array
3592 * collect -> new_enumerator
3593 * map {|element| ... } -> new_array
3594 * map -> new_enumerator
3596 * With a block given, calls the block with each element of +self+;
3597 * returns a new array whose elements are the return values from the block:
3599 * a = [:foo, 'bar', 2]
3600 * a1 = a.map {|element| element.class }
3601 * a1 # => [Symbol, String, Integer]
3603 * With no block given, returns a new Enumerator.
3605 * Related: #collect!;
3606 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3610 rb_ary_collect(VALUE ary
)
3615 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3616 collect
= rb_ary_new2(RARRAY_LEN(ary
));
3617 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3618 rb_ary_push(collect
, rb_yield(RARRAY_AREF(ary
, i
)));
3626 * collect! {|element| ... } -> new_array
3627 * collect! -> new_enumerator
3628 * map! {|element| ... } -> new_array
3629 * map! -> new_enumerator
3631 * With a block given, calls the block with each element of +self+
3632 * and replaces the element with the block's return value;
3635 * a = [:foo, 'bar', 2]
3636 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3638 * With no block given, returns a new Enumerator.
3640 * Related: #collect;
3641 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3645 rb_ary_collect_bang(VALUE ary
)
3649 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3651 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3652 rb_ary_store(ary
, i
, rb_yield(RARRAY_AREF(ary
, i
)));
3658 rb_get_values_at(VALUE obj
, long olen
, int argc
, const VALUE
*argv
, VALUE (*func
) (VALUE
, long))
3660 VALUE result
= rb_ary_new2(argc
);
3661 long beg
, len
, i
, j
;
3663 for (i
=0; i
<argc
; i
++) {
3664 if (FIXNUM_P(argv
[i
])) {
3665 rb_ary_push(result
, (*func
)(obj
, FIX2LONG(argv
[i
])));
3668 /* check if idx is Range */
3669 if (rb_range_beg_len(argv
[i
], &beg
, &len
, olen
, 1)) {
3670 long end
= olen
< beg
+len
? olen
: beg
+len
;
3671 for (j
= beg
; j
< end
; j
++) {
3672 rb_ary_push(result
, (*func
)(obj
, j
));
3675 rb_ary_resize(result
, RARRAY_LEN(result
) + (beg
+ len
) - j
);
3678 rb_ary_push(result
, (*func
)(obj
, NUM2LONG(argv
[i
])));
3684 append_values_at_single(VALUE result
, VALUE ary
, long olen
, VALUE idx
)
3687 if (FIXNUM_P(idx
)) {
3688 beg
= FIX2LONG(idx
);
3690 /* check if idx is Range */
3691 else if (rb_range_beg_len(idx
, &beg
, &len
, olen
, 1)) {
3693 const VALUE
*const src
= RARRAY_CONST_PTR(ary
);
3694 const long end
= beg
+ len
;
3695 const long prevlen
= RARRAY_LEN(result
);
3697 rb_ary_cat(result
, src
+ beg
, end
> olen
? olen
-beg
: len
);
3700 rb_ary_store(result
, prevlen
+ len
- 1, Qnil
);
3706 beg
= NUM2LONG(idx
);
3708 return rb_ary_push(result
, rb_ary_entry(ary
, beg
));
3713 * array.values_at(*indexes) -> new_array
3715 * Returns a new +Array+ whose elements are the elements
3716 * of +self+ at the given Integer or Range +indexes+.
3718 * For each positive +index+, returns the element at offset +index+:
3720 * a = [:foo, 'bar', 2]
3721 * a.values_at(0, 2) # => [:foo, 2]
3722 * a.values_at(0..1) # => [:foo, "bar"]
3724 * The given +indexes+ may be in any order, and may repeat:
3726 * a = [:foo, 'bar', 2]
3727 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3728 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3730 * Assigns +nil+ for an +index+ that is too large:
3732 * a = [:foo, 'bar', 2]
3733 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3735 * Returns a new empty +Array+ if no arguments given.
3737 * For each negative +index+, counts backward from the end of the array:
3739 * a = [:foo, 'bar', 2]
3740 * a.values_at(-1, -3) # => [2, :foo]
3742 * Assigns +nil+ for an +index+ that is too small:
3744 * a = [:foo, 'bar', 2]
3745 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3747 * The given +indexes+ may have a mixture of signs:
3749 * a = [:foo, 'bar', 2]
3750 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3755 rb_ary_values_at(int argc
, VALUE
*argv
, VALUE ary
)
3757 long i
, olen
= RARRAY_LEN(ary
);
3758 VALUE result
= rb_ary_new_capa(argc
);
3759 for (i
= 0; i
< argc
; ++i
) {
3760 append_values_at_single(result
, ary
, olen
, argv
[i
]);
3769 * select {|element| ... } -> new_array
3770 * select -> new_enumerator
3771 * filter {|element| ... } -> new_array
3772 * filter -> new_enumerator
3774 * With a block given, calls the block with each element of +self+;
3775 * returns a new array containing those elements of +self+
3776 * for which the block returns a truthy value:
3778 * a = [:foo, 'bar', 2, :bam]
3779 * a.select {|element| element.to_s.start_with?('b') }
3780 * # => ["bar", :bam]
3782 * With no block given, returns a new Enumerator.
3784 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3788 rb_ary_select(VALUE ary
)
3793 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3794 result
= rb_ary_new2(RARRAY_LEN(ary
));
3795 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3796 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
3797 rb_ary_push(result
, rb_ary_elt(ary
, i
));
3803 struct select_bang_arg
{
3809 select_bang_i(VALUE a
)
3811 volatile struct select_bang_arg
*arg
= (void *)a
;
3812 VALUE ary
= arg
->ary
;
3815 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
3816 VALUE v
= RARRAY_AREF(ary
, i1
);
3817 if (!RTEST(rb_yield(v
))) continue;
3819 rb_ary_store(ary
, i2
, v
);
3823 return (i1
== i2
) ? Qnil
: ary
;
3827 select_bang_ensure(VALUE a
)
3829 volatile struct select_bang_arg
*arg
= (void *)a
;
3830 VALUE ary
= arg
->ary
;
3831 long len
= RARRAY_LEN(ary
);
3832 long i1
= arg
->len
[0], i2
= arg
->len
[1];
3834 if (i2
< len
&& i2
< i1
) {
3839 RARRAY_PTR_USE(ary
, ptr
, {
3840 MEMMOVE(ptr
+ i2
, ptr
+ i1
, VALUE
, tail
);
3843 ARY_SET_LEN(ary
, i2
+ tail
);
3850 * select! {|element| ... } -> self or nil
3851 * select! -> new_enumerator
3852 * filter! {|element| ... } -> self or nil
3853 * filter! -> new_enumerator
3855 * With a block given, calls the block with each element of +self+;
3856 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3858 * Returns +self+ if any elements were removed:
3860 * a = [:foo, 'bar', 2, :bam]
3861 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3863 * Returns +nil+ if no elements were removed.
3865 * With no block given, returns a new Enumerator.
3867 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3871 rb_ary_select_bang(VALUE ary
)
3873 struct select_bang_arg args
;
3875 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3879 args
.len
[0] = args
.len
[1] = 0;
3880 return rb_ensure(select_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
3885 * keep_if {|element| ... } -> self
3886 * keep_if -> new_enumerator
3888 * With a block given, calls the block with each element of +self+;
3889 * removes the element from +self+ if the block does not return a truthy value:
3891 * a = [:foo, 'bar', 2, :bam]
3892 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3894 * With no block given, returns a new Enumerator.
3896 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3900 rb_ary_keep_if(VALUE ary
)
3902 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3903 rb_ary_select_bang(ary
);
3908 ary_resize_smaller(VALUE ary
, long len
)
3911 if (RARRAY_LEN(ary
) > len
) {
3912 ARY_SET_LEN(ary
, len
);
3913 if (len
* 2 < ARY_CAPA(ary
) &&
3914 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
) {
3915 ary_resize_capa(ary
, len
* 2);
3922 * delete(object) -> last_removed_object
3923 * delete(object) {|element| ... } -> last_removed_object or block_return
3925 * Removes zero or more elements from +self+.
3927 * With no block given,
3928 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
3929 * returns the last removed element:
3931 * a = [0, 1, 2, 2.0]
3932 * a.delete(2) # => 2.0
3935 * Returns +nil+ if no elements removed:
3937 * a.delete(2) # => nil
3939 * With a block given,
3940 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
3942 * If any such elements are found, ignores the block
3943 * and returns the last removed element:
3945 * a = [0, 1, 2, 2.0]
3946 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
3949 * If no such element is found, returns the block's return value:
3951 * a.delete(2) {|element| "Element #{element} not found." }
3952 * # => "Element 2 not found."
3954 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3958 rb_ary_delete(VALUE ary
, VALUE item
)
3963 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
3964 VALUE e
= RARRAY_AREF(ary
, i1
);
3966 if (rb_equal(e
, item
)) {
3971 rb_ary_store(ary
, i2
, e
);
3975 if (RARRAY_LEN(ary
) == i2
) {
3976 if (rb_block_given_p()) {
3977 return rb_yield(item
);
3982 ary_resize_smaller(ary
, i2
);
3989 rb_ary_delete_same(VALUE ary
, VALUE item
)
3993 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
3994 VALUE e
= RARRAY_AREF(ary
, i1
);
4000 rb_ary_store(ary
, i2
, e
);
4004 if (RARRAY_LEN(ary
) == i2
) {
4008 ary_resize_smaller(ary
, i2
);
4012 rb_ary_delete_at(VALUE ary
, long pos
)
4014 long len
= RARRAY_LEN(ary
);
4017 if (pos
>= len
) return Qnil
;
4020 if (pos
< 0) return Qnil
;
4024 del
= RARRAY_AREF(ary
, pos
);
4025 RARRAY_PTR_USE(ary
, ptr
, {
4026 MEMMOVE(ptr
+pos
, ptr
+pos
+1, VALUE
, len
-pos
-1);
4028 ARY_INCREASE_LEN(ary
, -1);
4035 * delete_at(index) -> removed_object or nil
4037 * Removes the element of +self+ at the given +index+, which must be an
4038 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4040 * When +index+ is non-negative, deletes the element at offset +index+:
4042 * a = [:foo, 'bar', 2]
4043 * a.delete_at(1) # => "bar"
4046 * When +index+ is negative, counts backward from the end of the array:
4048 * a = [:foo, 'bar', 2]
4049 * a.delete_at(-2) # => "bar"
4052 * When +index+ is out of range, returns +nil+.
4054 * a = [:foo, 'bar', 2]
4055 * a.delete_at(3) # => nil
4056 * a.delete_at(-4) # => nil
4058 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4062 rb_ary_delete_at_m(VALUE ary
, VALUE pos
)
4064 return rb_ary_delete_at(ary
, NUM2LONG(pos
));
4068 ary_slice_bang_by_rb_ary_splice(VALUE ary
, long pos
, long len
)
4070 const long orig_len
= RARRAY_LEN(ary
);
4075 else if (pos
< -orig_len
) {
4081 else if (orig_len
< pos
) {
4084 if (orig_len
< pos
+ len
) {
4085 len
= orig_len
- pos
;
4088 return rb_ary_new2(0);
4091 VALUE arg2
= rb_ary_new4(len
, RARRAY_CONST_PTR(ary
)+pos
);
4092 rb_ary_splice(ary
, pos
, len
, 0, 0);
4099 * slice!(index) -> object or nil
4100 * slice!(start, length) -> new_array or nil
4101 * slice!(range) -> new_array or nil
4103 * Removes and returns elements from +self+.
4105 * With numeric argument +index+ given,
4106 * removes and returns the element at offset +index+:
4108 * a = ['a', 'b', 'c', 'd']
4109 * a.slice!(2) # => "c"
4110 * a # => ["a", "b", "d"]
4111 * a.slice!(2.1) # => "d"
4114 * If +index+ is negative, counts backwards from the end of +self+:
4116 * a = ['a', 'b', 'c', 'd']
4117 * a.slice!(-2) # => "c"
4118 * a # => ["a", "b", "d"]
4120 * If +index+ is out of range, returns +nil+.
4122 * With numeric arguments +start+ and +length+ given,
4123 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4124 * returns the removed objects in a new array:
4126 * a = ['a', 'b', 'c', 'd']
4127 * a.slice!(1, 2) # => ["b", "c"]
4129 * a.slice!(0.1, 1.1) # => ["a"]
4132 * If +start+ is negative, counts backwards from the end of +self+:
4134 * a = ['a', 'b', 'c', 'd']
4135 * a.slice!(-2, 1) # => ["c"]
4136 * a # => ["a", "b", "d"]
4138 * If +start+ is out-of-range, returns +nil+:
4140 * a = ['a', 'b', 'c', 'd']
4141 * a.slice!(5, 1) # => nil
4142 * a.slice!(-5, 1) # => nil
4144 * If <tt>start + length</tt> exceeds the array size,
4145 * removes and returns all elements from offset +start+ to the end:
4147 * a = ['a', 'b', 'c', 'd']
4148 * a.slice!(2, 50) # => ["c", "d"]
4151 * If <tt>start == a.size</tt> and +length+ is non-negative,
4152 * returns a new empty array.
4154 * If +length+ is negative, returns +nil+.
4156 * With Range argument +range+ given,
4157 * treats <tt>range.min</tt> as +start+ (as above)
4158 * and <tt>range.size</tt> as +length+ (as above):
4160 * a = ['a', 'b', 'c', 'd']
4161 * a.slice!(1..2) # => ["b", "c"]
4164 * If <tt>range.start == a.size</tt>, returns a new empty array:
4166 * a = ['a', 'b', 'c', 'd']
4167 * a.slice!(4..5) # => []
4169 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4171 * a = ['a', 'b', 'c', 'd']
4172 a.slice!(5..6) # => nil
4174 * If <tt>range.start</tt> is negative,
4175 * calculates the start index by counting backwards from the end of +self+:
4177 * a = ['a', 'b', 'c', 'd']
4178 * a.slice!(-2..2) # => ["c"]
4180 * If <tt>range.end</tt> is negative,
4181 * calculates the end index by counting backwards from the end of +self+:
4183 * a = ['a', 'b', 'c', 'd']
4184 * a.slice!(0..-2) # => ["a", "b", "c"]
4186 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4190 rb_ary_slice_bang(int argc
, VALUE
*argv
, VALUE ary
)
4195 rb_ary_modify_check(ary
);
4196 rb_check_arity(argc
, 1, 2);
4200 pos
= NUM2LONG(argv
[0]);
4201 len
= NUM2LONG(argv
[1]);
4202 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4205 if (!FIXNUM_P(arg1
)) {
4206 switch (rb_range_beg_len(arg1
, &pos
, &len
, RARRAY_LEN(ary
), 0)) {
4209 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4219 return rb_ary_delete_at(ary
, NUM2LONG(arg1
));
4223 ary_reject(VALUE orig
, VALUE result
)
4227 for (i
= 0; i
< RARRAY_LEN(orig
); i
++) {
4228 VALUE v
= RARRAY_AREF(orig
, i
);
4230 if (!RTEST(rb_yield(v
))) {
4231 rb_ary_push(result
, v
);
4238 reject_bang_i(VALUE a
)
4240 volatile struct select_bang_arg
*arg
= (void *)a
;
4241 VALUE ary
= arg
->ary
;
4244 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
4245 VALUE v
= RARRAY_AREF(ary
, i1
);
4246 if (RTEST(rb_yield(v
))) continue;
4248 rb_ary_store(ary
, i2
, v
);
4252 return (i1
== i2
) ? Qnil
: ary
;
4256 ary_reject_bang(VALUE ary
)
4258 struct select_bang_arg args
;
4259 rb_ary_modify_check(ary
);
4261 args
.len
[0] = args
.len
[1] = 0;
4262 return rb_ensure(reject_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
4267 * reject! {|element| ... } -> self or nil
4268 * reject! -> new_enumerator
4270 * With a block given, calls the block with each element of +self+;
4271 * removes each element for which the block returns a truthy value.
4273 * Returns +self+ if any elements removed:
4275 * a = [:foo, 'bar', 2, 'bat']
4276 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4278 * Returns +nil+ if no elements removed.
4280 * With no block given, returns a new Enumerator.
4282 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4286 rb_ary_reject_bang(VALUE ary
)
4288 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4290 return ary_reject_bang(ary
);
4295 * reject {|element| ... } -> new_array
4296 * reject -> new_enumerator
4298 * With a block given, returns a new array whose elements are all those from +self+
4299 * for which the block returns +false+ or +nil+:
4301 * a = [:foo, 'bar', 2, 'bat']
4302 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4305 * With no block given, returns a new Enumerator.
4307 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4311 rb_ary_reject(VALUE ary
)
4315 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4316 rejected_ary
= rb_ary_new();
4317 ary_reject(ary
, rejected_ary
);
4318 return rejected_ary
;
4323 * delete_if {|element| ... } -> self
4324 * delete_if -> new_numerator
4326 * With a block given, calls the block with each element of +self+;
4327 * removes the element if the block returns a truthy value;
4330 * a = [:foo, 'bar', 2, 'bat']
4331 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4333 * With no block given, returns a new Enumerator.
4335 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4339 rb_ary_delete_if(VALUE ary
)
4342 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4343 ary_reject_bang(ary
);
4348 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val
, cbarg
))
4350 VALUE
*args
= (VALUE
*)cbarg
;
4351 if (argc
> 1) val
= rb_ary_new4(argc
, argv
);
4352 rb_ary_push(args
[0], val
);
4353 if (--args
[1] == 0) rb_iter_break();
4358 take_items(VALUE obj
, long n
)
4360 VALUE result
= rb_check_array_type(obj
);
4363 if (n
== 0) return result
;
4364 if (!NIL_P(result
)) return rb_ary_subseq(result
, 0, n
);
4365 result
= rb_ary_new2(n
);
4366 args
[0] = result
; args
[1] = (VALUE
)n
;
4367 if (UNDEF_P(rb_check_block_call(obj
, idEach
, 0, 0, take_i
, (VALUE
)args
)))
4368 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
" (must respond to :each)",
4376 * array.zip(*other_arrays) -> new_array
4377 * array.zip(*other_arrays) {|other_array| ... } -> nil
4379 * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
4380 * whose elements are Arrays.
4382 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4385 * - The _nth_ element of +self+.
4386 * - The _nth_ element of each of the +other_arrays+.
4388 * If all +other_arrays+ and +self+ are the same size:
4390 * a = [:a0, :a1, :a2, :a3]
4391 * b = [:b0, :b1, :b2, :b3]
4392 * c = [:c0, :c1, :c2, :c3]
4394 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4396 * If any array in +other_arrays+ is smaller than +self+,
4397 * fills to <tt>self.size</tt> with +nil+:
4399 * a = [:a0, :a1, :a2, :a3]
4400 * b = [:b0, :b1, :b2]
4403 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4405 * If any array in +other_arrays+ is larger than +self+,
4406 * its trailing elements are ignored:
4408 * a = [:a0, :a1, :a2, :a3]
4409 * b = [:b0, :b1, :b2, :b3, :b4]
4410 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4412 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4414 * If an argument is not an array, it extracts the values by calling #each:
4416 * a = [:a0, :a1, :a2, :a2]
4419 * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
4421 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
4423 * a = [:a0, :a1, :a2, :a3]
4424 * b = [:b0, :b1, :b2, :b3]
4425 * c = [:c0, :c1, :c2, :c3]
4426 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4438 rb_ary_zip(int argc
, VALUE
*argv
, VALUE ary
)
4441 long len
= RARRAY_LEN(ary
);
4442 VALUE result
= Qnil
;
4444 for (i
=0; i
<argc
; i
++) {
4445 argv
[i
] = take_items(argv
[i
], len
);
4448 if (rb_block_given_p()) {
4449 int arity
= rb_block_arity();
4454 tmp
= ALLOCV_N(VALUE
, work
, argc
+1);
4456 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4457 tmp
[0] = RARRAY_AREF(ary
, i
);
4458 for (j
=0; j
<argc
; j
++) {
4459 tmp
[j
+1] = rb_ary_elt(argv
[j
], i
);
4461 rb_yield_values2(argc
+1, tmp
);
4464 if (work
) ALLOCV_END(work
);
4467 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4468 VALUE tmp
= rb_ary_new2(argc
+1);
4470 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4471 for (j
=0; j
<argc
; j
++) {
4472 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4479 result
= rb_ary_new_capa(len
);
4481 for (i
=0; i
<len
; i
++) {
4482 VALUE tmp
= rb_ary_new_capa(argc
+1);
4484 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4485 for (j
=0; j
<argc
; j
++) {
4486 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4488 rb_ary_push(result
, tmp
);
4497 * transpose -> new_array
4499 * Returns a new array that is +self+
4500 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4502 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4503 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4505 * The elements of +self+ must all be the same size.
4507 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4511 rb_ary_transpose(VALUE ary
)
4513 long elen
= -1, alen
, i
, j
;
4514 VALUE tmp
, result
= 0;
4516 alen
= RARRAY_LEN(ary
);
4517 if (alen
== 0) return rb_ary_dup(ary
);
4518 for (i
=0; i
<alen
; i
++) {
4519 tmp
= to_ary(rb_ary_elt(ary
, i
));
4520 if (elen
< 0) { /* first element */
4521 elen
= RARRAY_LEN(tmp
);
4522 result
= rb_ary_new2(elen
);
4523 for (j
=0; j
<elen
; j
++) {
4524 rb_ary_store(result
, j
, rb_ary_new2(alen
));
4527 else if (elen
!= RARRAY_LEN(tmp
)) {
4528 rb_raise(rb_eIndexError
, "element size differs (%ld should be %ld)",
4529 RARRAY_LEN(tmp
), elen
);
4531 for (j
=0; j
<elen
; j
++) {
4532 rb_ary_store(rb_ary_elt(result
, j
), i
, rb_ary_elt(tmp
, j
));
4540 * initialize_copy(other_array) -> self
4541 * replace(other_array) -> self
4543 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4544 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4547 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4548 * a.replace(['d', 'e']) # => ["d", "e"]
4550 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4554 rb_ary_replace(VALUE copy
, VALUE orig
)
4556 rb_ary_modify_check(copy
);
4557 orig
= to_ary(orig
);
4558 if (copy
== orig
) return copy
;
4562 /* orig has enough space to embed the contents of orig. */
4563 if (RARRAY_LEN(orig
) <= ary_embed_capa(copy
)) {
4564 RUBY_ASSERT(ARY_EMBED_P(copy
));
4565 ary_memcpy(copy
, 0, RARRAY_LEN(orig
), RARRAY_CONST_PTR(orig
));
4566 ARY_SET_EMBED_LEN(copy
, RARRAY_LEN(orig
));
4568 /* orig is embedded but copy does not have enough space to embed the
4569 * contents of orig. */
4570 else if (ARY_EMBED_P(orig
)) {
4571 long len
= ARY_EMBED_LEN(orig
);
4572 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
4574 FL_UNSET_EMBED(copy
);
4575 ARY_SET_PTR(copy
, ptr
);
4576 ARY_SET_LEN(copy
, len
);
4577 ARY_SET_CAPA(copy
, len
);
4579 // No allocation and exception expected that could leave `copy` in a
4580 // bad state from the edits above.
4581 ary_memcpy(copy
, 0, len
, RARRAY_CONST_PTR(orig
));
4583 /* Otherwise, orig is on heap and copy does not have enough space to embed
4584 * the contents of orig. */
4586 VALUE shared_root
= ary_make_shared(orig
);
4587 FL_UNSET_EMBED(copy
);
4588 ARY_SET_PTR(copy
, ARY_HEAP_PTR(orig
));
4589 ARY_SET_LEN(copy
, ARY_HEAP_LEN(orig
));
4590 rb_ary_set_shared(copy
, shared_root
);
4600 * Removes all elements from +self+; returns +self+:
4602 * a = [:foo, 'bar', 2]
4605 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4609 rb_ary_clear(VALUE ary
)
4611 rb_ary_modify_check(ary
);
4612 if (ARY_SHARED_P(ary
)) {
4613 rb_ary_unshare(ary
);
4615 ARY_SET_EMBED_LEN(ary
, 0);
4618 ARY_SET_LEN(ary
, 0);
4619 if (ARY_DEFAULT_SIZE
* 2 < ARY_CAPA(ary
)) {
4620 ary_resize_capa(ary
, ARY_DEFAULT_SIZE
* 2);
4629 * fill(object, start = nil, count = nil) -> new_array
4630 * fill(object, range) -> new_array
4631 * fill(start = nil, count = nil) {|element| ... } -> new_array
4632 * fill(range) {|element| ... } -> new_array
4634 * Replaces selected elements in +self+;
4635 * may add elements to +self+;
4636 * always returns +self+ (never a new array).
4640 * # Non-negative start.
4641 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4642 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4644 * # Extends with specified values if necessary.
4645 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4646 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4648 * # Fills with nils if necessary.
4649 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4650 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4652 * # For negative start, counts backwards from the end.
4653 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4654 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4657 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4658 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4660 * When arguments +start+ and +count+ are given,
4661 * they select the elements of +self+ to be replaced;
4663 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
4666 * - +start+ specifies the zero-based offset of the first element to be replaced;
4668 * - +count+ is the number of consecutive elements to be replaced;
4669 * +nil+ means "all the rest."
4671 * With argument +object+ given,
4672 * that one object is used for all replacements:
4674 * o = Object.new # => #<Object:0x0000014e7bff7600>
4675 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4677 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
4679 * With a block given, the block is called once for each element to be replaced;
4680 * the value passed to the block is the _index_ of the element to be replaced
4681 * (not the element itself);
4682 * the block's return value replaces the element:
4684 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4685 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
4687 * For arguments +start+ and +count+:
4689 * - If +start+ is non-negative,
4690 * replaces +count+ elements beginning at offset +start+:
4692 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
4693 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4694 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
4696 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4697 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4698 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
4700 * Extends +self+ if necessary:
4702 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4703 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
4705 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4706 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
4708 * Fills with +nil+ if necessary:
4710 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
4711 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4713 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
4714 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4716 * Does nothing if +count+ is non-positive:
4718 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
4719 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
4720 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
4722 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4723 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4724 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4726 * - If +start+ is negative, counts backwards from the end of +self+:
4728 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
4729 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4731 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
4732 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4734 * Extends +self+ if necessary:
4736 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
4737 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
4739 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
4740 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
4742 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
4744 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
4745 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
4747 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4748 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4750 * Does nothing if +count+ is non-positive:
4752 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
4753 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
4755 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4756 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4758 * When argument +range+ is given,
4759 * it must be a Range object whose members are numeric;
4760 * its +begin+ and +end+ values determine the elements of +self+
4763 * - If both +begin+ and +end+ are positive, they specify the first and last elements
4766 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4767 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4769 * If +end+ is smaller than +begin+, replaces no elements:
4771 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
4772 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
4774 * - If either is negative (or both are negative), counts backwards from the end of +self+:
4776 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
4777 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
4778 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
4780 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4781 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4782 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4784 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
4786 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
4787 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
4789 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4790 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4792 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
4793 * replaces elements to the end of +self+:
4795 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
4796 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
4798 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
4799 * replaces elements from the beginning of +self+:
4801 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
4802 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
4804 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4808 rb_ary_fill(int argc
, VALUE
*argv
, VALUE ary
)
4810 VALUE item
= Qundef
, arg1
, arg2
;
4811 long beg
= 0, end
= 0, len
= 0;
4813 if (rb_block_given_p()) {
4814 rb_scan_args(argc
, argv
, "02", &arg1
, &arg2
);
4815 argc
+= 1; /* hackish */
4818 rb_scan_args(argc
, argv
, "12", &item
, &arg1
, &arg2
);
4823 len
= RARRAY_LEN(ary
);
4826 if (rb_range_beg_len(arg1
, &beg
, &len
, RARRAY_LEN(ary
), 1)) {
4831 beg
= NIL_P(arg1
) ? 0 : NUM2LONG(arg1
);
4833 beg
= RARRAY_LEN(ary
) + beg
;
4834 if (beg
< 0) beg
= 0;
4836 len
= NIL_P(arg2
) ? RARRAY_LEN(ary
) - beg
: NUM2LONG(arg2
);
4843 if (beg
>= ARY_MAX_SIZE
|| len
> ARY_MAX_SIZE
- beg
) {
4844 rb_raise(rb_eArgError
, "argument too big");
4847 if (RARRAY_LEN(ary
) < end
) {
4848 if (end
>= ARY_CAPA(ary
)) {
4849 ary_resize_capa(ary
, end
);
4851 ary_mem_clear(ary
, RARRAY_LEN(ary
), end
- RARRAY_LEN(ary
));
4852 ARY_SET_LEN(ary
, end
);
4855 if (UNDEF_P(item
)) {
4859 for (i
=beg
; i
<end
; i
++) {
4860 v
= rb_yield(LONG2NUM(i
));
4861 if (i
>=RARRAY_LEN(ary
)) break;
4866 ary_memfill(ary
, beg
, len
, item
);
4873 * self + other_array -> new_array
4875 * Returns a new array containing all elements of +self+
4876 * followed by all elements of +other_array+:
4878 * a = [0, 1] + [2, 3]
4879 * a # => [0, 1, 2, 3]
4881 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
4885 rb_ary_plus(VALUE x
, VALUE y
)
4888 long len
, xlen
, ylen
;
4891 xlen
= RARRAY_LEN(x
);
4892 ylen
= RARRAY_LEN(y
);
4894 z
= rb_ary_new2(len
);
4896 ary_memcpy(z
, 0, xlen
, RARRAY_CONST_PTR(x
));
4897 ary_memcpy(z
, xlen
, ylen
, RARRAY_CONST_PTR(y
));
4898 ARY_SET_LEN(z
, len
);
4903 ary_append(VALUE x
, VALUE y
)
4905 long n
= RARRAY_LEN(y
);
4907 rb_ary_splice(x
, RARRAY_LEN(x
), 0, RARRAY_CONST_PTR(y
), n
);
4915 * concat(*other_arrays) -> self
4917 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
4920 * a.concat(['two', 'three'], [:four, :five], a)
4921 * # => [0, 1, "two", "three", :four, :five, 0, 1]
4923 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4927 rb_ary_concat_multi(int argc
, VALUE
*argv
, VALUE ary
)
4929 rb_ary_modify_check(ary
);
4932 rb_ary_concat(ary
, argv
[0]);
4934 else if (argc
> 1) {
4936 VALUE args
= rb_ary_hidden_new(argc
);
4937 for (i
= 0; i
< argc
; i
++) {
4938 rb_ary_concat(args
, argv
[i
]);
4940 ary_append(ary
, args
);
4948 rb_ary_concat(VALUE x
, VALUE y
)
4950 return ary_append(x
, to_ary(y
));
4955 * self * n -> new_array
4956 * self * string_separator -> new_string
4958 * When non-negative integer argument +n+ is given,
4959 * returns a new array built by concatenating +n+ copies of +self+:
4962 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
4964 * When string argument +string_separator+ is given,
4965 * equivalent to <tt>self.join(string_separator)</tt>:
4967 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
4972 rb_ary_times(VALUE ary
, VALUE times
)
4978 tmp
= rb_check_string_type(times
);
4980 return rb_ary_join(ary
, tmp
);
4983 len
= NUM2LONG(times
);
4985 ary2
= ary_new(rb_cArray
, 0);
4989 rb_raise(rb_eArgError
, "negative argument");
4991 if (ARY_MAX_SIZE
/len
< RARRAY_LEN(ary
)) {
4992 rb_raise(rb_eArgError
, "argument too big");
4994 len
*= RARRAY_LEN(ary
);
4996 ary2
= ary_new(rb_cArray
, len
);
4997 ARY_SET_LEN(ary2
, len
);
4999 ptr
= RARRAY_CONST_PTR(ary
);
5000 t
= RARRAY_LEN(ary
);
5002 ary_memcpy(ary2
, 0, t
, ptr
);
5003 while (t
<= len
/2) {
5004 ary_memcpy(ary2
, t
, t
, RARRAY_CONST_PTR(ary2
));
5008 ary_memcpy(ary2
, t
, len
-t
, RARRAY_CONST_PTR(ary2
));
5017 * assoc(object) -> found_array or nil
5019 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5020 * and <tt>ele[0] == object</tt>:
5022 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5023 * a.assoc(4) # => [4, 5, 6]
5025 * Returns +nil+ if no such element is found.
5027 * Related: Array#rassoc;
5028 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5032 rb_ary_assoc(VALUE ary
, VALUE key
)
5037 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5038 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5039 if (!NIL_P(v
) && RARRAY_LEN(v
) > 0 &&
5040 rb_equal(RARRAY_AREF(v
, 0), key
))
5048 * rassoc(object) -> found_array or nil
5050 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5051 * and <tt>ele[1] == object</tt>:
5053 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5054 * a.rassoc(4) # => [2, 4]
5055 * a.rassoc(5) # => [4, 5, 6]
5057 * Returns +nil+ if no such element is found.
5059 * Related: Array#assoc;
5060 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5064 rb_ary_rassoc(VALUE ary
, VALUE value
)
5069 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5070 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5071 if (RB_TYPE_P(v
, T_ARRAY
) &&
5072 RARRAY_LEN(v
) > 1 &&
5073 rb_equal(RARRAY_AREF(v
, 1), value
))
5080 recursive_equal(VALUE ary1
, VALUE ary2
, int recur
)
5083 const VALUE
*p1
, *p2
;
5085 if (recur
) return Qtrue
; /* Subtle! */
5087 /* rb_equal() can evacuate ptrs */
5088 p1
= RARRAY_CONST_PTR(ary1
);
5089 p2
= RARRAY_CONST_PTR(ary2
);
5090 len1
= RARRAY_LEN(ary1
);
5092 for (i
= 0; i
< len1
; i
++) {
5094 if (rb_equal(*p1
, *p2
)) {
5095 len1
= RARRAY_LEN(ary1
);
5096 if (len1
!= RARRAY_LEN(ary2
))
5100 p1
= RARRAY_CONST_PTR(ary1
) + i
;
5101 p2
= RARRAY_CONST_PTR(ary2
) + i
;
5115 * self == other_array -> true or false
5117 * Returns whether both:
5119 * - +self+ and +other_array+ are the same size.
5120 * - Their corresponding elements are the same;
5121 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5122 * <tt>self[i] == other_array[i]</tt>.
5126 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5127 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5128 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5129 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5131 * This method is different from method Array#eql?,
5132 * which compares elements using <tt>Object#eql?</tt>.
5134 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5138 rb_ary_equal(VALUE ary1
, VALUE ary2
)
5140 if (ary1
== ary2
) return Qtrue
;
5141 if (!RB_TYPE_P(ary2
, T_ARRAY
)) {
5142 if (!rb_respond_to(ary2
, idTo_ary
)) {
5145 return rb_equal(ary2
, ary1
);
5147 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5148 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5149 return rb_exec_recursive_paired(recursive_equal
, ary1
, ary2
, ary2
);
5153 recursive_eql(VALUE ary1
, VALUE ary2
, int recur
)
5157 if (recur
) return Qtrue
; /* Subtle! */
5158 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5159 if (!rb_eql(rb_ary_elt(ary1
, i
), rb_ary_elt(ary2
, i
)))
5167 * eql?(other_array) -> true or false
5169 * Returns +true+ if +self+ and +other_array+ are the same size,
5170 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5172 * a0 = [:foo, 'bar', 2]
5173 * a1 = [:foo, 'bar', 2]
5174 * a1.eql?(a0) # => true
5176 * Otherwise, returns +false+.
5178 * This method is different from method Array#==,
5179 * which compares using method <tt>Object#==</tt>.
5181 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5185 rb_ary_eql(VALUE ary1
, VALUE ary2
)
5187 if (ary1
== ary2
) return Qtrue
;
5188 if (!RB_TYPE_P(ary2
, T_ARRAY
)) return Qfalse
;
5189 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5190 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5191 return rb_exec_recursive_paired(recursive_eql
, ary1
, ary2
, ary2
);
5195 rb_ary_hash_values(long len
, const VALUE
*elements
)
5201 h
= rb_hash_start(len
);
5202 h
= rb_hash_uint(h
, (st_index_t
)rb_ary_hash_values
);
5203 for (i
=0; i
<len
; i
++) {
5204 n
= rb_hash(elements
[i
]);
5205 h
= rb_hash_uint(h
, NUM2LONG(n
));
5215 * Returns the integer hash value for +self+.
5217 * Two arrays with the same content will have the same hash value
5218 * (and will compare using eql?):
5220 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5221 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5222 * ['a', 'b'].hash == ['a'].hash # => false
5227 rb_ary_hash(VALUE ary
)
5229 return rb_ary_hash_values(RARRAY_LEN(ary
), RARRAY_CONST_PTR(ary
));
5234 * include?(object) -> true or false
5236 * Returns whether for some element +element+ in +self+,
5237 * <tt>object == element</tt>:
5239 * [0, 1, 2].include?(2) # => true
5240 * [0, 1, 2].include?(2.0) # => true
5241 * [0, 1, 2].include?(2.1) # => false
5243 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5247 rb_ary_includes(VALUE ary
, VALUE item
)
5252 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5253 e
= RARRAY_AREF(ary
, i
);
5254 if (rb_equal(e
, item
)) {
5262 rb_ary_includes_by_eql(VALUE ary
, VALUE item
)
5267 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5268 e
= RARRAY_AREF(ary
, i
);
5269 if (rb_eql(item
, e
)) {
5277 recursive_cmp(VALUE ary1
, VALUE ary2
, int recur
)
5281 if (recur
) return Qundef
; /* Subtle! */
5282 len
= RARRAY_LEN(ary1
);
5283 if (len
> RARRAY_LEN(ary2
)) {
5284 len
= RARRAY_LEN(ary2
);
5286 for (i
=0; i
<len
; i
++) {
5287 VALUE e1
= rb_ary_elt(ary1
, i
), e2
= rb_ary_elt(ary2
, i
);
5288 VALUE v
= rb_funcallv(e1
, id_cmp
, 1, &e2
);
5289 if (v
!= INT2FIX(0)) {
5298 * self <=> other_array -> -1, 0, or 1
5300 * Returns -1, 0, or 1 as +self+ is determined
5301 * to be less than, equal to, or greater than +other_array+.
5303 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5305 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5306 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5308 * [0, 1, 2] <=> [0, 0, 2] # => 1
5310 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5312 * [0, 1, 2] <=> [0, 2, 2] # => -1
5314 * - Continues if <tt>result[i]</tt> is 0.
5316 * When every +result+ is 0,
5317 * returns <tt>self.size <=> other_array.size</tt>
5318 * (see Integer#<=>):
5320 * [0, 1, 2] <=> [0, 1] # => 1
5321 * [0, 1, 2] <=> [0, 1, 2] # => 0
5322 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5324 * Note that when +other_array+ is larger than +self+,
5325 * its trailing elements do not affect the result:
5327 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5328 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5329 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5331 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5335 rb_ary_cmp(VALUE ary1
, VALUE ary2
)
5340 ary2
= rb_check_array_type(ary2
);
5341 if (NIL_P(ary2
)) return Qnil
;
5342 if (ary1
== ary2
) return INT2FIX(0);
5343 v
= rb_exec_recursive_paired(recursive_cmp
, ary1
, ary2
, ary2
);
5344 if (!UNDEF_P(v
)) return v
;
5345 len
= RARRAY_LEN(ary1
) - RARRAY_LEN(ary2
);
5346 if (len
== 0) return INT2FIX(0);
5347 if (len
> 0) return INT2FIX(1);
5352 ary_add_hash(VALUE hash
, VALUE ary
)
5356 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5357 VALUE elt
= RARRAY_AREF(ary
, i
);
5358 rb_hash_add_new_element(hash
, elt
, elt
);
5364 ary_tmp_hash_new(VALUE ary
)
5366 long size
= RARRAY_LEN(ary
);
5367 VALUE hash
= rb_hash_new_with_size(size
);
5369 RBASIC_CLEAR_CLASS(hash
);
5374 ary_make_hash(VALUE ary
)
5376 VALUE hash
= ary_tmp_hash_new(ary
);
5377 return ary_add_hash(hash
, ary
);
5381 ary_add_hash_by(VALUE hash
, VALUE ary
)
5385 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5386 VALUE v
= rb_ary_elt(ary
, i
), k
= rb_yield(v
);
5387 rb_hash_add_new_element(hash
, k
, v
);
5393 ary_make_hash_by(VALUE ary
)
5395 VALUE hash
= ary_tmp_hash_new(ary
);
5396 return ary_add_hash_by(hash
, ary
);
5401 * self - other_array -> new_array
5403 * Returns a new array containing only those elements of +self+
5404 * that are not found in +other_array+;
5405 * the order from +self+ is preserved:
5407 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5408 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5409 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5411 * Element are compared using method <tt>#eql?</tt>
5412 * (as defined in each element of +self+).
5414 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5418 rb_ary_diff(VALUE ary1
, VALUE ary2
)
5424 ary2
= to_ary(ary2
);
5425 if (RARRAY_LEN(ary2
) == 0) { return ary_make_shared_copy(ary1
); }
5426 ary3
= rb_ary_new();
5428 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
|| RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5429 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5430 VALUE elt
= rb_ary_elt(ary1
, i
);
5431 if (rb_ary_includes_by_eql(ary2
, elt
)) continue;
5432 rb_ary_push(ary3
, elt
);
5437 hash
= ary_make_hash(ary2
);
5438 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5439 if (rb_hash_stlike_lookup(hash
, RARRAY_AREF(ary1
, i
), NULL
)) continue;
5440 rb_ary_push(ary3
, rb_ary_elt(ary1
, i
));
5448 * difference(*other_arrays = []) -> new_array
5450 * Returns a new array containing only those elements from +self+
5451 * that are not found in any of the given +other_arrays+;
5452 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5454 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5455 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5456 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5457 * [0, 1, 2].difference # => [0, 1, 2]
5459 * Returns a copy of +self+ if no arguments are given.
5462 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5466 rb_ary_difference_multi(int argc
, VALUE
*argv
, VALUE ary
)
5471 bool *is_hash
= ALLOCV_N(bool, t0
, argc
);
5472 ary_diff
= rb_ary_new();
5473 length
= RARRAY_LEN(ary
);
5475 for (i
= 0; i
< argc
; i
++) {
5476 argv
[i
] = to_ary(argv
[i
]);
5477 is_hash
[i
] = (length
> SMALL_ARRAY_LEN
&& RARRAY_LEN(argv
[i
]) > SMALL_ARRAY_LEN
);
5478 if (is_hash
[i
]) argv
[i
] = ary_make_hash(argv
[i
]);
5481 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5483 VALUE elt
= rb_ary_elt(ary
, i
);
5484 for (j
= 0; j
< argc
; j
++) {
5486 if (rb_hash_stlike_lookup(argv
[j
], RARRAY_AREF(ary
, i
), NULL
))
5490 if (rb_ary_includes_by_eql(argv
[j
], elt
)) break;
5493 if (j
== argc
) rb_ary_push(ary_diff
, elt
);
5504 * self & other_array -> new_array
5506 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5507 * that is, containing those elements found in both +self+ and +other_array+:
5509 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5513 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5515 * Preserves order from +self+:
5517 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5519 * Identifies common elements using method <tt>#eql?</tt>
5520 * (as defined in each element of +self+).
5522 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5527 rb_ary_and(VALUE ary1
, VALUE ary2
)
5529 VALUE hash
, ary3
, v
;
5533 ary2
= to_ary(ary2
);
5534 ary3
= rb_ary_new();
5535 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return ary3
;
5537 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5538 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5539 v
= RARRAY_AREF(ary1
, i
);
5540 if (!rb_ary_includes_by_eql(ary2
, v
)) continue;
5541 if (rb_ary_includes_by_eql(ary3
, v
)) continue;
5542 rb_ary_push(ary3
, v
);
5547 hash
= ary_make_hash(ary2
);
5549 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5550 v
= RARRAY_AREF(ary1
, i
);
5552 if (rb_hash_stlike_delete(hash
, &vv
, 0)) {
5553 rb_ary_push(ary3
, v
);
5562 * intersection(*other_arrays) -> new_array
5564 * Returns a new array containing each element in +self+ that is +#eql?+
5565 * to at least one element in each of the given +other_arrays+;
5566 * duplicates are omitted:
5568 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5570 * Each element must correctly implement method <tt>#hash</tt>.
5572 * Order from +self+ is preserved:
5574 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5576 * Returns a copy of +self+ if no arguments are given.
5578 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5582 rb_ary_intersection_multi(int argc
, VALUE
*argv
, VALUE ary
)
5584 VALUE result
= rb_ary_dup(ary
);
5587 for (i
= 0; i
< argc
; i
++) {
5588 result
= rb_ary_and(result
, argv
[i
]);
5595 ary_hash_orset(st_data_t
*key
, st_data_t
*value
, st_data_t arg
, int existing
)
5597 if (existing
) return ST_STOP
;
5598 *key
= *value
= (VALUE
)arg
;
5603 rb_ary_union(VALUE ary_union
, VALUE ary
)
5606 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5607 VALUE elt
= rb_ary_elt(ary
, i
);
5608 if (rb_ary_includes_by_eql(ary_union
, elt
)) continue;
5609 rb_ary_push(ary_union
, elt
);
5614 rb_ary_union_hash(VALUE hash
, VALUE ary2
)
5617 for (i
= 0; i
< RARRAY_LEN(ary2
); i
++) {
5618 VALUE elt
= RARRAY_AREF(ary2
, i
);
5619 if (!rb_hash_stlike_update(hash
, (st_data_t
)elt
, ary_hash_orset
, (st_data_t
)elt
)) {
5620 RB_OBJ_WRITTEN(hash
, Qundef
, elt
);
5627 * array | other_array -> new_array
5629 * Returns the union of +array+ and +Array+ +other_array+;
5630 * duplicates are removed; order is preserved;
5631 * items are compared using <tt>eql?</tt>:
5633 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5634 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5635 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5637 * Related: Array#union.
5641 rb_ary_or(VALUE ary1
, VALUE ary2
)
5645 ary2
= to_ary(ary2
);
5646 if (RARRAY_LEN(ary1
) + RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5647 VALUE ary3
= rb_ary_new();
5648 rb_ary_union(ary3
, ary1
);
5649 rb_ary_union(ary3
, ary2
);
5653 hash
= ary_make_hash(ary1
);
5654 rb_ary_union_hash(hash
, ary2
);
5656 return rb_hash_values(hash
);
5661 * union(*other_arrays) -> new_array
5663 * Returns a new array that is the union of the elements of +self+
5664 * and all given arrays +other_arrays+;
5665 * items are compared using <tt>eql?</tt>:
5667 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5669 * Removes duplicates (preserving the first found):
5671 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5673 * Preserves order (preserving the position of the first found):
5675 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
5677 * With no arguments given, returns a copy of +self+.
5679 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5683 rb_ary_union_multi(int argc
, VALUE
*argv
, VALUE ary
)
5689 sum
= RARRAY_LEN(ary
);
5690 for (i
= 0; i
< argc
; i
++) {
5691 argv
[i
] = to_ary(argv
[i
]);
5692 sum
+= RARRAY_LEN(argv
[i
]);
5695 if (sum
<= SMALL_ARRAY_LEN
) {
5696 VALUE ary_union
= rb_ary_new();
5698 rb_ary_union(ary_union
, ary
);
5699 for (i
= 0; i
< argc
; i
++) rb_ary_union(ary_union
, argv
[i
]);
5704 hash
= ary_make_hash(ary
);
5705 for (i
= 0; i
< argc
; i
++) rb_ary_union_hash(hash
, argv
[i
]);
5707 return rb_hash_values(hash
);
5712 * intersect?(other_array) -> true or false
5714 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5716 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5717 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5719 * Each element must correctly implement method <tt>#hash</tt>.
5721 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5725 rb_ary_intersect_p(VALUE ary1
, VALUE ary2
)
5727 VALUE hash
, v
, result
, shorter
, longer
;
5731 ary2
= to_ary(ary2
);
5732 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return Qfalse
;
5734 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5735 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5736 v
= RARRAY_AREF(ary1
, i
);
5737 if (rb_ary_includes_by_eql(ary2
, v
)) return Qtrue
;
5744 if (RARRAY_LEN(ary1
) > RARRAY_LEN(ary2
)) {
5749 hash
= ary_make_hash(shorter
);
5752 for (i
=0; i
<RARRAY_LEN(longer
); i
++) {
5753 v
= RARRAY_AREF(longer
, i
);
5755 if (rb_hash_stlike_lookup(hash
, vv
, 0)) {
5765 ary_max_generic(VALUE ary
, long i
, VALUE vmax
)
5767 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5770 for (; i
< RARRAY_LEN(ary
); ++i
) {
5771 v
= RARRAY_AREF(ary
, i
);
5773 if (rb_cmpint(rb_funcallv(vmax
, id_cmp
, 1, &v
), vmax
, v
) < 0) {
5782 ary_max_opt_fixnum(VALUE ary
, long i
, VALUE vmax
)
5784 const long n
= RARRAY_LEN(ary
);
5785 RUBY_ASSERT(i
> 0 && i
< n
);
5786 RUBY_ASSERT(FIXNUM_P(vmax
));
5789 for (; i
< n
; ++i
) {
5790 v
= RARRAY_AREF(ary
, i
);
5793 if ((long)vmax
< (long)v
) {
5798 return ary_max_generic(ary
, i
, vmax
);
5806 ary_max_opt_float(VALUE ary
, long i
, VALUE vmax
)
5808 const long n
= RARRAY_LEN(ary
);
5809 RUBY_ASSERT(i
> 0 && i
< n
);
5810 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax
));
5813 for (; i
< n
; ++i
) {
5814 v
= RARRAY_AREF(ary
, i
);
5816 if (RB_FLOAT_TYPE_P(v
)) {
5817 if (rb_float_cmp(vmax
, v
) < 0) {
5822 return ary_max_generic(ary
, i
, vmax
);
5830 ary_max_opt_string(VALUE ary
, long i
, VALUE vmax
)
5832 const long n
= RARRAY_LEN(ary
);
5833 RUBY_ASSERT(i
> 0 && i
< n
);
5834 RUBY_ASSERT(STRING_P(vmax
));
5837 for (; i
< n
; ++i
) {
5838 v
= RARRAY_AREF(ary
, i
);
5841 if (rb_str_cmp(vmax
, v
) < 0) {
5846 return ary_max_generic(ary
, i
, vmax
);
5856 * max(n) -> new_array
5857 * max {|a, b| ... } -> element
5858 * max(n) {|a, b| ... } -> new_array
5860 * Returns one of the following:
5862 * - The maximum-valued element from +self+.
5863 * - A new array of maximum-valued elements from +self+.
5865 * Does not modify +self+.
5867 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
5870 * With no argument and no block, returns the element in +self+
5871 * having the maximum value per method <tt>#<=></tt>:
5873 * [1, 0, 3, 2].max # => 3
5875 * With non-negative numeric argument +n+ and no block,
5876 * returns a new array with at most +n+ elements,
5877 * in descending order, per method <tt>#<=></tt>:
5879 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
5880 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
5881 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
5882 * [1, 0, 3, 2].max(0) # => []
5884 * With a block given, the block must return a numeric.
5886 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
5887 * returns the element having the maximum value per the block:
5889 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
5892 * With non-negative numeric argument +n+ and a block,
5893 * returns a new array with at most +n+ elements,
5894 * in descending order, per the block:
5896 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
5897 * # => ["000", "00"]
5899 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5902 rb_ary_max(int argc
, VALUE
*argv
, VALUE ary
)
5904 VALUE result
= Qundef
, v
;
5908 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
5909 return rb_nmin_run(ary
, num
, 0, 1, 1);
5911 const long n
= RARRAY_LEN(ary
);
5912 if (rb_block_given_p()) {
5913 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5914 v
= RARRAY_AREF(ary
, i
);
5915 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) > 0) {
5921 result
= RARRAY_AREF(ary
, 0);
5923 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
5924 return ary_max_opt_fixnum(ary
, 1, result
);
5926 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
5927 return ary_max_opt_string(ary
, 1, result
);
5929 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
5930 return ary_max_opt_float(ary
, 1, result
);
5933 return ary_max_generic(ary
, 1, result
);
5937 if (UNDEF_P(result
)) return Qnil
;
5942 ary_min_generic(VALUE ary
, long i
, VALUE vmin
)
5944 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5947 for (; i
< RARRAY_LEN(ary
); ++i
) {
5948 v
= RARRAY_AREF(ary
, i
);
5950 if (rb_cmpint(rb_funcallv(vmin
, id_cmp
, 1, &v
), vmin
, v
) > 0) {
5959 ary_min_opt_fixnum(VALUE ary
, long i
, VALUE vmin
)
5961 const long n
= RARRAY_LEN(ary
);
5962 RUBY_ASSERT(i
> 0 && i
< n
);
5963 RUBY_ASSERT(FIXNUM_P(vmin
));
5966 for (; i
< n
; ++i
) {
5967 a
= RARRAY_AREF(ary
, i
);
5970 if ((long)vmin
> (long)a
) {
5975 return ary_min_generic(ary
, i
, vmin
);
5983 ary_min_opt_float(VALUE ary
, long i
, VALUE vmin
)
5985 const long n
= RARRAY_LEN(ary
);
5986 RUBY_ASSERT(i
> 0 && i
< n
);
5987 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin
));
5990 for (; i
< n
; ++i
) {
5991 a
= RARRAY_AREF(ary
, i
);
5993 if (RB_FLOAT_TYPE_P(a
)) {
5994 if (rb_float_cmp(vmin
, a
) > 0) {
5999 return ary_min_generic(ary
, i
, vmin
);
6007 ary_min_opt_string(VALUE ary
, long i
, VALUE vmin
)
6009 const long n
= RARRAY_LEN(ary
);
6010 RUBY_ASSERT(i
> 0 && i
< n
);
6011 RUBY_ASSERT(STRING_P(vmin
));
6014 for (; i
< n
; ++i
) {
6015 a
= RARRAY_AREF(ary
, i
);
6018 if (rb_str_cmp(vmin
, a
) > 0) {
6023 return ary_min_generic(ary
, i
, vmin
);
6033 * min(n) -> new_array
6034 * min {|a, b| ... } -> element
6035 * min(n) {|a, b| ... } -> new_array
6037 * Returns one of the following:
6039 * - The minimum-valued element from +self+.
6040 * - A new array of minimum-valued elements from +self+.
6042 * Does not modify +self+.
6044 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6047 * With no argument and no block, returns the element in +self+
6048 * having the minimum value per method <tt>#<=></tt>:
6050 * [1, 0, 3, 2].min # => 0
6052 * With non-negative numeric argument +n+ and no block,
6053 * returns a new array with at most +n+ elements,
6054 * in ascending order, per method <tt>#<=></tt>:
6056 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6057 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6058 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6059 * [1, 0, 3, 2].min(0) # => []
6061 * With a block given, the block must return a numeric.
6063 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6064 * returns the element having the minimum value per the block:
6066 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6069 * With non-negative numeric argument +n+ and a block,
6070 * returns a new array with at most +n+ elements,
6071 * in ascending order, per the block:
6073 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6076 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6079 rb_ary_min(int argc
, VALUE
*argv
, VALUE ary
)
6081 VALUE result
= Qundef
, v
;
6085 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
6086 return rb_nmin_run(ary
, num
, 0, 0, 1);
6088 const long n
= RARRAY_LEN(ary
);
6089 if (rb_block_given_p()) {
6090 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6091 v
= RARRAY_AREF(ary
, i
);
6092 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) < 0) {
6098 result
= RARRAY_AREF(ary
, 0);
6100 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
6101 return ary_min_opt_fixnum(ary
, 1, result
);
6103 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
6104 return ary_min_opt_string(ary
, 1, result
);
6106 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
6107 return ary_min_opt_float(ary
, 1, result
);
6110 return ary_min_generic(ary
, 1, result
);
6114 if (UNDEF_P(result
)) return Qnil
;
6121 * minmax {|a, b| ... } -> array
6123 * Returns a 2-element array containing the minimum-valued and maximum-valued
6124 * elements from +self+;
6125 * does not modify +self+.
6127 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6129 * [1, 0, 3, 2].minmax # => [0, 3]
6131 * With a block given, the block must return a numeric;
6132 * the block is called <tt>self.size - 1</tt> times to compare elements;
6133 * returns the elements having the minimum and maximum values per the block:
6135 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6138 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6141 rb_ary_minmax(VALUE ary
)
6143 if (rb_block_given_p()) {
6144 return rb_call_super(0, NULL
);
6146 return rb_assoc_new(rb_ary_min(0, 0, ary
), rb_ary_max(0, 0, ary
));
6150 push_value(st_data_t key
, st_data_t val
, st_data_t ary
)
6152 rb_ary_push((VALUE
)ary
, (VALUE
)val
);
6158 * array.uniq! -> self or nil
6159 * array.uniq! {|element| ... } -> self or nil
6161 * Removes duplicate elements from +self+, the first occurrence always being retained;
6162 * returns +self+ if any elements removed, +nil+ otherwise.
6164 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6167 * Returns +self+ if any elements removed:
6169 * a = [0, 0, 1, 1, 2, 2]
6170 * a.uniq! # => [0, 1, 2]
6172 * Returns +nil+ if no elements removed.
6174 * With a block given, calls the block for each element;
6175 * identifies (using method <tt>eql?</tt>) and removes
6176 * elements for which the block returns duplicate values.
6178 * Returns +self+ if any elements removed:
6180 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6181 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
6183 * Returns +nil+ if no elements removed.
6186 rb_ary_uniq_bang(VALUE ary
)
6191 rb_ary_modify_check(ary
);
6192 if (RARRAY_LEN(ary
) <= 1)
6194 if (rb_block_given_p())
6195 hash
= ary_make_hash_by(ary
);
6197 hash
= ary_make_hash(ary
);
6199 hash_size
= RHASH_SIZE(hash
);
6200 if (RARRAY_LEN(ary
) == hash_size
) {
6203 rb_ary_modify_check(ary
);
6204 ARY_SET_LEN(ary
, 0);
6205 if (ARY_SHARED_P(ary
)) {
6206 rb_ary_unshare(ary
);
6209 ary_resize_capa(ary
, hash_size
);
6210 rb_hash_foreach(hash
, push_value
, ary
);
6217 * array.uniq -> new_array
6218 * array.uniq {|element| ... } -> new_array
6220 * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
6221 * the first occurrence always being retained.
6223 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
6226 * a = [0, 0, 1, 1, 2, 2]
6227 * a.uniq # => [0, 1, 2]
6229 * With a block given, calls the block for each element;
6230 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
6231 * that is, those elements for which the block returns the same value:
6233 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6234 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6239 rb_ary_uniq(VALUE ary
)
6243 if (RARRAY_LEN(ary
) <= 1) {
6245 uniq
= rb_ary_dup(ary
);
6247 else if (rb_block_given_p()) {
6248 hash
= ary_make_hash_by(ary
);
6249 uniq
= rb_hash_values(hash
);
6252 hash
= ary_make_hash(ary
);
6253 uniq
= rb_hash_values(hash
);
6261 * compact! -> self or nil
6263 * Removes all +nil+ elements from +self+;
6264 * Returns +self+ if any elements are removed, +nil+ otherwise:
6266 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6267 * a.compact! # => [0, false, "", [], {}]
6268 * a # => [0, false, "", [], {}]
6269 * a.compact! # => nil
6271 * Related: Array#compact;
6272 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6276 rb_ary_compact_bang(VALUE ary
)
6282 p
= t
= (VALUE
*)RARRAY_CONST_PTR(ary
); /* WB: no new reference */
6283 end
= p
+ RARRAY_LEN(ary
);
6289 n
= p
- RARRAY_CONST_PTR(ary
);
6290 if (RARRAY_LEN(ary
) == n
) {
6293 ary_resize_smaller(ary
, n
);
6300 * compact -> new_array
6302 * Returns a new array containing only the non-+nil+ elements from +self+;
6303 * element order is preserved:
6305 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6306 * a.compact # => [0, false, "", [], {}]
6308 * Related: Array#compact!;
6309 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6313 rb_ary_compact(VALUE ary
)
6315 ary
= rb_ary_dup(ary
);
6316 rb_ary_compact_bang(ary
);
6323 * count(object) -> integer
6324 * count {|element| ... } -> integer
6326 * Returns a count of specified elements.
6328 * With no argument and no block, returns the count of all elements:
6330 * [0, :one, 'two', 3, 3.0].count # => 5
6332 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6334 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6336 * With no argument and a block given, calls the block with each element;
6337 * returns the count of elements for which the block returns a truthy value:
6339 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6341 * With argument +object+ and a block given, issues a warning, ignores the block,
6342 * and returns the count of elements <tt>==</tt> to +object+.
6344 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6348 rb_ary_count(int argc
, VALUE
*argv
, VALUE ary
)
6352 if (rb_check_arity(argc
, 0, 1) == 0) {
6355 if (!rb_block_given_p())
6356 return LONG2NUM(RARRAY_LEN(ary
));
6358 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6359 v
= RARRAY_AREF(ary
, i
);
6360 if (RTEST(rb_yield(v
))) n
++;
6364 VALUE obj
= argv
[0];
6366 if (rb_block_given_p()) {
6367 rb_warn("given block not used");
6369 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6370 if (rb_equal(RARRAY_AREF(ary
, i
), obj
)) n
++;
6378 flatten(VALUE ary
, int level
)
6381 VALUE stack
, result
, tmp
= 0, elt
;
6382 VALUE memo
= Qfalse
;
6384 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6385 elt
= RARRAY_AREF(ary
, i
);
6386 tmp
= rb_check_array_type(elt
);
6391 if (i
== RARRAY_LEN(ary
)) {
6395 result
= ary_new(0, RARRAY_LEN(ary
));
6396 ary_memcpy(result
, 0, i
, RARRAY_CONST_PTR(ary
));
6397 ARY_SET_LEN(result
, i
);
6399 stack
= ary_new(0, ARY_DEFAULT_SIZE
);
6400 rb_ary_push(stack
, ary
);
6401 rb_ary_push(stack
, LONG2NUM(i
+ 1));
6404 memo
= rb_obj_hide(rb_ident_hash_new());
6405 rb_hash_aset(memo
, ary
, Qtrue
);
6406 rb_hash_aset(memo
, tmp
, Qtrue
);
6413 while (i
< RARRAY_LEN(ary
)) {
6414 elt
= RARRAY_AREF(ary
, i
++);
6415 if (level
>= 0 && RARRAY_LEN(stack
) / 2 >= level
) {
6416 rb_ary_push(result
, elt
);
6419 tmp
= rb_check_array_type(elt
);
6420 if (RBASIC(result
)->klass
) {
6422 rb_hash_clear(memo
);
6424 rb_raise(rb_eRuntimeError
, "flatten reentered");
6427 rb_ary_push(result
, elt
);
6431 if (rb_hash_aref(memo
, tmp
) == Qtrue
) {
6432 rb_hash_clear(memo
);
6433 rb_raise(rb_eArgError
, "tried to flatten recursive array");
6435 rb_hash_aset(memo
, tmp
, Qtrue
);
6437 rb_ary_push(stack
, ary
);
6438 rb_ary_push(stack
, LONG2NUM(i
));
6443 if (RARRAY_LEN(stack
) == 0) {
6447 rb_hash_delete(memo
, ary
);
6449 tmp
= rb_ary_pop(stack
);
6451 ary
= rb_ary_pop(stack
);
6455 rb_hash_clear(memo
);
6458 RBASIC_SET_CLASS(result
, rb_cArray
);
6464 * flatten!(depth = nil) -> self or nil
6466 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6467 * +depth+ must be an
6468 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6470 * At each level of recursion:
6472 * - Each element that is an array is "flattened"
6473 * (that is, replaced by its individual array elements).
6474 * - Each element that is not an array is unchanged
6475 * (even if the element is an object that has instance method +flatten+).
6477 * Returns +nil+ if no elements were flattened.
6479 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6481 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6482 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6483 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6484 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6485 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6486 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6488 * With +nil+ or negative argument +depth+, flattens all levels:
6490 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6491 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6493 * Related: Array#flatten;
6494 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6498 rb_ary_flatten_bang(int argc
, VALUE
*argv
, VALUE ary
)
6500 int mod
= 0, level
= -1;
6503 lv
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : Qnil
);
6504 rb_ary_modify_check(ary
);
6505 if (!NIL_P(lv
)) level
= NUM2INT(lv
);
6506 if (level
== 0) return Qnil
;
6508 result
= flatten(ary
, level
);
6509 if (result
== ary
) {
6512 if (!(mod
= ARY_EMBED_P(result
))) rb_ary_freeze(result
);
6513 rb_ary_replace(ary
, result
);
6514 if (mod
) ARY_SET_EMBED_LEN(result
, 0);
6521 * flatten(depth = nil) -> new_array
6523 * Returns a new array that is a recursive flattening of +self+
6524 * to +depth+ levels of recursion;
6525 * +depth+ must be an
6526 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6528 * At each level of recursion:
6530 * - Each element that is an array is "flattened"
6531 * (that is, replaced by its individual array elements).
6532 * - Each element that is not an array is unchanged
6533 * (even if the element is an object that has instance method +flatten+).
6535 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6537 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6538 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6539 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6540 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6541 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6542 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6543 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6545 * With +nil+ or negative +depth+, flattens all levels.
6547 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6548 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6550 * Related: Array#flatten!;
6551 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6555 rb_ary_flatten(int argc
, VALUE
*argv
, VALUE ary
)
6560 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0])) {
6561 level
= NUM2INT(argv
[0]);
6562 if (level
== 0) return ary_make_shared_copy(ary
);
6565 result
= flatten(ary
, level
);
6566 if (result
== ary
) {
6567 result
= ary_make_shared_copy(ary
);
6573 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6576 rb_ary_shuffle_bang(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6581 i
= len
= RARRAY_LEN(ary
);
6582 RARRAY_PTR_USE(ary
, ptr
, {
6584 long j
= RAND_UPTO(i
);
6586 if (len
!= RARRAY_LEN(ary
) || ptr
!= RARRAY_CONST_PTR(ary
)) {
6587 rb_raise(rb_eRuntimeError
, "modified during shuffle");
6593 }); /* WB: no new reference */
6598 rb_ary_shuffle(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6600 ary
= rb_ary_dup(ary
);
6601 rb_ary_shuffle_bang(ec
, ary
, randgen
);
6605 static const rb_data_type_t ary_sample_memo_type
= {
6606 .wrap_struct_name
= "ary_sample_memo",
6608 .dfree
= (RUBY_DATA_FUNC
)st_free_table
,
6610 .flags
= RUBY_TYPED_WB_PROTECTED
| RUBY_TYPED_FREE_IMMEDIATELY
6614 ary_sample(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
, VALUE nv
, VALUE to_array
)
6617 long n
, len
, i
, j
, k
, idx
[10];
6618 long rnds
[numberof(idx
)];
6619 long memo_threshold
;
6621 len
= RARRAY_LEN(ary
);
6628 return rb_ary_elt(ary
, i
);
6631 if (n
< 0) rb_raise(rb_eArgError
, "negative sample number");
6632 if (n
> len
) n
= len
;
6633 if (n
<= numberof(idx
)) {
6634 for (i
= 0; i
< n
; ++i
) {
6635 rnds
[i
] = RAND_UPTO(len
- i
);
6639 len
= RARRAY_LEN(ary
);
6640 if (len
< k
&& n
<= numberof(idx
)) {
6641 for (i
= 0; i
< n
; ++i
) {
6642 if (rnds
[i
] >= len
) return rb_ary_new_capa(0);
6645 if (n
> len
) n
= len
;
6648 return rb_ary_new_capa(0);
6651 return rb_ary_new_from_args(1, RARRAY_AREF(ary
, i
));
6656 return rb_ary_new_from_args(2, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
));
6663 if (j
>= i
) l
= i
, g
= ++j
;
6664 if (k
>= l
&& (++k
>= g
)) ++k
;
6666 return rb_ary_new_from_args(3, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
), RARRAY_AREF(ary
, k
));
6669 len
< 2560 ? len
/ 128 :
6670 len
< 5120 ? len
/ 64 :
6671 len
< 10240 ? len
/ 32 :
6673 if (n
<= numberof(idx
)) {
6674 long sorted
[numberof(idx
)];
6675 sorted
[0] = idx
[0] = rnds
[0];
6676 for (i
=1; i
<n
; i
++) {
6678 for (j
= 0; j
< i
; ++j
) {
6679 if (k
< sorted
[j
]) break;
6682 memmove(&sorted
[j
+1], &sorted
[j
], sizeof(sorted
[0])*(i
-j
));
6683 sorted
[j
] = idx
[i
] = k
;
6685 result
= rb_ary_new_capa(n
);
6686 RARRAY_PTR_USE(result
, ptr_result
, {
6687 for (i
=0; i
<n
; i
++) {
6688 ptr_result
[i
] = RARRAY_AREF(ary
, idx
[i
]);
6692 else if (n
<= memo_threshold
/ 2) {
6694 VALUE vmemo
= TypedData_Wrap_Struct(0, &ary_sample_memo_type
, 0);
6695 st_table
*memo
= st_init_numtable_with_size(n
);
6696 RTYPEDDATA_DATA(vmemo
) = memo
;
6697 result
= rb_ary_new_capa(n
);
6698 RARRAY_PTR_USE(result
, ptr_result
, {
6699 for (i
=0; i
<n
; i
++) {
6700 long r
= RAND_UPTO(len
-i
) + i
;
6702 if (r
> max_idx
) max_idx
= r
;
6704 len
= RARRAY_LEN(ary
);
6705 if (len
<= max_idx
) n
= 0;
6706 else if (n
> len
) n
= len
;
6707 RARRAY_PTR_USE(ary
, ptr_ary
, {
6708 for (i
=0; i
<n
; i
++) {
6709 long j2
= j
= ptr_result
[i
];
6712 if (st_lookup(memo
, (st_data_t
)i
, &value
)) i2
= (long)value
;
6713 if (st_lookup(memo
, (st_data_t
)j
, &value
)) j2
= (long)value
;
6714 st_insert(memo
, (st_data_t
)j
, (st_data_t
)i2
);
6715 ptr_result
[i
] = ptr_ary
[j2
];
6719 RTYPEDDATA_DATA(vmemo
) = 0;
6720 st_free_table(memo
);
6724 result
= rb_ary_dup(ary
);
6725 RBASIC_CLEAR_CLASS(result
);
6727 RARRAY_PTR_USE(result
, ptr_result
, {
6728 for (i
=0; i
<n
; i
++) {
6729 j
= RAND_UPTO(len
-i
) + i
;
6731 ptr_result
[j
] = ptr_result
[i
];
6735 RBASIC_SET_CLASS_RAW(result
, rb_cArray
);
6737 ARY_SET_LEN(result
, n
);
6743 ary_sample0(rb_execution_context_t
*ec
, VALUE ary
)
6745 return ary_sample(ec
, ary
, rb_cRandom
, Qfalse
, Qfalse
);
6749 rb_ary_cycle_size(VALUE self
, VALUE args
, VALUE eobj
)
6753 if (args
&& (RARRAY_LEN(args
) > 0)) {
6754 n
= RARRAY_AREF(args
, 0);
6756 if (RARRAY_LEN(self
) == 0) return INT2FIX(0);
6757 if (NIL_P(n
)) return DBL2NUM(HUGE_VAL
);
6759 if (mul
<= 0) return INT2FIX(0);
6761 return rb_fix_mul_fix(rb_ary_length(self
), n
);
6766 * cycle(count = nil) {|element| ... } -> nil
6767 * cycle(count = nil) -> new_enumerator
6769 * With a block given, may call the block, depending on the value of argument +count+;
6770 * +count+ must be an
6771 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6774 * When +count+ is positive,
6775 * calls the block with each element, then does so repeatedly,
6776 * until it has done so +count+ times; returns +nil+:
6779 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6780 * output # => [0, 1, 0, 1]
6782 * When +count+ is zero or negative, does not call the block:
6784 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6785 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6787 * When +count+ is +nil+, cycles forever:
6789 * # Prints 0 and 1 forever.
6790 * [0, 1].cycle {|element| puts element }
6791 * [0, 1].cycle(nil) {|element| puts element }
6793 * With no block given, returns a new Enumerator.
6795 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6798 rb_ary_cycle(int argc
, VALUE
*argv
, VALUE ary
)
6802 rb_check_arity(argc
, 0, 1);
6804 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_cycle_size
);
6805 if (argc
== 0 || NIL_P(argv
[0])) {
6809 n
= NUM2LONG(argv
[0]);
6810 if (n
<= 0) return Qnil
;
6813 while (RARRAY_LEN(ary
) > 0 && (n
< 0 || 0 < n
--)) {
6814 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
6815 rb_yield(RARRAY_AREF(ary
, i
));
6822 * Build a ruby array of the corresponding values and yield it to the
6824 * Return the class of +values+ for reentry check.
6827 yield_indexed_values(const VALUE values
, const long r
, const long *const p
)
6829 const VALUE result
= rb_ary_new2(r
);
6832 for (i
= 0; i
< r
; i
++) ARY_SET(result
, i
, RARRAY_AREF(values
, p
[i
]));
6833 ARY_SET_LEN(result
, r
);
6835 return !RBASIC(values
)->klass
;
6839 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6841 * When we have a complete permutation of array indices, copy the values
6842 * at those indices into a new array and yield that array.
6844 * n: the size of the set
6845 * r: the number of elements in each permutation
6846 * p: the array (of size r) that we're filling in
6847 * used: an array of booleans: whether a given index is already used
6848 * values: the Ruby array that holds the actual values to permute
6851 permute0(const long n
, const long r
, long *const p
, char *const used
, const VALUE values
)
6853 long i
= 0, index
= 0;
6856 const char *const unused
= memchr(&used
[i
], 0, n
-i
);
6859 i
= p
[--index
]; /* pop index */
6860 used
[i
++] = 0; /* index unused */
6865 used
[i
] = 1; /* mark index used */
6867 if (index
< r
-1) { /* if not done yet */
6871 for (i
= 0; i
< n
; ++i
) {
6872 if (used
[i
]) continue;
6874 if (!yield_indexed_values(values
, r
, p
)) {
6875 rb_raise(rb_eRuntimeError
, "permute reentered");
6878 i
= p
[--index
]; /* pop index */
6879 used
[i
] = 0; /* index unused */
6886 * Returns the product of from, from-1, ..., from - how_many + 1.
6887 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6890 descending_factorial(long from
, long how_many
)
6894 cnt
= LONG2FIX(from
);
6895 while (--how_many
> 0) {
6897 cnt
= rb_int_mul(cnt
, LONG2FIX(v
));
6901 cnt
= LONG2FIX(how_many
== 0);
6907 binomial_coefficient(long comb
, long size
)
6911 if (comb
> size
-comb
) {
6917 else if (comb
== 0) {
6921 for (i
= 1; i
< comb
; ++i
) {
6922 r
= rb_int_mul(r
, LONG2FIX(size
- i
));
6923 r
= rb_int_idiv(r
, LONG2FIX(i
+ 1));
6929 rb_ary_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
6931 long n
= RARRAY_LEN(ary
);
6932 long k
= (args
&& (RARRAY_LEN(args
) > 0)) ? NUM2LONG(RARRAY_AREF(args
, 0)) : n
;
6934 return descending_factorial(n
, k
);
6939 * permutation(n = self.size) {|permutation| ... } -> self
6940 * permutation(n = self.size) -> new_enumerator
6942 * Iterates over permutations of the elements of +self+;
6943 * the order of permutations is indeterminate.
6945 * With a block and an in-range positive integer argument +n+ (<tt>0 < n <= self.size</tt>) given,
6946 * calls the block with each +n+-tuple permutations of +self+;
6951 * a.permutation(1) {|perm| perms.push(perm) }
6952 * perms # => [[0], [1], [2]]
6955 * a.permutation(2) {|perm| perms.push(perm) }
6956 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
6959 * a.permutation(3) {|perm| perms.push(perm) }
6960 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
6962 * When +n+ is zero, calls the block once with a new empty array:
6965 * a.permutation(0) {|perm| perms.push(perm) }
6968 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
6969 * does not call the block:
6971 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
6972 * a.permutation(4) {|permutation| fail 'Cannot happen' }
6974 * With no block given, returns a new Enumerator.
6976 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6980 rb_ary_permutation(int argc
, VALUE
*argv
, VALUE ary
)
6984 n
= RARRAY_LEN(ary
); /* Array length */
6985 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_permutation_size
); /* Return enumerator if no block */
6987 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0]))
6988 r
= NUM2LONG(argv
[0]); /* Permutation size from argument */
6990 if (r
< 0 || n
< r
) {
6991 /* no permutations: yield nothing */
6993 else if (r
== 0) { /* exactly one permutation: the zero-length array */
6994 rb_yield(rb_ary_new2(0));
6996 else if (r
== 1) { /* this is a special, easy case */
6997 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6998 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7001 else { /* this is the general case */
7003 long *p
= ALLOCV_N(long, t0
, r
+roomof(n
, sizeof(long)));
7004 char *used
= (char*)(p
+ r
);
7005 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7006 RBASIC_CLEAR_CLASS(ary0
);
7008 MEMZERO(used
, char, n
); /* initialize array */
7010 permute0(n
, r
, p
, used
, ary0
); /* compute and yield permutations */
7012 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7018 combinate0(const long len
, const long n
, long *const stack
, const VALUE values
)
7022 MEMZERO(stack
+1, long, n
);
7025 for (lev
++; lev
< n
; lev
++) {
7026 stack
[lev
+1] = stack
[lev
]+1;
7028 if (!yield_indexed_values(values
, n
, stack
+1)) {
7029 rb_raise(rb_eRuntimeError
, "combination reentered");
7032 if (lev
== 0) return;
7034 } while (stack
[lev
+1]+n
== len
+lev
+1);
7039 rb_ary_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7041 long n
= RARRAY_LEN(ary
);
7042 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7044 return binomial_coefficient(k
, n
);
7049 * combination(n) {|element| ... } -> self
7050 * combination(n) -> new_enumerator
7052 * When a block and a positive
7053 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7054 * argument +n+ (<tt>0 < n <= self.size</tt>)
7055 * are given, calls the block with all +n+-tuple combinations of +self+;
7058 * a = %w[a b c] # => ["a", "b", "c"]
7059 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7067 * The order of the yielded combinations is not guaranteed.
7069 * When +n+ is zero, calls the block once with a new empty array:
7071 * a.combination(0) {|combination| p combination }
7072 * [].combination(0) {|combination| p combination }
7079 * When +n+ is negative or larger than +self.size+ and +self+ is non-empty,
7080 * does not call the block:
7082 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7083 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7085 * With no block given, returns a new Enumerator.
7087 * Related: Array#permutation;
7088 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7092 rb_ary_combination(VALUE ary
, VALUE num
)
7097 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_combination_size
);
7098 len
= RARRAY_LEN(ary
);
7099 if (n
< 0 || len
< n
) {
7103 rb_yield(rb_ary_new2(0));
7106 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7107 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7111 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7113 long *stack
= ALLOCV_N(long, t0
, n
+1);
7115 RBASIC_CLEAR_CLASS(ary0
);
7116 combinate0(len
, n
, stack
, ary0
);
7118 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7124 * Compute repeated permutations of +r+ elements of the set
7125 * <code>[0..n-1]</code>.
7127 * When we have a complete repeated permutation of array indices, copy the
7128 * values at those indices into a new array and yield that array.
7130 * n: the size of the set
7131 * r: the number of elements in each permutation
7132 * p: the array (of size r) that we're filling in
7133 * values: the Ruby array that holds the actual values to permute
7136 rpermute0(const long n
, const long r
, long *const p
, const VALUE values
)
7138 long i
= 0, index
= 0;
7142 if (++index
< r
-1) {
7146 for (i
= 0; i
< n
; ++i
) {
7148 if (!yield_indexed_values(values
, r
, p
)) {
7149 rb_raise(rb_eRuntimeError
, "repeated permute reentered");
7153 if (index
<= 0) return;
7154 } while ((i
= ++p
[--index
]) >= n
);
7159 rb_ary_repeated_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
7161 long n
= RARRAY_LEN(ary
);
7162 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7168 return LONG2FIX(!k
);
7170 return rb_int_positive_pow(n
, (unsigned long)k
);
7175 * repeated_permutation(size) {|permutation| ... } -> self
7176 * repeated_permutation(size) -> new_enumerator
7178 * With a block given, calls the block with each repeated permutation of length +size+
7179 * of the elements of +self+;
7180 * each permutation is an array;
7181 * returns +self+. The order of the permutations is indeterminate.
7183 * If a positive integer argument +size+ is given,
7184 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7185 * The number of permutations is <tt>self.size**size</tt>.
7192 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7193 * p # => [[0], [1], [2]]
7198 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7199 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7201 * If +size+ is zero, calls the block once with an empty array.
7203 * If +size+ is negative, does not call the block:
7205 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7207 * With no block given, returns a new Enumerator.
7209 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7212 rb_ary_repeated_permutation(VALUE ary
, VALUE num
)
7216 n
= RARRAY_LEN(ary
); /* Array length */
7217 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_permutation_size
); /* Return Enumerator if no block */
7218 r
= NUM2LONG(num
); /* Permutation size from argument */
7221 /* no permutations: yield nothing */
7223 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7224 rb_yield(rb_ary_new2(0));
7226 else if (r
== 1) { /* this is a special, easy case */
7227 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7228 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7231 else { /* this is the general case */
7233 long *p
= ALLOCV_N(long, t0
, r
);
7234 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7235 RBASIC_CLEAR_CLASS(ary0
);
7237 rpermute0(n
, r
, p
, ary0
); /* compute and yield repeated permutations */
7239 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7245 rcombinate0(const long n
, const long r
, long *const p
, const long rest
, const VALUE values
)
7247 long i
= 0, index
= 0;
7251 if (++index
< r
-1) {
7255 for (; i
< n
; ++i
) {
7257 if (!yield_indexed_values(values
, r
, p
)) {
7258 rb_raise(rb_eRuntimeError
, "repeated combination reentered");
7262 if (index
<= 0) return;
7263 } while ((i
= ++p
[--index
]) >= n
);
7268 rb_ary_repeated_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7270 long n
= RARRAY_LEN(ary
);
7271 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7275 return binomial_coefficient(k
, n
+ k
- 1);
7280 * repeated_combination(size) {|combination| ... } -> self
7281 * repeated_combination(size) -> new_enumerator
7283 * With a block given, calls the block with each repeated combination of length +size+
7284 * of the elements of +self+;
7285 * each combination is an array;
7286 * returns +self+. The order of the combinations is indeterminate.
7288 * If a positive integer argument +size+ is given,
7289 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7290 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7297 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7298 * c # => [[0], [1], [2]]
7303 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7304 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7306 * If +size+ is zero, calls the block once with an empty array.
7308 * If +size+ is negative, does not call the block:
7310 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7312 * With no block given, returns a new Enumerator.
7314 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7318 rb_ary_repeated_combination(VALUE ary
, VALUE num
)
7322 n
= NUM2LONG(num
); /* Combination size from argument */
7323 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_combination_size
); /* Return enumerator if no block */
7324 len
= RARRAY_LEN(ary
);
7329 rb_yield(rb_ary_new2(0));
7332 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7333 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7336 else if (len
== 0) {
7341 long *p
= ALLOCV_N(long, t0
, n
);
7342 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7343 RBASIC_CLEAR_CLASS(ary0
);
7345 rcombinate0(len
, n
, p
, n
, ary0
); /* compute and yield repeated combinations */
7347 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7354 * product(*other_arrays) -> new_array
7355 * product(*other_arrays) {|combination| ... } -> self
7357 * Computes all combinations of elements from all the arrays,
7358 * including both +self+ and +other_arrays+:
7360 * - The number of combinations is the product of the sizes of all the arrays,
7361 * including both +self+ and +other_arrays+.
7362 * - The order of the returned combinations is indeterminate.
7364 * With no block given, returns the combinations as an array of arrays:
7366 * p = [0, 1].product([2, 3])
7367 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7369 * p = [0, 1].product([2, 3], [4, 5])
7370 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7373 * If +self+ or any argument is empty, returns an empty array:
7375 * [].product([2, 3], [4, 5]) # => []
7376 * [0, 1].product([2, 3], []) # => []
7378 * If no argument is given, returns an array of 1-element arrays,
7379 * each containing an element of +self+:
7381 * a.product # => [[0], [1], [2]]
7383 * With a block given, calls the block with each combination; returns +self+:
7386 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7387 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7389 * If +self+ or any argument is empty, does not call the block:
7391 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7393 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7396 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7399 * [0, 1].product {|combination| p.push(combination) }
7402 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7406 rb_ary_product(int argc
, VALUE
*argv
, VALUE ary
)
7408 int n
= argc
+1; /* How many arrays we're operating on */
7409 volatile VALUE t0
= rb_ary_hidden_new(n
);
7410 volatile VALUE t1
= Qundef
;
7411 VALUE
*arrays
= RARRAY_PTR(t0
); /* The arrays we're computing the product of */
7412 int *counters
= ALLOCV_N(int, t1
, n
); /* The current position in each one */
7413 VALUE result
= Qnil
; /* The array we'll be returning, when no block given */
7417 RBASIC_CLEAR_CLASS(t0
);
7419 /* initialize the arrays of arrays */
7422 for (i
= 1; i
< n
; i
++) arrays
[i
] = Qnil
;
7423 for (i
= 1; i
< n
; i
++) arrays
[i
] = to_ary(argv
[i
-1]);
7425 /* initialize the counters for the arrays */
7426 for (i
= 0; i
< n
; i
++) counters
[i
] = 0;
7428 /* Otherwise, allocate and fill in an array of results */
7429 if (rb_block_given_p()) {
7430 /* Make defensive copies of arrays; exit if any is empty */
7431 for (i
= 0; i
< n
; i
++) {
7432 if (RARRAY_LEN(arrays
[i
]) == 0) goto done
;
7433 arrays
[i
] = ary_make_shared_copy(arrays
[i
]);
7437 /* Compute the length of the result array; return [] if any is empty */
7438 for (i
= 0; i
< n
; i
++) {
7439 long k
= RARRAY_LEN(arrays
[i
]);
7441 result
= rb_ary_new2(0);
7444 if (MUL_OVERFLOW_LONG_P(resultlen
, k
))
7445 rb_raise(rb_eRangeError
, "too big to product");
7448 result
= rb_ary_new2(resultlen
);
7452 /* fill in one subarray */
7453 VALUE subarray
= rb_ary_new2(n
);
7454 for (j
= 0; j
< n
; j
++) {
7455 rb_ary_push(subarray
, rb_ary_entry(arrays
[j
], counters
[j
]));
7458 /* put it on the result array */
7459 if (NIL_P(result
)) {
7460 FL_SET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7462 if (!FL_TEST(t0
, RARRAY_SHARED_ROOT_FLAG
)) {
7463 rb_raise(rb_eRuntimeError
, "product reentered");
7466 FL_UNSET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7470 rb_ary_push(result
, subarray
);
7474 * Increment the last counter. If it overflows, reset to 0
7475 * and increment the one before it.
7479 while (counters
[m
] == RARRAY_LEN(arrays
[m
])) {
7481 /* If the first counter overflows, we are done */
7482 if (--m
< 0) goto done
;
7490 return NIL_P(result
) ? ary
: result
;
7495 * take(count) -> new_array
7497 * Returns a new array containing the first +count+ element of +self+
7499 * +count+ must be a non-negative numeric;
7500 * does not modify +self+:
7502 * a = ['a', 'b', 'c', 'd']
7503 * a.take(2) # => ["a", "b"]
7504 * a.take(2.1) # => ["a", "b"]
7505 * a.take(50) # => ["a", "b", "c", "d"]
7508 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7512 rb_ary_take(VALUE obj
, VALUE n
)
7514 long len
= NUM2LONG(n
);
7516 rb_raise(rb_eArgError
, "attempt to take negative size");
7518 return rb_ary_subseq(obj
, 0, len
);
7523 * take_while {|element| ... } -> new_array
7524 * take_while -> new_enumerator
7526 * With a block given, calls the block with each successive element of +self+;
7527 * stops iterating if the block returns +false+ or +nil+;
7528 * returns a new array containing those elements for which the block returned a truthy value:
7530 * a = [0, 1, 2, 3, 4, 5]
7531 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7532 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7533 * a.take_while {|element| false } # => []
7535 * With no block given, returns a new Enumerator.
7537 * Does not modify +self+.
7539 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7543 rb_ary_take_while(VALUE ary
)
7547 RETURN_ENUMERATOR(ary
, 0, 0);
7548 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7549 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7551 return rb_ary_take(ary
, LONG2FIX(i
));
7556 * drop(n) -> new_array
7558 * Returns a new array containing all but the first +n+ element of +self+,
7559 * where +n+ is a non-negative Integer;
7560 * does not modify +self+.
7564 * a = [0, 1, 2, 3, 4, 5]
7565 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7566 * a.drop(1) # => [1, 2, 3, 4, 5]
7567 * a.drop(2) # => [2, 3, 4, 5]
7570 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7574 rb_ary_drop(VALUE ary
, VALUE n
)
7577 long pos
= NUM2LONG(n
);
7579 rb_raise(rb_eArgError
, "attempt to drop negative size");
7582 result
= rb_ary_subseq(ary
, pos
, RARRAY_LEN(ary
));
7583 if (NIL_P(result
)) result
= rb_ary_new();
7589 * drop_while {|element| ... } -> new_array
7590 * drop_while -> new_enumerator
7592 * With a block given, calls the block with each successive element of +self+;
7593 * stops if the block returns +false+ or +nil+;
7594 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7595 * does not modify +self+:
7597 * a = [0, 1, 2, 3, 4, 5]
7598 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7600 * With no block given, returns a new Enumerator.
7602 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7606 rb_ary_drop_while(VALUE ary
)
7610 RETURN_ENUMERATOR(ary
, 0, 0);
7611 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7612 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7614 return rb_ary_drop(ary
, LONG2FIX(i
));
7619 * any? -> true or false
7620 * any?(object) -> true or false
7621 * any? {|element| ... } -> true or false
7623 * Returns whether for any element of +self+, a given criterion is satisfied.
7625 * With no block and no argument, returns whether any element of +self+ is truthy:
7627 * [nil, false, []].any? # => true # Array object is truthy.
7628 * [nil, false, {}].any? # => true # Hash object is truthy.
7629 * [nil, false, ''].any? # => true # String object is truthy.
7630 * [nil, false].any? # => false # Nil and false are not truthy.
7632 * With argument +object+ given,
7633 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7635 * [nil, false, 0].any?(0) # => true
7636 * [nil, false, 1].any?(0) # => false
7637 * [nil, false, 'food'].any?(/foo/) # => true
7638 * [nil, false, 'food'].any?(/bar/) # => false
7640 * With a block given,
7641 * calls the block with each element in +self+;
7642 * returns whether the block returns any truthy value:
7644 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7645 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7647 * With both a block and argument +object+ given,
7648 * ignores the block and uses +object+ as above.
7650 * <b>Special case</b>: returns +false+ if +self+ is empty
7651 * (regardless of any given argument or block).
7653 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7657 rb_ary_any_p(int argc
, VALUE
*argv
, VALUE ary
)
7659 long i
, len
= RARRAY_LEN(ary
);
7661 rb_check_arity(argc
, 0, 1);
7662 if (!len
) return Qfalse
;
7664 if (rb_block_given_p()) {
7665 rb_warn("given block not used");
7667 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7668 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qtrue
;
7671 else if (!rb_block_given_p()) {
7672 for (i
= 0; i
< len
; ++i
) {
7673 if (RTEST(RARRAY_AREF(ary
, i
))) return Qtrue
;
7677 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7678 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qtrue
;
7686 * all? -> true or false
7687 * all?(object) -> true or false
7688 * all? {|element| ... } -> true or false
7690 * Returns whether for every element of +self+,
7691 * a given criterion is satisfied.
7693 * With no block and no argument,
7694 * returns whether every element of +self+ is truthy:
7696 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7697 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7698 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7700 * With argument +object+ given, returns whether <tt>object === ele</tt>
7701 * for every element +ele+ in +self+:
7703 * [0, 0, 0].all?(0) # => true
7704 * [0, 1, 2].all?(1) # => false
7705 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7706 * ['food', 'drink'].all?(/foo/) # => false
7708 * With a block given, calls the block with each element in +self+;
7709 * returns whether the block returns only truthy values:
7711 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7712 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7714 * With both a block and argument +object+ given,
7715 * ignores the block and uses +object+ as above.
7717 * <b>Special case</b>: returns +true+ if +self+ is empty
7718 * (regardless of any given argument or block).
7720 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7724 rb_ary_all_p(int argc
, VALUE
*argv
, VALUE ary
)
7726 long i
, len
= RARRAY_LEN(ary
);
7728 rb_check_arity(argc
, 0, 1);
7729 if (!len
) return Qtrue
;
7731 if (rb_block_given_p()) {
7732 rb_warn("given block not used");
7734 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7735 if (!RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7738 else if (!rb_block_given_p()) {
7739 for (i
= 0; i
< len
; ++i
) {
7740 if (!RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7744 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7745 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7753 * none? -> true or false
7754 * none?(object) -> true or false
7755 * none? {|element| ... } -> true or false
7757 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
7759 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7760 * +false+ otherwise:
7762 * [nil, false].none? # => true
7763 * [nil, 0, false].none? # => false
7764 * [].none? # => true
7766 * With argument +object+ given, returns +false+ if for any element +element+,
7767 * <tt>object === element</tt>; +true+ otherwise:
7769 * ['food', 'drink'].none?(/bar/) # => true
7770 * ['food', 'drink'].none?(/foo/) # => false
7771 * [].none?(/foo/) # => true
7772 * [0, 1, 2].none?(3) # => true
7773 * [0, 1, 2].none?(1) # => false
7775 * With a block given, calls the block with each element in +self+;
7776 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7778 * [0, 1, 2].none? {|element| element > 3 } # => true
7779 * [0, 1, 2].none? {|element| element > 1 } # => false
7781 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7785 rb_ary_none_p(int argc
, VALUE
*argv
, VALUE ary
)
7787 long i
, len
= RARRAY_LEN(ary
);
7789 rb_check_arity(argc
, 0, 1);
7790 if (!len
) return Qtrue
;
7792 if (rb_block_given_p()) {
7793 rb_warn("given block not used");
7795 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7796 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7799 else if (!rb_block_given_p()) {
7800 for (i
= 0; i
< len
; ++i
) {
7801 if (RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7805 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7806 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7814 * one? -> true or false
7815 * one? {|element| ... } -> true or false
7816 * one?(object) -> true or false
7818 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7820 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7821 * +false+ otherwise:
7823 * [nil, 0].one? # => true
7824 * [0, 0].one? # => false
7825 * [nil, nil].one? # => false
7826 * [].one? # => false
7828 * With a block given, calls the block with each element in +self+;
7829 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7831 * [0, 1, 2].one? {|element| element > 0 } # => false
7832 * [0, 1, 2].one? {|element| element > 1 } # => true
7833 * [0, 1, 2].one? {|element| element > 2 } # => false
7835 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
7836 * +false+ otherwise:
7838 * [0, 1, 2].one?(0) # => true
7839 * [0, 0, 1].one?(0) # => false
7840 * [1, 1, 2].one?(0) # => false
7841 * ['food', 'drink'].one?(/bar/) # => false
7842 * ['food', 'drink'].one?(/foo/) # => true
7843 * [].one?(/foo/) # => false
7845 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7849 rb_ary_one_p(int argc
, VALUE
*argv
, VALUE ary
)
7851 long i
, len
= RARRAY_LEN(ary
);
7852 VALUE result
= Qfalse
;
7854 rb_check_arity(argc
, 0, 1);
7855 if (!len
) return Qfalse
;
7857 if (rb_block_given_p()) {
7858 rb_warn("given block not used");
7860 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7861 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) {
7862 if (result
) return Qfalse
;
7867 else if (!rb_block_given_p()) {
7868 for (i
= 0; i
< len
; ++i
) {
7869 if (RTEST(RARRAY_AREF(ary
, i
))) {
7870 if (result
) return Qfalse
;
7876 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7877 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
7878 if (result
) return Qfalse
;
7888 * array.dig(index, *identifiers) -> object
7890 * Finds and returns the object in nested object
7891 * specified by +index+ and +identifiers+;
7892 * the nested objects may be instances of various classes.
7893 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
7897 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
7898 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
7899 * a.dig(1, 2) # => [:bat, :bam]
7900 * a.dig(1, 2, 0) # => :bat
7901 * a.dig(1, 2, 3) # => nil
7903 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7907 rb_ary_dig(int argc
, VALUE
*argv
, VALUE self
)
7909 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
7910 self
= rb_ary_at(self
, *argv
);
7911 if (!--argc
) return self
;
7913 return rb_obj_dig(argc
, argv
, self
, Qnil
);
7917 finish_exact_sum(long n
, VALUE r
, VALUE v
, int z
)
7920 v
= rb_fix_plus(LONG2FIX(n
), v
);
7922 v
= rb_rational_plus(r
, v
);
7925 v
= rb_fix_plus(LONG2FIX(0), v
);
7932 * sum(init = 0) -> object
7933 * sum(init = 0) {|element| ... } -> object
7935 * With no block given, returns the sum of +init+ and all elements of +self+;
7936 * for array +array+ and value +init+, equivalent to:
7939 * array.each {|element| sum += element }
7942 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
7946 * [0, 1, 2, 3].sum # => 6
7947 * [0, 1, 2, 3].sum(100) # => 106
7948 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
7949 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
7950 * # => [2, 3, :foo, :bar, "foo", "bar"]
7952 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
7954 * # Raises TypeError: Array can't be coerced into Integer.
7955 * [[:foo, :bar], ['foo', 'bar']].sum(2)
7957 * With a block given, calls the block with each element of +self+;
7958 * the block's return value (instead of the element itself) is used as the addend:
7960 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
7961 * # => "Coerced and concatenated: zero1two"
7965 * - Array#join and Array#flatten may be faster than Array#sum
7966 * for an array of strings or an array of arrays.
7967 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
7972 rb_ary_sum(int argc
, VALUE
*argv
, VALUE ary
)
7978 v
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : LONG2FIX(0));
7980 block_given
= rb_block_given_p();
7982 if (RARRAY_LEN(ary
) == 0)
7988 if (!FIXNUM_P(v
) && !RB_BIGNUM_TYPE_P(v
) && !RB_TYPE_P(v
, T_RATIONAL
)) {
7990 goto init_is_a_value
;
7993 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7994 e
= RARRAY_AREF(ary
, i
);
7998 n
+= FIX2LONG(e
); /* should not overflow long type */
8000 v
= rb_big_plus(LONG2NUM(n
), v
);
8004 else if (RB_BIGNUM_TYPE_P(e
))
8005 v
= rb_big_plus(e
, v
);
8006 else if (RB_TYPE_P(e
, T_RATIONAL
)) {
8010 r
= rb_rational_plus(r
, e
);
8015 v
= finish_exact_sum(n
, r
, v
, argc
!=0);
8019 v
= finish_exact_sum(n
, r
, v
, i
!=0);
8021 if (RB_FLOAT_TYPE_P(e
)) {
8023 * Kahan-Babuska balancing compensated summation algorithm
8024 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8031 goto has_float_value
;
8032 for (; i
< RARRAY_LEN(ary
); i
++) {
8033 e
= RARRAY_AREF(ary
, i
);
8036 if (RB_FLOAT_TYPE_P(e
))
8038 x
= RFLOAT_VALUE(e
);
8039 else if (FIXNUM_P(e
))
8041 else if (RB_BIGNUM_TYPE_P(e
))
8043 else if (RB_TYPE_P(e
, T_RATIONAL
))
8048 if (isnan(f
)) continue;
8054 if (isinf(f
) && signbit(x
) != signbit(f
))
8060 if (isinf(f
)) continue;
8063 if (fabs(f
) >= fabs(x
))
8076 goto has_some_value
;
8078 for (; i
< RARRAY_LEN(ary
); i
++) {
8079 e
= RARRAY_AREF(ary
, i
);
8083 v
= rb_funcall(v
, idPLUS
, 1, e
);
8090 rb_ary_deconstruct(VALUE ary
)
8096 * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
8097 * Any object (even another array) may be an array element,
8098 * and an array can contain objects of different types.
8100 * == +Array+ Indexes
8102 * +Array+ indexing starts at 0, as in C or Java.
8104 * A positive index is an offset from the first element:
8106 * - Index 0 indicates the first element.
8107 * - Index 1 indicates the second element.
8110 * A negative index is an offset, backwards, from the end of the array:
8112 * - Index -1 indicates the last element.
8113 * - Index -2 indicates the next-to-last element.
8116 * A non-negative index is <i>in range</i> if and only if it is smaller than
8117 * the size of the array. For a 3-element array:
8119 * - Indexes 0 through 2 are in range.
8120 * - Index 3 is out of range.
8122 * A negative index is <i>in range</i> if and only if its absolute value is
8123 * not larger than the size of the array. For a 3-element array:
8125 * - Indexes -1 through -3 are in range.
8126 * - Index -4 is out of range.
8128 * Although the effective index into an array is always an integer,
8129 * some methods (both within and outside of class +Array+)
8130 * accept one or more non-integer arguments that are
8131 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8134 * == Creating Arrays
8136 * You can create an +Array+ object explicitly with:
8138 * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
8140 * [1, 'one', :one, [2, 'two', :two]]
8142 * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8144 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8145 * %w[1 % *] # => ["1", "%", "*"]
8147 * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8149 * %i[foo bar baz] # => [:foo, :bar, :baz]
8150 * %i[1 % *] # => [:"1", :%, :*]
8152 * - \Method Kernel#Array:
8154 * Array(["a", "b"]) # => ["a", "b"]
8155 * Array(1..5) # => [1, 2, 3, 4, 5]
8156 * Array(key: :value) # => [[:key, :value]]
8157 * Array(nil) # => []
8159 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8161 * - \Method Array.new:
8164 * Array.new(3) # => [nil, nil, nil]
8165 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8166 * Array.new(3, true) # => [true, true, true]
8168 * Note that the last example above populates the array
8169 * with references to the same object.
8170 * This is recommended only in cases where that object is a natively immutable object
8171 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8173 * Another way to create an array with various objects, using a block;
8174 * this usage is safe for mutable objects such as hashes, strings or
8177 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8179 * Here is a way to create a multi-dimensional array:
8181 * Array.new(3) {Array.new(3)}
8182 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8184 * A number of Ruby methods, both in the core and in the standard library,
8185 * provide instance method +to_a+, which converts an object to an array.
8193 * - OptionParser#to_a
8198 * - Benchmark::Tms#to_a
8200 * - Enumerator::Lazy#to_a
8202 * - Gem::NameTuple#to_a
8203 * - Gem::Platform#to_a
8204 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8205 * - Gem::SourceList#to_a
8206 * - OpenSSL::X509::Extension#to_a
8207 * - OpenSSL::X509::Name#to_a
8209 * - Rinda::RingFinger#to_a
8210 * - Ripper::Lexer::Elem#to_a
8211 * - RubyVM::InstructionSequence#to_a
8216 * In addition to the methods it mixes in through the Enumerable module, the
8217 * +Array+ class has proprietary methods for accessing, searching and otherwise
8218 * manipulating arrays.
8220 * Some of the more common ones are illustrated below.
8222 * == Accessing Elements
8224 * Elements in an array can be retrieved using the Array#[] method. It can
8225 * take a single integer argument (a numeric index), a pair of arguments
8226 * (start and length) or a range. Negative indices start counting from the end,
8227 * with -1 being the last element.
8229 * arr = [1, 2, 3, 4, 5, 6]
8233 * arr[2, 3] #=> [3, 4, 5]
8234 * arr[1..4] #=> [2, 3, 4, 5]
8235 * arr[1..-3] #=> [2, 3, 4]
8237 * Another way to access a particular array element is by using the #at method
8241 * The #slice method works in an identical manner to Array#[].
8243 * To raise an error for indices outside of the array bounds or else to
8244 * provide a default value when that happens, you can use #fetch.
8246 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8247 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8248 * arr.fetch(100, "oops") #=> "oops"
8250 * The special methods #first and #last will return the first and last
8251 * elements of an array, respectively.
8256 * To return the first +n+ elements of an array, use #take
8258 * arr.take(3) #=> [1, 2, 3]
8260 * #drop does the opposite of #take, by returning the elements after +n+
8261 * elements have been dropped:
8263 * arr.drop(3) #=> [4, 5, 6]
8265 * == Obtaining Information about an +Array+
8267 * Arrays keep track of their own length at all times. To query an array
8268 * about the number of elements it contains, use #length, #count or #size.
8270 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8271 * browsers.length #=> 5
8272 * browsers.count #=> 5
8274 * To check whether an array contains any elements at all
8276 * browsers.empty? #=> false
8278 * To check whether a particular item is included in the array
8280 * browsers.include?('Konqueror') #=> false
8282 * == Adding Items to Arrays
8284 * Items can be added to the end of an array by using either #push or #<<
8286 * arr = [1, 2, 3, 4]
8287 * arr.push(5) #=> [1, 2, 3, 4, 5]
8288 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8290 * #unshift will add a new item to the beginning of an array.
8292 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8294 * With #insert you can add a new element to an array at any position.
8296 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8298 * Using the #insert method, you can also insert multiple values at once:
8300 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8301 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8303 * == Removing Items from an +Array+
8305 * The method #pop removes the last element in an array and returns it:
8307 * arr = [1, 2, 3, 4, 5, 6]
8309 * arr #=> [1, 2, 3, 4, 5]
8311 * To retrieve and at the same time remove the first item, use #shift:
8314 * arr #=> [2, 3, 4, 5]
8316 * To delete an element at a particular index:
8318 * arr.delete_at(2) #=> 4
8321 * To delete a particular element anywhere in an array, use #delete:
8323 * arr = [1, 2, 2, 3]
8324 * arr.delete(2) #=> 2
8327 * A useful method if you need to remove +nil+ values from an array is
8330 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8331 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8332 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8333 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8334 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8336 * Another common need is to remove duplicate elements from an array.
8338 * It has the non-destructive #uniq, and destructive method #uniq!
8340 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8341 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8343 * == Iterating over Arrays
8345 * Like all classes that include the Enumerable module, +Array+ has an each
8346 * method, which defines what elements should be iterated over and how. In
8347 * case of Array's #each, all elements in the +Array+ instance are yielded to
8348 * the supplied block in sequence.
8350 * Note that this operation leaves the array unchanged.
8352 * arr = [1, 2, 3, 4, 5]
8353 * arr.each {|a| print a -= 10, " "}
8354 * # prints: -9 -8 -7 -6 -5
8355 * #=> [1, 2, 3, 4, 5]
8357 * Another sometimes useful iterator is #reverse_each which will iterate over
8358 * the elements in the array in reverse order.
8360 * words = %w[first second third fourth fifth sixth]
8362 * words.reverse_each {|word| str += "#{word} "}
8363 * p str #=> "sixth fifth fourth third second first "
8365 * The #map method can be used to create a new array based on the original
8366 * array, but with the values modified by the supplied block:
8368 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8369 * arr #=> [1, 2, 3, 4, 5]
8370 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8371 * arr #=> [1, 4, 9, 16, 25]
8374 * == Selecting Items from an +Array+
8376 * Elements can be selected from an array according to criteria defined in a
8377 * block. The selection can happen in a destructive or a non-destructive
8378 * manner. While the destructive operations will modify the array they were
8379 * called on, the non-destructive methods usually return a new array with the
8380 * selected elements, but leave the original array unchanged.
8382 * === Non-destructive Selection
8384 * arr = [1, 2, 3, 4, 5, 6]
8385 * arr.select {|a| a > 3} #=> [4, 5, 6]
8386 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8387 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8388 * arr #=> [1, 2, 3, 4, 5, 6]
8390 * === Destructive Selection
8392 * #select! and #reject! are the corresponding destructive methods to #select
8395 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8396 * opposite result when supplied with the same block:
8398 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8401 * arr = [1, 2, 3, 4, 5, 6]
8402 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8407 * First, what's elsewhere. \Class +Array+:
8409 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8410 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8411 * which provides dozens of additional methods.
8413 * Here, class +Array+ provides methods that are useful for:
8415 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8416 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8417 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8418 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8419 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8420 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8421 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8422 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8423 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8424 * - {And more....}[rdoc-ref:Array@Other+Methods]
8426 * === Methods for Creating an +Array+
8428 * - ::[]: Returns a new array populated with given objects.
8429 * - ::new: Returns a new array.
8430 * - ::try_convert: Returns a new array created from a given object.
8432 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8434 * === Methods for Querying
8436 * - #length (aliased as #size): Returns the count of elements.
8437 * - #include?: Returns whether any element <tt>==</tt> a given object.
8438 * - #empty?: Returns whether there are no elements.
8439 * - #all?: Returns whether all elements meet a given criterion.
8440 * - #any?: Returns whether any element meets a given criterion.
8441 * - #none?: Returns whether no element <tt>==</tt> a given object.
8442 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8443 * - #count: Returns the count of elements that meet a given criterion.
8444 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8445 * - #rindex: Returns the index of the last element that meets a given criterion.
8446 * - #hash: Returns the integer hash code.
8448 * === Methods for Comparing
8450 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or
8451 * greater than a given object.
8452 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
8453 * in a given object.
8454 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8455 * element in a given object.
8457 * === Methods for Fetching
8459 * These methods do not modify +self+.
8461 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8462 * - #fetch: Returns the element at a given offset.
8463 * - #fetch_values: Returns elements at given offsets.
8464 * - #first: Returns one or more leading elements.
8465 * - #last: Returns one or more trailing elements.
8466 * - #max: Returns one or more maximum-valued elements,
8467 * as determined by <tt>#<=></tt> or a given block.
8468 * - #min: Returns one or more minimum-valued elements,
8469 * as determined by <tt>#<=></tt> or a given block.
8470 * - #minmax: Returns the minimum-valued and maximum-valued elements,
8471 * as determined by <tt>#<=></tt> or a given block.
8472 * - #assoc: Returns the first element that is an array
8473 * whose first element <tt>==</tt> a given object.
8474 * - #rassoc: Returns the first element that is an array
8475 * whose second element <tt>==</tt> a given object.
8476 * - #at: Returns the element at a given offset.
8477 * - #values_at: Returns the elements at given offsets.
8478 * - #dig: Returns the object in nested objects
8479 * that is specified by a given index and additional arguments.
8480 * - #drop: Returns trailing elements as determined by a given index.
8481 * - #take: Returns leading elements as determined by a given index.
8482 * - #drop_while: Returns trailing elements as determined by a given block.
8483 * - #take_while: Returns leading elements as determined by a given block.
8484 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8485 * - #reverse: Returns all elements in reverse order.
8486 * - #compact: Returns an array containing all non-+nil+ elements.
8487 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8488 * - #uniq: Returns an array containing non-duplicate elements.
8489 * - #rotate: Returns all elements with some rotated from one end to the other.
8490 * - #bsearch: Returns an element selected via a binary search
8491 * as determined by a given block.
8492 * - #bsearch_index: Returns the index of an element selected via a binary search
8493 * as determined by a given block.
8494 * - #sample: Returns one or more random elements.
8495 * - #shuffle: Returns elements in a random order.
8496 * - #reject: Returns an array containing elements not rejected by a given block.
8498 * === Methods for Assigning
8500 * These methods add, replace, or reorder elements in +self+.
8502 * - #[]=: Assigns specified elements with a given object.
8503 * - #<<: Appends an element.
8504 * - #push (aliased as #append): Appends elements.
8505 * - #unshift (aliased as #prepend): Prepends leading elements.
8506 * - #insert: Inserts given objects at a given offset; does not replace elements.
8507 * - #concat: Appends all elements from given arrays.
8508 * - #fill: Replaces specified elements with specified objects.
8509 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8510 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8511 * - #reverse!: Replaces +self+ with its elements reversed.
8512 * - #rotate!: Replaces +self+ with its elements rotated.
8513 * - #shuffle!: Replaces +self+ with its elements in random order.
8514 * - #sort!: Replaces +self+ with its elements sorted,
8515 * as determined by <tt>#<=></tt> or a given block.
8516 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8518 * === Methods for Deleting
8520 * Each of these methods removes elements from +self+:
8522 * - #pop: Removes and returns the last element.
8523 * - #shift: Removes and returns the first element.
8524 * - #compact!: Removes all +nil+ elements.
8525 * - #delete: Removes elements equal to a given object.
8526 * - #delete_at: Removes the element at a given offset.
8527 * - #delete_if: Removes elements specified by a given block.
8528 * - #clear: Removes all elements.
8529 * - #keep_if: Removes elements not specified by a given block.
8530 * - #reject!: Removes elements specified by a given block.
8531 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8532 * - #slice!: Removes and returns a sequence of elements.
8533 * - #uniq!: Removes duplicates.
8535 * === Methods for Combining
8537 * - #&: Returns an array containing elements found both in +self+ and a given array.
8538 * - #intersection: Returns an array containing elements found both in +self+
8539 * and in each given array.
8540 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8541 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8542 * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
8543 * duplicates removed.
8544 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
8545 * duplicates removed.
8546 * - #difference: Returns an array containing all elements of +self+ that are not found
8547 * in any of the given arrays..
8548 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8549 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8551 * === Methods for Iterating
8553 * - #each: Passes each element to a given block.
8554 * - #reverse_each: Passes each element, in reverse order, to a given block.
8555 * - #each_index: Passes each element index to a given block.
8556 * - #cycle: Calls a given block with each element, then does so again,
8557 * for a specified number of times, or forever.
8558 * - #combination: Calls a given block with combinations of elements of +self+;
8559 * a combination does not use the same element more than once.
8560 * - #permutation: Calls a given block with permutations of elements of +self+;
8561 * a permutation does not use the same element more than once.
8562 * - #repeated_combination: Calls a given block with combinations of elements of +self+;
8563 * a combination may use the same element more than once.
8564 * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
8565 * a permutation may use the same element more than once.
8567 * === Methods for Converting
8569 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8570 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8571 * - #flatten: Returns an array that is a recursive flattening of +self+.
8572 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8573 * - #join: Returns a newsString containing the elements joined by the field separator.
8574 * - #to_a: Returns +self+ or a new array containing all elements.
8575 * - #to_ary: Returns +self+.
8576 * - #to_h: Returns a new hash formed from the elements.
8577 * - #transpose: Transposes +self+, which must be an array of arrays.
8578 * - #zip: Returns a new array of arrays containing +self+ and given arrays;
8579 * follow the link for details.
8583 * - #*: Returns one of the following:
8585 * - With integer argument +n+, a new array that is the concatenation
8586 * of +n+ copies of +self+.
8587 * - With string argument +field_separator+, a new string that is equivalent to
8588 * <tt>join(field_separator)</tt>.
8590 * - #pack: Packs the elements into a binary sequence.
8591 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8597 fake_ary_flags
= init_fake_ary_flags();
8599 rb_cArray
= rb_define_class("Array", rb_cObject
);
8600 rb_include_module(rb_cArray
, rb_mEnumerable
);
8602 rb_define_alloc_func(rb_cArray
, empty_ary_alloc
);
8603 rb_define_singleton_method(rb_cArray
, "new", rb_ary_s_new
, -1);
8604 rb_define_singleton_method(rb_cArray
, "[]", rb_ary_s_create
, -1);
8605 rb_define_singleton_method(rb_cArray
, "try_convert", rb_ary_s_try_convert
, 1);
8606 rb_define_method(rb_cArray
, "initialize", rb_ary_initialize
, -1);
8607 rb_define_method(rb_cArray
, "initialize_copy", rb_ary_replace
, 1);
8609 rb_define_method(rb_cArray
, "inspect", rb_ary_inspect
, 0);
8610 rb_define_alias(rb_cArray
, "to_s", "inspect");
8611 rb_define_method(rb_cArray
, "to_a", rb_ary_to_a
, 0);
8612 rb_define_method(rb_cArray
, "to_h", rb_ary_to_h
, 0);
8613 rb_define_method(rb_cArray
, "to_ary", rb_ary_to_ary_m
, 0);
8615 rb_define_method(rb_cArray
, "==", rb_ary_equal
, 1);
8616 rb_define_method(rb_cArray
, "eql?", rb_ary_eql
, 1);
8617 rb_define_method(rb_cArray
, "hash", rb_ary_hash
, 0);
8619 rb_define_method(rb_cArray
, "[]", rb_ary_aref
, -1);
8620 rb_define_method(rb_cArray
, "[]=", rb_ary_aset
, -1);
8621 rb_define_method(rb_cArray
, "at", rb_ary_at
, 1);
8622 rb_define_method(rb_cArray
, "fetch", rb_ary_fetch
, -1);
8623 rb_define_method(rb_cArray
, "concat", rb_ary_concat_multi
, -1);
8624 rb_define_method(rb_cArray
, "union", rb_ary_union_multi
, -1);
8625 rb_define_method(rb_cArray
, "difference", rb_ary_difference_multi
, -1);
8626 rb_define_method(rb_cArray
, "intersection", rb_ary_intersection_multi
, -1);
8627 rb_define_method(rb_cArray
, "intersect?", rb_ary_intersect_p
, 1);
8628 rb_define_method(rb_cArray
, "<<", rb_ary_push
, 1);
8629 rb_define_method(rb_cArray
, "push", rb_ary_push_m
, -1);
8630 rb_define_alias(rb_cArray
, "append", "push");
8631 rb_define_method(rb_cArray
, "pop", rb_ary_pop_m
, -1);
8632 rb_define_method(rb_cArray
, "shift", rb_ary_shift_m
, -1);
8633 rb_define_method(rb_cArray
, "unshift", rb_ary_unshift_m
, -1);
8634 rb_define_alias(rb_cArray
, "prepend", "unshift");
8635 rb_define_method(rb_cArray
, "insert", rb_ary_insert
, -1);
8636 rb_define_method(rb_cArray
, "each_index", rb_ary_each_index
, 0);
8637 rb_define_method(rb_cArray
, "reverse_each", rb_ary_reverse_each
, 0);
8638 rb_define_method(rb_cArray
, "length", rb_ary_length
, 0);
8639 rb_define_method(rb_cArray
, "size", rb_ary_length
, 0);
8640 rb_define_method(rb_cArray
, "empty?", rb_ary_empty_p
, 0);
8641 rb_define_method(rb_cArray
, "find_index", rb_ary_index
, -1);
8642 rb_define_method(rb_cArray
, "index", rb_ary_index
, -1);
8643 rb_define_method(rb_cArray
, "rindex", rb_ary_rindex
, -1);
8644 rb_define_method(rb_cArray
, "join", rb_ary_join_m
, -1);
8645 rb_define_method(rb_cArray
, "reverse", rb_ary_reverse_m
, 0);
8646 rb_define_method(rb_cArray
, "reverse!", rb_ary_reverse_bang
, 0);
8647 rb_define_method(rb_cArray
, "rotate", rb_ary_rotate_m
, -1);
8648 rb_define_method(rb_cArray
, "rotate!", rb_ary_rotate_bang
, -1);
8649 rb_define_method(rb_cArray
, "sort", rb_ary_sort
, 0);
8650 rb_define_method(rb_cArray
, "sort!", rb_ary_sort_bang
, 0);
8651 rb_define_method(rb_cArray
, "sort_by!", rb_ary_sort_by_bang
, 0);
8652 rb_define_method(rb_cArray
, "collect", rb_ary_collect
, 0);
8653 rb_define_method(rb_cArray
, "collect!", rb_ary_collect_bang
, 0);
8654 rb_define_method(rb_cArray
, "map", rb_ary_collect
, 0);
8655 rb_define_method(rb_cArray
, "map!", rb_ary_collect_bang
, 0);
8656 rb_define_method(rb_cArray
, "select", rb_ary_select
, 0);
8657 rb_define_method(rb_cArray
, "select!", rb_ary_select_bang
, 0);
8658 rb_define_method(rb_cArray
, "filter", rb_ary_select
, 0);
8659 rb_define_method(rb_cArray
, "filter!", rb_ary_select_bang
, 0);
8660 rb_define_method(rb_cArray
, "keep_if", rb_ary_keep_if
, 0);
8661 rb_define_method(rb_cArray
, "values_at", rb_ary_values_at
, -1);
8662 rb_define_method(rb_cArray
, "delete", rb_ary_delete
, 1);
8663 rb_define_method(rb_cArray
, "delete_at", rb_ary_delete_at_m
, 1);
8664 rb_define_method(rb_cArray
, "delete_if", rb_ary_delete_if
, 0);
8665 rb_define_method(rb_cArray
, "reject", rb_ary_reject
, 0);
8666 rb_define_method(rb_cArray
, "reject!", rb_ary_reject_bang
, 0);
8667 rb_define_method(rb_cArray
, "zip", rb_ary_zip
, -1);
8668 rb_define_method(rb_cArray
, "transpose", rb_ary_transpose
, 0);
8669 rb_define_method(rb_cArray
, "replace", rb_ary_replace
, 1);
8670 rb_define_method(rb_cArray
, "clear", rb_ary_clear
, 0);
8671 rb_define_method(rb_cArray
, "fill", rb_ary_fill
, -1);
8672 rb_define_method(rb_cArray
, "include?", rb_ary_includes
, 1);
8673 rb_define_method(rb_cArray
, "<=>", rb_ary_cmp
, 1);
8675 rb_define_method(rb_cArray
, "slice", rb_ary_aref
, -1);
8676 rb_define_method(rb_cArray
, "slice!", rb_ary_slice_bang
, -1);
8678 rb_define_method(rb_cArray
, "assoc", rb_ary_assoc
, 1);
8679 rb_define_method(rb_cArray
, "rassoc", rb_ary_rassoc
, 1);
8681 rb_define_method(rb_cArray
, "+", rb_ary_plus
, 1);
8682 rb_define_method(rb_cArray
, "*", rb_ary_times
, 1);
8684 rb_define_method(rb_cArray
, "-", rb_ary_diff
, 1);
8685 rb_define_method(rb_cArray
, "&", rb_ary_and
, 1);
8686 rb_define_method(rb_cArray
, "|", rb_ary_or
, 1);
8688 rb_define_method(rb_cArray
, "max", rb_ary_max
, -1);
8689 rb_define_method(rb_cArray
, "min", rb_ary_min
, -1);
8690 rb_define_method(rb_cArray
, "minmax", rb_ary_minmax
, 0);
8692 rb_define_method(rb_cArray
, "uniq", rb_ary_uniq
, 0);
8693 rb_define_method(rb_cArray
, "uniq!", rb_ary_uniq_bang
, 0);
8694 rb_define_method(rb_cArray
, "compact", rb_ary_compact
, 0);
8695 rb_define_method(rb_cArray
, "compact!", rb_ary_compact_bang
, 0);
8696 rb_define_method(rb_cArray
, "flatten", rb_ary_flatten
, -1);
8697 rb_define_method(rb_cArray
, "flatten!", rb_ary_flatten_bang
, -1);
8698 rb_define_method(rb_cArray
, "count", rb_ary_count
, -1);
8699 rb_define_method(rb_cArray
, "cycle", rb_ary_cycle
, -1);
8700 rb_define_method(rb_cArray
, "permutation", rb_ary_permutation
, -1);
8701 rb_define_method(rb_cArray
, "combination", rb_ary_combination
, 1);
8702 rb_define_method(rb_cArray
, "repeated_permutation", rb_ary_repeated_permutation
, 1);
8703 rb_define_method(rb_cArray
, "repeated_combination", rb_ary_repeated_combination
, 1);
8704 rb_define_method(rb_cArray
, "product", rb_ary_product
, -1);
8706 rb_define_method(rb_cArray
, "take", rb_ary_take
, 1);
8707 rb_define_method(rb_cArray
, "take_while", rb_ary_take_while
, 0);
8708 rb_define_method(rb_cArray
, "drop", rb_ary_drop
, 1);
8709 rb_define_method(rb_cArray
, "drop_while", rb_ary_drop_while
, 0);
8710 rb_define_method(rb_cArray
, "bsearch", rb_ary_bsearch
, 0);
8711 rb_define_method(rb_cArray
, "bsearch_index", rb_ary_bsearch_index
, 0);
8712 rb_define_method(rb_cArray
, "any?", rb_ary_any_p
, -1);
8713 rb_define_method(rb_cArray
, "all?", rb_ary_all_p
, -1);
8714 rb_define_method(rb_cArray
, "none?", rb_ary_none_p
, -1);
8715 rb_define_method(rb_cArray
, "one?", rb_ary_one_p
, -1);
8716 rb_define_method(rb_cArray
, "dig", rb_ary_dig
, -1);
8717 rb_define_method(rb_cArray
, "sum", rb_ary_sum
, -1);
8718 rb_define_method(rb_cArray
, "freeze", rb_ary_freeze
, 0);
8720 rb_define_method(rb_cArray
, "deconstruct", rb_ary_deconstruct
, 0);
8722 rb_cArray_empty_frozen
= rb_ary_freeze(rb_ary_new());
8723 rb_vm_register_global_object(rb_cArray_empty_frozen
);
8726 #include "array.rbinc"