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 * array.shift -> object or nil
1516 * array.shift(n) -> new_array
1518 * Removes and returns leading elements.
1520 * When no argument is given, removes and returns the first element:
1522 * a = [:foo, 'bar', 2]
1526 * Returns +nil+ if +self+ is empty.
1528 * When positive Integer argument +n+ is given, removes the first +n+ elements;
1529 * returns those elements in a new +Array+:
1531 * a = [:foo, 'bar', 2]
1532 * a.shift(2) # => [:foo, 'bar']
1535 * If +n+ is as large as or larger than <tt>self.length</tt>,
1536 * removes all elements; returns those elements in a new +Array+:
1538 * a = [:foo, 'bar', 2]
1539 * a.shift(3) # => [:foo, 'bar', 2]
1541 * If +n+ is zero, returns a new empty +Array+; +self+ is unmodified.
1543 * Related: #push, #pop, #unshift.
1547 rb_ary_shift_m(int argc
, VALUE
*argv
, VALUE ary
)
1553 return rb_ary_shift(ary
);
1556 rb_ary_modify_check(ary
);
1557 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1558 n
= RARRAY_LEN(result
);
1559 rb_ary_behead(ary
,n
);
1565 rb_ary_behead(VALUE ary
, long n
)
1571 rb_ary_modify_check(ary
);
1573 if (!ARY_SHARED_P(ary
)) {
1574 if (ARY_EMBED_P(ary
) || RARRAY_LEN(ary
) < ARY_DEFAULT_SIZE
) {
1575 RARRAY_PTR_USE(ary
, ptr
, {
1576 MEMMOVE(ptr
, ptr
+ n
, VALUE
, RARRAY_LEN(ary
) - n
);
1577 }); /* WB: no new reference */
1578 ARY_INCREASE_LEN(ary
, -n
);
1583 ary_mem_clear(ary
, 0, n
);
1584 ary_make_shared(ary
);
1586 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
))) {
1587 ary_mem_clear(ary
, 0, n
);
1590 ARY_INCREASE_PTR(ary
, n
);
1591 ARY_INCREASE_LEN(ary
, -n
);
1598 make_room_for_unshift(VALUE ary
, const VALUE
*head
, VALUE
*sharedp
, int argc
, long capa
, long len
)
1600 if (head
- sharedp
< argc
) {
1601 long room
= capa
- len
- argc
;
1604 MEMMOVE((VALUE
*)sharedp
+ argc
+ room
, head
, VALUE
, len
);
1605 head
= sharedp
+ argc
+ room
;
1607 ARY_SET_PTR(ary
, head
- argc
);
1608 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
)));
1611 return ARY_SHARED_ROOT(ary
);
1615 ary_modify_for_unshift(VALUE ary
, int argc
)
1617 long len
= RARRAY_LEN(ary
);
1618 long new_len
= len
+ argc
;
1620 const VALUE
*head
, *sharedp
;
1623 capa
= ARY_CAPA(ary
);
1624 if (capa
- (capa
>> 6) <= new_len
) {
1625 ary_double_capa(ary
, new_len
);
1628 /* use shared array for big "queues" */
1629 if (new_len
> ARY_DEFAULT_SIZE
* 4 && !ARY_EMBED_P(ary
)) {
1632 /* make a room for unshifted items */
1633 capa
= ARY_CAPA(ary
);
1634 ary_make_shared(ary
);
1636 head
= sharedp
= RARRAY_CONST_PTR(ary
);
1637 return make_room_for_unshift(ary
, head
, (void *)sharedp
, argc
, capa
, len
);
1641 RARRAY_PTR_USE(ary
, ptr
, {
1642 MEMMOVE(ptr
+ argc
, ptr
, VALUE
, len
);
1651 ary_ensure_room_for_unshift(VALUE ary
, int argc
)
1653 long len
= RARRAY_LEN(ary
);
1654 long new_len
= len
+ argc
;
1656 if (len
> ARY_MAX_SIZE
- argc
) {
1657 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
1659 else if (! ARY_SHARED_P(ary
)) {
1660 return ary_modify_for_unshift(ary
, argc
);
1663 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
1664 long capa
= RARRAY_LEN(shared_root
);
1666 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
1667 return ary_modify_for_unshift(ary
, argc
);
1669 else if (new_len
> capa
) {
1670 return ary_modify_for_unshift(ary
, argc
);
1673 const VALUE
* head
= RARRAY_CONST_PTR(ary
);
1674 void *sharedp
= (void *)RARRAY_CONST_PTR(shared_root
);
1676 rb_ary_modify_check(ary
);
1677 return make_room_for_unshift(ary
, head
, sharedp
, argc
, capa
, len
);
1684 * unshift(*objects) -> self
1685 * prepend(*objects) -> self
1687 * Prepends the given +objects+ to +self+:
1689 * a = [:foo, 'bar', 2]
1690 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1692 * Related: Array#shift;
1693 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1697 rb_ary_unshift_m(int argc
, VALUE
*argv
, VALUE ary
)
1699 long len
= RARRAY_LEN(ary
);
1703 rb_ary_modify_check(ary
);
1707 target_ary
= ary_ensure_room_for_unshift(ary
, argc
);
1708 ary_memcpy0(ary
, 0, argc
, argv
, target_ary
);
1709 ARY_SET_LEN(ary
, len
+ argc
);
1714 rb_ary_unshift(VALUE ary
, VALUE item
)
1716 return rb_ary_unshift_m(1, &item
, ary
);
1719 /* faster version - use this if you don't need to treat negative offset */
1721 rb_ary_elt(VALUE ary
, long offset
)
1723 long len
= RARRAY_LEN(ary
);
1724 if (len
== 0) return Qnil
;
1725 if (offset
< 0 || len
<= offset
) {
1728 return RARRAY_AREF(ary
, offset
);
1732 rb_ary_entry(VALUE ary
, long offset
)
1734 return rb_ary_entry_internal(ary
, offset
);
1738 rb_ary_subseq_step(VALUE ary
, long beg
, long len
, long step
)
1741 long alen
= RARRAY_LEN(ary
);
1743 if (beg
> alen
) return Qnil
;
1744 if (beg
< 0 || len
< 0) return Qnil
;
1746 if (alen
< len
|| alen
< beg
+ len
) {
1750 if (len
== 0) return ary_new(klass
, 0);
1752 rb_raise(rb_eArgError
, "slice step cannot be zero");
1754 return ary_make_partial(ary
, klass
, beg
, len
);
1756 return ary_make_partial_step(ary
, klass
, beg
, len
, step
);
1760 rb_ary_subseq(VALUE ary
, long beg
, long len
)
1762 return rb_ary_subseq_step(ary
, beg
, len
, 1);
1765 static VALUE
rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
);
1769 * self[index] -> object or nil
1770 * self[start, length] -> object or nil
1771 * self[range] -> object or nil
1772 * self[aseq] -> object or nil
1773 * slice(index) -> object or nil
1774 * slice(start, length) -> object or nil
1775 * slice(range) -> object or nil
1776 * slice(aseq) -> object or nil
1778 * Returns elements from +self+; does not modify +self+.
1782 * a = [:foo, 'bar', 2]
1784 * # Single argument index: returns one element.
1785 * a[0] # => :foo # Zero-based index.
1786 * a[-1] # => 2 # Negative index counts backwards from end.
1788 * # Arguments start and length: returns an array.
1789 * a[1, 2] # => ["bar", 2]
1790 * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end.
1792 * # Single argument range: returns an array.
1793 * a[0..1] # => [:foo, "bar"]
1794 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1795 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1797 * When a single integer argument +index+ is given, returns the element at offset +index+:
1799 * a = [:foo, 'bar', 2]
1802 * a # => [:foo, "bar", 2]
1804 * If +index+ is negative, counts backwards from the end of +self+:
1806 * a = [:foo, 'bar', 2]
1810 * If +index+ is out of range, returns +nil+.
1812 * When two Integer arguments +start+ and +length+ are given,
1813 * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
1815 * a = [:foo, 'bar', 2]
1816 * a[0, 2] # => [:foo, "bar"]
1817 * a[1, 2] # => ["bar", 2]
1819 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1820 * returns all elements from offset +start+ to the end:
1822 * a = [:foo, 'bar', 2]
1823 * a[0, 4] # => [:foo, "bar", 2]
1824 * a[1, 3] # => ["bar", 2]
1827 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1828 * returns a new empty +Array+.
1830 * If +length+ is negative, returns +nil+.
1832 * When a single Range argument +range+ is given,
1833 * treats <tt>range.min</tt> as +start+ above
1834 * and <tt>range.size</tt> as +length+ above:
1836 * a = [:foo, 'bar', 2]
1837 * a[0..1] # => [:foo, "bar"]
1838 * a[1..2] # => ["bar", 2]
1840 * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
1842 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1844 * a = [:foo, 'bar', 2]
1845 * a[0..-1] # => [:foo, "bar", 2]
1846 * a[0..-2] # => [:foo, "bar"]
1847 * a[0..-3] # => [:foo]
1849 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1851 * a = [:foo, 'bar', 2]
1853 * a[-2..2] # => ["bar", 2]
1854 * a[-3..2] # => [:foo, "bar", 2]
1856 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1858 * a = [:foo, 'bar', 2]
1863 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1864 * returns an +Array+ of elements corresponding to the indexes produced by
1867 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1868 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1870 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1871 * is larger than array size, throws RangeError.
1873 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1874 * a[(1..11).step(2)]
1875 * # RangeError (((1..11).step(2)) out of range)
1877 * # RangeError (((7..).step(2)) out of range)
1879 * If given a single argument, and its type is not one of the listed, tries to
1880 * convert it to Integer, and raises if it is impossible:
1882 * a = [:foo, 'bar', 2]
1883 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1886 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1890 rb_ary_aref(int argc
, const VALUE
*argv
, VALUE ary
)
1892 rb_check_arity(argc
, 1, 2);
1894 return rb_ary_aref2(ary
, argv
[0], argv
[1]);
1896 return rb_ary_aref1(ary
, argv
[0]);
1900 rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
)
1902 long beg
= NUM2LONG(b
);
1903 long len
= NUM2LONG(e
);
1905 beg
+= RARRAY_LEN(ary
);
1907 return rb_ary_subseq(ary
, beg
, len
);
1911 rb_ary_aref1(VALUE ary
, VALUE arg
)
1913 long beg
, len
, step
;
1915 /* special case - speeding up */
1916 if (FIXNUM_P(arg
)) {
1917 return rb_ary_entry(ary
, FIX2LONG(arg
));
1919 /* check if idx is Range or ArithmeticSequence */
1920 switch (rb_arithmetic_sequence_beg_len_step(arg
, &beg
, &len
, &step
, RARRAY_LEN(ary
), 0)) {
1926 return rb_ary_subseq_step(ary
, beg
, len
, step
);
1929 return rb_ary_entry(ary
, NUM2LONG(arg
));
1934 * at(index) -> object or nil
1936 * Returns the element of +self+ specified by the given +index+
1937 * or +nil+ if there is no such element;
1938 * +index+ must be an
1939 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1941 * For non-negative +index+, returns the element of +self+ at offset +index+:
1943 * a = [:foo, 'bar', 2]
1948 * For negative +index+, counts backwards from the end of +self+:
1950 * a.at(-2) # => "bar"
1952 * Related: Array#[];
1953 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1957 rb_ary_at(VALUE ary
, VALUE pos
)
1959 return rb_ary_entry(ary
, NUM2LONG(pos
));
1964 rb_ary_first(int argc
, VALUE
*argv
, VALUE ary
)
1967 if (RARRAY_LEN(ary
) == 0) return Qnil
;
1968 return RARRAY_AREF(ary
, 0);
1971 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1977 ary_first(VALUE self
)
1979 return (RARRAY_LEN(self
) == 0) ? Qnil
: RARRAY_AREF(self
, 0);
1983 ary_last(VALUE self
)
1985 long len
= RARRAY_LEN(self
);
1986 return (len
== 0) ? Qnil
: RARRAY_AREF(self
, len
-1);
1990 rb_ary_last(int argc
, const VALUE
*argv
, VALUE ary
) // used by parse.y
1993 return ary_last(ary
);
1996 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
2002 * fetch(index) -> element
2003 * fetch(index, default_value) -> element or default_value
2004 * fetch(index) {|index| ... } -> element or block_return_value
2006 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2007 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2009 * With the single argument +index+ and no block,
2010 * returns the element at offset +index+:
2012 * a = [:foo, 'bar', 2]
2013 * a.fetch(1) # => "bar"
2014 * a.fetch(1.1) # => "bar"
2016 * If +index+ is negative, counts from the end of the array:
2018 * a = [:foo, 'bar', 2]
2019 * a.fetch(-1) # => 2
2020 * a.fetch(-2) # => "bar"
2022 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2023 * returns +default_value+ if +index+ is out-of-range:
2025 * a = [:foo, 'bar', 2]
2026 * a.fetch(1, nil) # => "bar"
2027 * a.fetch(3, :foo) # => :foo
2029 * With argument +index+ and a block,
2030 * returns the element at offset +index+ if index is in range
2031 * (and the block is not called); otherwise calls the block with index and returns its return value:
2033 * a = [:foo, 'bar', 2]
2034 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2035 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2037 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2041 rb_ary_fetch(int argc
, VALUE
*argv
, VALUE ary
)
2047 rb_scan_args(argc
, argv
, "11", &pos
, &ifnone
);
2048 block_given
= rb_block_given_p();
2049 if (block_given
&& argc
== 2) {
2050 rb_warn("block supersedes default value argument");
2052 idx
= NUM2LONG(pos
);
2055 idx
+= RARRAY_LEN(ary
);
2057 if (idx
< 0 || RARRAY_LEN(ary
) <= idx
) {
2058 if (block_given
) return rb_yield(pos
);
2060 rb_raise(rb_eIndexError
, "index %ld outside of array bounds: %ld...%ld",
2061 idx
- (idx
< 0 ? RARRAY_LEN(ary
) : 0), -RARRAY_LEN(ary
), RARRAY_LEN(ary
));
2065 return RARRAY_AREF(ary
, idx
);
2070 * find_index(object) -> integer or nil
2071 * find_index {|element| ... } -> integer or nil
2072 * find_index -> new_enumerator
2073 * index(object) -> integer or nil
2074 * index {|element| ... } -> integer or nil
2075 * index -> new_enumerator
2077 * Returns the zero-based integer index of a specified element, or +nil+.
2079 * With only argument +object+ given,
2080 * returns the index of the first element +element+
2081 * for which <tt>object == element</tt>:
2083 * a = [:foo, 'bar', 2, 'bar']
2084 * a.index('bar') # => 1
2086 * Returns +nil+ if no such element found.
2088 * With only a block given,
2089 * calls the block with each successive element;
2090 * returns the index of the first element for which the block returns a truthy value:
2092 * a = [:foo, 'bar', 2, 'bar']
2093 * a.index {|element| element == 'bar' } # => 1
2095 * Returns +nil+ if the block never returns a truthy value.
2097 * With neither an argument nor a block given, returns a new Enumerator.
2099 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2103 rb_ary_index(int argc
, VALUE
*argv
, VALUE ary
)
2109 RETURN_ENUMERATOR(ary
, 0, 0);
2110 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2111 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
2117 rb_check_arity(argc
, 0, 1);
2119 if (rb_block_given_p())
2120 rb_warn("given block not used");
2121 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2122 VALUE e
= RARRAY_AREF(ary
, i
);
2123 if (rb_equal(e
, val
)) {
2132 * rindex(object) -> integer or nil
2133 * rindex {|element| ... } -> integer or nil
2134 * rindex -> new_enumerator
2136 * Returns the index of the last element for which <tt>object == element</tt>.
2138 * With argument +object+ given, returns the index of the last such element found:
2140 * a = [:foo, 'bar', 2, 'bar']
2141 * a.rindex('bar') # => 3
2143 * Returns +nil+ if no such object found.
2145 * With a block given, calls the block with each successive element;
2146 * returns the index of the last element for which the block returns a truthy value:
2148 * a = [:foo, 'bar', 2, 'bar']
2149 * a.rindex {|element| element == 'bar' } # => 3
2151 * Returns +nil+ if the block never returns a truthy value.
2153 * When neither an argument nor a block is given, returns a new Enumerator.
2155 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2159 rb_ary_rindex(int argc
, VALUE
*argv
, VALUE ary
)
2162 long i
= RARRAY_LEN(ary
), len
;
2165 RETURN_ENUMERATOR(ary
, 0, 0);
2167 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
))))
2169 if (i
> (len
= RARRAY_LEN(ary
))) {
2175 rb_check_arity(argc
, 0, 1);
2177 if (rb_block_given_p())
2178 rb_warn("given block not used");
2180 VALUE e
= RARRAY_AREF(ary
, i
);
2181 if (rb_equal(e
, val
)) {
2184 if (i
> RARRAY_LEN(ary
)) {
2192 rb_ary_to_ary(VALUE obj
)
2194 VALUE tmp
= rb_check_array_type(obj
);
2196 if (!NIL_P(tmp
)) return tmp
;
2197 return rb_ary_new3(1, obj
);
2201 rb_ary_splice(VALUE ary
, long beg
, long len
, const VALUE
*rptr
, long rlen
)
2206 if (len
< 0) rb_raise(rb_eIndexError
, "negative length (%ld)", len
);
2207 olen
= RARRAY_LEN(ary
);
2211 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2215 if (olen
< len
|| olen
< beg
+ len
) {
2220 const VALUE
*optr
= RARRAY_CONST_PTR(ary
);
2221 rofs
= (rptr
>= optr
&& rptr
< optr
+ olen
) ? rptr
- optr
: -1;
2226 if (beg
> ARY_MAX_SIZE
- rlen
) {
2227 rb_raise(rb_eIndexError
, "index %ld too big", beg
);
2229 target_ary
= ary_ensure_room_for_push(ary
, rlen
-len
); /* len is 0 or negative */
2231 ary_mem_clear(ary
, olen
, beg
- olen
);
2233 if (rofs
!= -1) rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2234 ary_memcpy0(ary
, beg
, rlen
, rptr
, target_ary
);
2236 ARY_SET_LEN(ary
, len
);
2241 if (olen
- len
> ARY_MAX_SIZE
- rlen
) {
2242 rb_raise(rb_eIndexError
, "index %ld too big", olen
+ rlen
- len
);
2245 alen
= olen
+ rlen
- len
;
2246 if (alen
>= ARY_CAPA(ary
)) {
2247 ary_double_capa(ary
, alen
);
2251 RARRAY_PTR_USE(ary
, ptr
,
2252 MEMMOVE(ptr
+ beg
+ rlen
, ptr
+ beg
+ len
,
2253 VALUE
, olen
- (beg
+ len
)));
2254 ARY_SET_LEN(ary
, alen
);
2258 rb_gc_writebarrier_remember(ary
);
2261 /* In this case, we're copying from a region in this array, so
2262 * we don't need to fire the write barrier. */
2263 rptr
= RARRAY_CONST_PTR(ary
) + rofs
;
2266 /* do not use RARRAY_PTR() because it can causes GC.
2267 * ary can contain T_NONE object because it is not cleared.
2269 RARRAY_PTR_USE(ary
, ptr
,
2270 MEMMOVE(ptr
+ beg
, rptr
, VALUE
, rlen
));
2276 rb_ary_set_len(VALUE ary
, long len
)
2280 rb_ary_modify_check(ary
);
2281 if (ARY_SHARED_P(ary
)) {
2282 rb_raise(rb_eRuntimeError
, "can't set length of shared ");
2284 if (len
> (capa
= (long)ARY_CAPA(ary
))) {
2285 rb_bug("probable buffer overflow: %ld for %ld", len
, capa
);
2287 ARY_SET_LEN(ary
, len
);
2291 rb_ary_resize(VALUE ary
, long len
)
2296 olen
= RARRAY_LEN(ary
);
2297 if (len
== olen
) return ary
;
2298 if (len
> ARY_MAX_SIZE
) {
2299 rb_raise(rb_eIndexError
, "index %ld too big", len
);
2302 if (len
>= ARY_CAPA(ary
)) {
2303 ary_double_capa(ary
, len
);
2305 ary_mem_clear(ary
, olen
, len
- olen
);
2306 ARY_SET_LEN(ary
, len
);
2308 else if (ARY_EMBED_P(ary
)) {
2309 ARY_SET_EMBED_LEN(ary
, len
);
2311 else if (len
<= ary_embed_capa(ary
)) {
2312 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
2313 long ptr_capa
= ARY_HEAP_SIZE(ary
);
2314 bool is_malloc_ptr
= !ARY_SHARED_P(ary
);
2318 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
); /* WB: no new reference */
2319 ARY_SET_EMBED_LEN(ary
, len
);
2321 if (is_malloc_ptr
) ruby_sized_xfree((void *)ptr
, ptr_capa
);
2324 if (olen
> len
+ ARY_DEFAULT_SIZE
) {
2325 size_t new_capa
= ary_heap_realloc(ary
, len
);
2326 ARY_SET_CAPA(ary
, new_capa
);
2328 ARY_SET_HEAP_LEN(ary
, len
);
2335 ary_aset_by_rb_ary_store(VALUE ary
, long key
, VALUE val
)
2337 rb_ary_store(ary
, key
, val
);
2342 ary_aset_by_rb_ary_splice(VALUE ary
, long beg
, long len
, VALUE val
)
2344 VALUE rpl
= rb_ary_to_ary(val
);
2345 rb_ary_splice(ary
, beg
, len
, RARRAY_CONST_PTR(rpl
), RARRAY_LEN(rpl
));
2352 * self[index] = object -> object
2353 * self[start, length] = object -> object
2354 * self[range] = object -> object
2356 * Assigns elements in +self+, based on the given +object+; returns +object+.
2360 * a_orig = [:foo, 'bar', 2]
2362 * # With argument index.
2364 * a[0] = 'foo' # => "foo"
2365 * a # => ["foo", "bar", 2]
2367 * a[7] = 'foo' # => "foo"
2368 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2370 * # With arguments start and length.
2372 * a[0, 2] = 'foo' # => "foo"
2375 * a[6, 50] = 'foo' # => "foo"
2376 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2378 * # With argument range.
2380 * a[0..1] = 'foo' # => "foo"
2383 * a[6..50] = 'foo' # => "foo"
2384 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2386 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2388 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2390 * a = [:foo, 'bar', 2]
2391 * a[0] = 'foo' # => "foo"
2392 * a # => ["foo", "bar", 2]
2394 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2396 * a = [:foo, 'bar', 2]
2397 * a[7] = 'foo' # => "foo"
2398 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2400 * If +index+ is negative, counts backwards from the end of the array:
2402 * a = [:foo, 'bar', 2]
2403 * a[-1] = 'two' # => "two"
2404 * a # => [:foo, "bar", "two"]
2406 * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
2407 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2408 * and assigns +object+ at offset +start+:
2410 * a = [:foo, 'bar', 2]
2411 * a[0, 2] = 'foo' # => "foo"
2414 * If +start+ is negative, counts backwards from the end of the array:
2416 * a = [:foo, 'bar', 2]
2417 * a[-2, 2] = 'foo' # => "foo"
2418 * a # => [:foo, "foo"]
2420 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2421 * extends the array with +nil+, assigns +object+ at offset +start+,
2422 * and ignores +length+:
2424 * a = [:foo, 'bar', 2]
2425 * a[6, 50] = 'foo' # => "foo"
2426 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2428 * If +length+ is zero, shifts elements at and following offset +start+
2429 * and assigns +object+ at offset +start+:
2431 * a = [:foo, 'bar', 2]
2432 * a[1, 0] = 'foo' # => "foo"
2433 * a # => [:foo, "foo", "bar", 2]
2435 * If +length+ is too large for the existing array, does not extend the array:
2437 * a = [:foo, 'bar', 2]
2438 * a[1, 5] = 'foo' # => "foo"
2439 * a # => [:foo, "foo"]
2441 * When Range argument +range+ is given and +object+ is not an +Array+,
2442 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2443 * and assigns +object+ at offset +start+:
2445 * a = [:foo, 'bar', 2]
2446 * a[0..1] = 'foo' # => "foo"
2449 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2451 * a = [:foo, 'bar', 2]
2452 * a[-2..2] = 'foo' # => "foo"
2453 * a # => [:foo, "foo"]
2455 * If the array length is less than <tt>range.begin</tt>,
2456 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2457 * and ignores +length+:
2459 * a = [:foo, 'bar', 2]
2460 * a[6..50] = 'foo' # => "foo"
2461 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2463 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2464 * and assigns +object+ at offset +start+:
2466 * a = [:foo, 'bar', 2]
2467 * a[1..0] = 'foo' # => "foo"
2468 * a # => [:foo, "foo", "bar", 2]
2470 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2471 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2473 * a = [:foo, 'bar', 2]
2474 * a[1..-1] = 'foo' # => "foo"
2475 * a # => [:foo, "foo"]
2476 * a = [:foo, 'bar', 2]
2477 * a[1..-2] = 'foo' # => "foo"
2478 * a # => [:foo, "foo", 2]
2479 * a = [:foo, 'bar', 2]
2480 * a[1..-3] = 'foo' # => "foo"
2481 * a # => [:foo, "foo", "bar", 2]
2482 * a = [:foo, 'bar', 2]
2484 * If <tt>range.end</tt> is too large for the existing array,
2485 * replaces array elements, but does not extend the array with +nil+ values:
2487 * a = [:foo, 'bar', 2]
2488 * a[1..5] = 'foo' # => "foo"
2489 * a # => [:foo, "foo"]
2491 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2495 rb_ary_aset(int argc
, VALUE
*argv
, VALUE ary
)
2497 long offset
, beg
, len
;
2499 rb_check_arity(argc
, 2, 3);
2500 rb_ary_modify_check(ary
);
2502 beg
= NUM2LONG(argv
[0]);
2503 len
= NUM2LONG(argv
[1]);
2504 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[2]);
2506 if (FIXNUM_P(argv
[0])) {
2507 offset
= FIX2LONG(argv
[0]);
2508 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2510 if (rb_range_beg_len(argv
[0], &beg
, &len
, RARRAY_LEN(ary
), 1)) {
2511 /* check if idx is Range */
2512 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[1]);
2515 offset
= NUM2LONG(argv
[0]);
2516 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2521 * insert(index, *objects) -> self
2523 * Inserts the given +objects+ as elements of +self+;
2526 * When +index+ is non-negative, inserts +objects+
2527 * _before_ the element at offset +index+:
2529 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2530 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2532 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2534 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2535 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2537 * When +index+ is negative, inserts +objects+
2538 * _after_ the element at offset <tt>index + self.size</tt>:
2540 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2541 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2543 * With no +objects+ given, does nothing:
2545 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2546 * a.insert(1) # => ["a", "b", "c"]
2547 * a.insert(50) # => ["a", "b", "c"]
2548 * a.insert(-50) # => ["a", "b", "c"]
2550 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2552 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2556 rb_ary_insert(int argc
, VALUE
*argv
, VALUE ary
)
2560 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2561 rb_ary_modify_check(ary
);
2562 pos
= NUM2LONG(argv
[0]);
2563 if (argc
== 1) return ary
;
2565 pos
= RARRAY_LEN(ary
);
2568 long minpos
= -RARRAY_LEN(ary
) - 1;
2570 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2575 rb_ary_splice(ary
, pos
, 0, argv
+ 1, argc
- 1);
2580 rb_ary_length(VALUE ary
);
2583 ary_enum_length(VALUE ary
, VALUE args
, VALUE eobj
)
2585 return rb_ary_length(ary
);
2588 // Primitive to avoid a race condition in Array#each.
2589 // Return `true` and write `value` and `index` if the element exists.
2591 ary_fetch_next(VALUE self
, VALUE
*index
, VALUE
*value
)
2593 long i
= NUM2LONG(*index
);
2594 if (i
>= RARRAY_LEN(self
)) {
2597 *value
= RARRAY_AREF(self
, i
);
2598 *index
= LONG2NUM(i
+ 1);
2603 rb_ary_each(VALUE ary
)
2607 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2608 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2609 rb_yield(RARRAY_AREF(ary
, i
));
2616 * each_index {|index| ... } -> self
2617 * each_index -> new_enumerator
2619 * With a block given, iterates over the elements of +self+,
2620 * passing each <i>array index</i> to the block;
2623 * a = [:foo, 'bar', 2]
2624 * a.each_index {|index| puts "#{index} #{a[index]}" }
2632 * Allows the array to be modified during iteration:
2634 * a = [:foo, 'bar', 2]
2635 * a.each_index {|index| puts index; a.clear if index > 0 }
2642 * With no block given, returns a new Enumerator.
2644 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2648 rb_ary_each_index(VALUE ary
)
2651 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2653 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2654 rb_yield(LONG2NUM(i
));
2661 * array.reverse_each {|element| ... } -> self
2662 * array.reverse_each -> Enumerator
2664 * Iterates backwards over array elements.
2666 * When a block given, passes, in reverse order, each element to the block;
2669 * a = [:foo, 'bar', 2]
2670 * a.reverse_each {|element| puts "#{element.class} #{element}" }
2678 * Allows the array to be modified during iteration:
2680 * a = [:foo, 'bar', 2]
2681 * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2688 * When no block given, returns a new Enumerator:
2690 * a = [:foo, 'bar', 2]
2691 * e = a.reverse_each
2692 * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
2693 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2701 * Related: #each, #each_index.
2705 rb_ary_reverse_each(VALUE ary
)
2709 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2710 len
= RARRAY_LEN(ary
);
2713 rb_yield(RARRAY_AREF(ary
, len
));
2714 nlen
= RARRAY_LEN(ary
);
2727 * Returns the count of elements in +self+:
2729 * [0, 1, 2].length # => 3
2732 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2736 rb_ary_length(VALUE ary
)
2738 long len
= RARRAY_LEN(ary
);
2739 return LONG2NUM(len
);
2744 * array.empty? -> true or false
2746 * Returns +true+ if the count of elements in +self+ is zero,
2747 * +false+ otherwise.
2749 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2753 rb_ary_empty_p(VALUE ary
)
2755 return RBOOL(RARRAY_LEN(ary
) == 0);
2759 rb_ary_dup(VALUE ary
)
2761 long len
= RARRAY_LEN(ary
);
2762 VALUE dup
= rb_ary_new2(len
);
2763 ary_memcpy(dup
, 0, len
, RARRAY_CONST_PTR(ary
));
2764 ARY_SET_LEN(dup
, len
);
2772 rb_ary_resurrect(VALUE ary
)
2774 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
2777 extern VALUE rb_output_fs
;
2779 static void ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
);
2782 recursive_join(VALUE obj
, VALUE argp
, int recur
)
2784 VALUE
*arg
= (VALUE
*)argp
;
2787 VALUE result
= arg
[2];
2788 int *first
= (int *)arg
[3];
2791 rb_raise(rb_eArgError
, "recursive array join");
2794 ary_join_1(obj
, ary
, sep
, 0, result
, first
);
2800 ary_join_0(VALUE ary
, VALUE sep
, long max
, VALUE result
)
2805 if (max
> 0) rb_enc_copy(result
, RARRAY_AREF(ary
, 0));
2806 for (i
=0; i
<max
; i
++) {
2807 val
= RARRAY_AREF(ary
, i
);
2808 if (!RB_TYPE_P(val
, T_STRING
)) break;
2809 if (i
> 0 && !NIL_P(sep
))
2810 rb_str_buf_append(result
, sep
);
2811 rb_str_buf_append(result
, val
);
2817 ary_join_1_str(VALUE dst
, VALUE src
, int *first
)
2819 rb_str_buf_append(dst
, src
);
2821 rb_enc_copy(dst
, src
);
2827 ary_join_1_ary(VALUE obj
, VALUE ary
, VALUE sep
, VALUE result
, VALUE val
, int *first
)
2830 rb_raise(rb_eArgError
, "recursive array join");
2839 args
[3] = (VALUE
)first
;
2840 rb_exec_recursive(recursive_join
, obj
, (VALUE
)args
);
2845 ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
)
2849 for (; i
<RARRAY_LEN(ary
); i
++) {
2850 if (i
> 0 && !NIL_P(sep
))
2851 rb_str_buf_append(result
, sep
);
2853 val
= RARRAY_AREF(ary
, i
);
2854 if (RB_TYPE_P(val
, T_STRING
)) {
2855 ary_join_1_str(result
, val
, first
);
2857 else if (RB_TYPE_P(val
, T_ARRAY
)) {
2858 ary_join_1_ary(val
, ary
, sep
, result
, val
, first
);
2860 else if (!NIL_P(tmp
= rb_check_string_type(val
))) {
2861 ary_join_1_str(result
, tmp
, first
);
2863 else if (!NIL_P(tmp
= rb_check_array_type(val
))) {
2864 ary_join_1_ary(val
, ary
, sep
, result
, tmp
, first
);
2867 ary_join_1_str(result
, rb_obj_as_string(val
), first
);
2873 rb_ary_join(VALUE ary
, VALUE sep
)
2876 VALUE val
, tmp
, result
;
2878 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new(0, 0);
2882 len
+= RSTRING_LEN(sep
) * (RARRAY_LEN(ary
) - 1);
2884 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2885 val
= RARRAY_AREF(ary
, i
);
2886 tmp
= rb_check_string_type(val
);
2888 if (NIL_P(tmp
) || tmp
!= val
) {
2890 long n
= RARRAY_LEN(ary
);
2892 result
= rb_str_buf_new(len
+ (n
-i
)*10);
2893 rb_enc_associate(result
, rb_usascii_encoding());
2894 i
= ary_join_0(ary
, sep
, i
, result
);
2896 ary_join_1(ary
, ary
, sep
, i
, result
, &first
);
2900 len
+= RSTRING_LEN(tmp
);
2903 result
= rb_str_new(0, len
);
2904 rb_str_set_len(result
, 0);
2906 ary_join_0(ary
, sep
, RARRAY_LEN(ary
), result
);
2913 * array.join(separator = $,) -> new_string
2915 * Returns the new string formed by joining the converted elements of +self+;
2916 * for each element +element+:
2918 * - Converts recursively using <tt>element.join(separator)</tt>
2919 * if +element+ is a <tt>kind_of?(Array)</tt>.
2920 * - Otherwise, converts using <tt>element.to_s</tt>.
2922 * With no argument given, joins using the output field separator, <tt>$,</tt>:
2924 * a = [:foo, 'bar', 2]
2926 * a.join # => "foobar2"
2928 * With string argument +separator+ given, joins using that separator:
2930 * a = [:foo, 'bar', 2]
2931 * a.join("\n") # => "foo\nbar\n2"
2933 * Joins recursively for nested arrays:
2935 * a = [:foo, [:bar, [:baz, :bat]]]
2936 * a.join # => "foobarbazbat"
2938 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
2941 rb_ary_join_m(int argc
, VALUE
*argv
, VALUE ary
)
2945 if (rb_check_arity(argc
, 0, 1) == 0 || NIL_P(sep
= argv
[0])) {
2948 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
2952 return rb_ary_join(ary
, sep
);
2956 inspect_ary(VALUE ary
, VALUE dummy
, int recur
)
2961 if (recur
) return rb_usascii_str_new_cstr("[...]");
2962 str
= rb_str_buf_new2("[");
2963 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2964 s
= rb_inspect(RARRAY_AREF(ary
, i
));
2965 if (i
> 0) rb_str_buf_cat2(str
, ", ");
2966 else rb_enc_copy(str
, s
);
2967 rb_str_buf_append(str
, s
);
2969 rb_str_buf_cat2(str
, "]");
2975 * inspect -> new_string
2977 * Returns the new string formed by calling method <tt>#inspect</tt>
2978 * on each array element:
2980 * a = [:foo, 'bar', 2]
2981 * a.inspect # => "[:foo, \"bar\", 2]"
2983 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2987 rb_ary_inspect(VALUE ary
)
2989 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new2("[]");
2990 return rb_exec_recursive(inspect_ary
, ary
, 0);
2994 rb_ary_to_s(VALUE ary
)
2996 return rb_ary_inspect(ary
);
3001 * to_a -> self or new_array
3003 * When +self+ is an instance of +Array+, returns +self+:
3005 * a = [:foo, 'bar', 2]
3006 * a.to_a # => [:foo, "bar", 2]
3008 * Otherwise, returns a new +Array+ containing the elements of +self+:
3010 * class MyArray < Array; end
3011 * a = MyArray.new(['foo', 'bar', 'two'])
3012 * a.instance_of?(Array) # => false
3013 * a.kind_of?(Array) # => true
3015 * a1 # => ["foo", "bar", "two"]
3016 * a1.class # => Array # Not MyArray
3021 rb_ary_to_a(VALUE ary
)
3023 if (rb_obj_class(ary
) != rb_cArray
) {
3024 VALUE dup
= rb_ary_new2(RARRAY_LEN(ary
));
3025 rb_ary_replace(dup
, ary
);
3033 * array.to_h -> new_hash
3034 * array.to_h {|item| ... } -> new_hash
3036 * Returns a new Hash formed from +self+.
3038 * When a block is given, calls the block with each array element;
3039 * the block must return a 2-element +Array+ whose two elements
3040 * form a key-value pair in the returned Hash:
3042 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3043 * h = a.to_h {|item| [item, item] }
3044 * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
3046 * When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
3047 * each sub-array is formed into a key-value pair in the new Hash:
3050 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3052 * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
3057 rb_ary_to_h(VALUE ary
)
3060 VALUE hash
= rb_hash_new_with_size(RARRAY_LEN(ary
));
3061 int block_given
= rb_block_given_p();
3063 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
3064 const VALUE e
= rb_ary_elt(ary
, i
);
3065 const VALUE elt
= block_given
? rb_yield_force_blockarg(e
) : e
;
3066 const VALUE key_value_pair
= rb_check_array_type(elt
);
3067 if (NIL_P(key_value_pair
)) {
3068 rb_raise(rb_eTypeError
, "wrong element type %"PRIsVALUE
" at %ld (expected array)",
3069 rb_obj_class(elt
), i
);
3071 if (RARRAY_LEN(key_value_pair
) != 2) {
3072 rb_raise(rb_eArgError
, "wrong array length at %ld (expected 2, was %ld)",
3073 i
, RARRAY_LEN(key_value_pair
));
3075 rb_hash_aset(hash
, RARRAY_AREF(key_value_pair
, 0), RARRAY_AREF(key_value_pair
, 1));
3082 * array.to_ary -> self
3088 rb_ary_to_ary_m(VALUE ary
)
3094 ary_reverse(VALUE
*p1
, VALUE
*p2
)
3104 rb_ary_reverse(VALUE ary
)
3107 long len
= RARRAY_LEN(ary
);
3111 RARRAY_PTR_USE(ary
, p1
, {
3112 p2
= p1
+ len
- 1; /* points last item */
3113 ary_reverse(p1
, p2
);
3114 }); /* WB: no new reference */
3123 * Reverses the order of the elements of +self+;
3127 * a.reverse! # => [2, 1, 0]
3130 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3134 rb_ary_reverse_bang(VALUE ary
)
3136 return rb_ary_reverse(ary
);
3141 * reverse -> new_array
3143 * Returns a new array containing the elements of +self+ in reverse order:
3145 * [0, 1, 2].reverse # => [2, 1, 0]
3147 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3151 rb_ary_reverse_m(VALUE ary
)
3153 long len
= RARRAY_LEN(ary
);
3154 VALUE dup
= rb_ary_new2(len
);
3157 const VALUE
*p1
= RARRAY_CONST_PTR(ary
);
3158 VALUE
*p2
= (VALUE
*)RARRAY_CONST_PTR(dup
) + len
- 1;
3159 do *p2
-- = *p1
++; while (--len
> 0);
3161 ARY_SET_LEN(dup
, RARRAY_LEN(ary
));
3166 rotate_count(long cnt
, long len
)
3168 return (cnt
< 0) ? (len
- (~cnt
% len
) - 1) : (cnt
% len
);
3172 ary_rotate_ptr(VALUE
*ptr
, long len
, long cnt
)
3176 memmove(ptr
, ptr
+ 1, sizeof(VALUE
)*(len
- 1));
3177 *(ptr
+ len
- 1) = tmp
;
3179 else if (cnt
== len
- 1) {
3180 VALUE tmp
= *(ptr
+ len
- 1);
3181 memmove(ptr
+ 1, ptr
, sizeof(VALUE
)*(len
- 1));
3186 if (cnt
< len
) ary_reverse(ptr
+ cnt
, ptr
+ len
);
3187 if (--cnt
> 0) ary_reverse(ptr
, ptr
+ cnt
);
3188 if (len
> 0) ary_reverse(ptr
, ptr
+ len
);
3193 rb_ary_rotate(VALUE ary
, long cnt
)
3198 long len
= RARRAY_LEN(ary
);
3199 if (len
> 1 && (cnt
= rotate_count(cnt
, len
)) > 0) {
3200 RARRAY_PTR_USE(ary
, ptr
, ary_rotate_ptr(ptr
, len
, cnt
));
3209 * array.rotate! -> self
3210 * array.rotate!(count) -> self
3212 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3214 * When no argument given, rotates the first element to the last position:
3216 * a = [:foo, 'bar', 2, 'bar']
3217 * a.rotate! # => ["bar", 2, "bar", :foo]
3219 * When given a non-negative Integer +count+,
3220 * rotates +count+ elements from the beginning to the end:
3222 * a = [:foo, 'bar', 2]
3224 * a # => [2, :foo, "bar"]
3226 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3228 * a = [:foo, 'bar', 2]
3230 * a # => [2, :foo, "bar"]
3232 * If +count+ is zero, returns +self+ unmodified:
3234 * a = [:foo, 'bar', 2]
3236 * a # => [:foo, "bar", 2]
3238 * When given a negative Integer +count+, rotates in the opposite direction,
3239 * from end to beginning:
3241 * a = [:foo, 'bar', 2]
3243 * a # => ["bar", 2, :foo]
3245 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3247 * a = [:foo, 'bar', 2]
3249 * a # => ["bar", 2, :foo]
3254 rb_ary_rotate_bang(int argc
, VALUE
*argv
, VALUE ary
)
3256 long n
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3257 rb_ary_rotate(ary
, n
);
3263 * array.rotate -> new_array
3264 * array.rotate(count) -> new_array
3266 * Returns a new +Array+ formed from +self+ with elements
3267 * rotated from one end to the other.
3269 * When no argument given, returns a new +Array+ that is like +self+,
3270 * except that the first element has been rotated to the last position:
3272 * a = [:foo, 'bar', 2, 'bar']
3274 * a1 # => ["bar", 2, "bar", :foo]
3276 * When given a non-negative Integer +count+,
3277 * returns a new +Array+ with +count+ elements rotated from the beginning to the end:
3279 * a = [:foo, 'bar', 2]
3281 * a1 # => [2, :foo, "bar"]
3283 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3285 * a = [:foo, 'bar', 2]
3287 * a1 # => [2, :foo, "bar"]
3289 * If +count+ is zero, returns a copy of +self+, unmodified:
3291 * a = [:foo, 'bar', 2]
3293 * a1 # => [:foo, "bar", 2]
3295 * When given a negative Integer +count+, rotates in the opposite direction,
3296 * from end to beginning:
3298 * a = [:foo, 'bar', 2]
3300 * a1 # => ["bar", 2, :foo]
3302 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3304 * a = [:foo, 'bar', 2]
3306 * a1 # => ["bar", 2, :foo]
3311 rb_ary_rotate_m(int argc
, VALUE
*argv
, VALUE ary
)
3316 long cnt
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3318 len
= RARRAY_LEN(ary
);
3319 rotated
= rb_ary_new2(len
);
3321 cnt
= rotate_count(cnt
, len
);
3322 ptr
= RARRAY_CONST_PTR(ary
);
3324 ary_memcpy(rotated
, 0, len
, ptr
+ cnt
);
3325 ary_memcpy(rotated
, len
, cnt
, ptr
);
3327 ARY_SET_LEN(rotated
, RARRAY_LEN(ary
));
3331 struct ary_sort_data
{
3337 sort_reentered(VALUE ary
)
3339 if (RBASIC(ary
)->klass
) {
3340 rb_raise(rb_eRuntimeError
, "sort reentered");
3346 sort_returned(struct ary_sort_data
*data
)
3348 if (rb_obj_frozen_p(data
->receiver
)) {
3349 rb_raise(rb_eFrozenError
, "array frozen during sort");
3351 sort_reentered(data
->ary
);
3355 sort_1(const void *ap
, const void *bp
, void *dummy
)
3357 struct ary_sort_data
*data
= dummy
;
3358 VALUE retval
= sort_reentered(data
->ary
);
3359 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3365 retval
= rb_yield_values2(2, args
);
3366 n
= rb_cmpint(retval
, a
, b
);
3367 sort_returned(data
);
3372 sort_2(const void *ap
, const void *bp
, void *dummy
)
3374 struct ary_sort_data
*data
= dummy
;
3375 VALUE retval
= sort_reentered(data
->ary
);
3376 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3379 if (FIXNUM_P(a
) && FIXNUM_P(b
) && CMP_OPTIMIZABLE(INTEGER
)) {
3380 if ((long)a
> (long)b
) return 1;
3381 if ((long)a
< (long)b
) return -1;
3384 if (STRING_P(a
) && STRING_P(b
) && CMP_OPTIMIZABLE(STRING
)) {
3385 return rb_str_cmp(a
, b
);
3387 if (RB_FLOAT_TYPE_P(a
) && CMP_OPTIMIZABLE(FLOAT
)) {
3388 return rb_float_cmp(a
, b
);
3391 retval
= rb_funcallv(a
, id_cmp
, 1, &b
);
3392 n
= rb_cmpint(retval
, a
, b
);
3393 sort_returned(data
);
3400 * array.sort! -> self
3401 * array.sort! {|a, b| ... } -> self
3403 * Returns +self+ with its elements sorted in place.
3405 * With no block, compares elements using operator <tt>#<=></tt>
3408 * a = 'abcde'.split('').shuffle
3409 * a # => ["e", "b", "d", "a", "c"]
3411 * a # => ["a", "b", "c", "d", "e"]
3413 * With a block, calls the block with each element pair;
3414 * for each element pair +a+ and +b+, the block should return an integer:
3416 * - Negative when +b+ is to follow +a+.
3417 * - Zero when +a+ and +b+ are equivalent.
3418 * - Positive when +a+ is to follow +b+.
3422 * a = 'abcde'.split('').shuffle
3423 * a # => ["e", "b", "d", "a", "c"]
3424 * a.sort! {|a, b| a <=> b }
3425 * a # => ["a", "b", "c", "d", "e"]
3426 * a.sort! {|a, b| b <=> a }
3427 * a # => ["e", "d", "c", "b", "a"]
3429 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3430 * and may be unstable:
3432 * a = 'abcde'.split('').shuffle
3433 * a # => ["e", "b", "d", "a", "c"]
3434 * a.sort! {|a, b| 0 }
3435 * a # => ["d", "e", "c", "a", "b"]
3440 rb_ary_sort_bang(VALUE ary
)
3443 RUBY_ASSERT(!ARY_SHARED_P(ary
));
3444 if (RARRAY_LEN(ary
) > 1) {
3445 VALUE tmp
= ary_make_substitution(ary
); /* only ary refers tmp */
3446 struct ary_sort_data data
;
3447 long len
= RARRAY_LEN(ary
);
3448 RBASIC_CLEAR_CLASS(tmp
);
3450 data
.receiver
= ary
;
3451 RARRAY_PTR_USE(tmp
, ptr
, {
3452 ruby_qsort(ptr
, len
, sizeof(VALUE
),
3453 rb_block_given_p()?sort_1
:sort_2
, &data
);
3454 }); /* WB: no new reference */
3456 if (ARY_EMBED_P(tmp
)) {
3457 if (ARY_SHARED_P(ary
)) { /* ary might be destructively operated in the given block */
3458 rb_ary_unshare(ary
);
3461 if (ARY_EMBED_LEN(tmp
) > ARY_CAPA(ary
)) {
3462 ary_resize_capa(ary
, ARY_EMBED_LEN(tmp
));
3464 ary_memcpy(ary
, 0, ARY_EMBED_LEN(tmp
), ARY_EMBED_PTR(tmp
));
3465 ARY_SET_LEN(ary
, ARY_EMBED_LEN(tmp
));
3468 if (!ARY_EMBED_P(ary
) && ARY_HEAP_PTR(ary
) == ARY_HEAP_PTR(tmp
)) {
3469 FL_UNSET_SHARED(ary
);
3470 ARY_SET_CAPA(ary
, RARRAY_LEN(tmp
));
3473 RUBY_ASSERT(!ARY_SHARED_P(tmp
));
3474 if (ARY_EMBED_P(ary
)) {
3475 FL_UNSET_EMBED(ary
);
3477 else if (ARY_SHARED_P(ary
)) {
3478 /* ary might be destructively operated in the given block */
3479 rb_ary_unshare(ary
);
3484 ARY_SET_PTR(ary
, ARY_HEAP_PTR(tmp
));
3485 ARY_SET_HEAP_LEN(ary
, len
);
3486 ARY_SET_CAPA(ary
, ARY_HEAP_LEN(tmp
));
3488 /* tmp was lost ownership for the ptr */
3489 FL_UNSET(tmp
, FL_FREEZE
);
3491 ARY_SET_EMBED_LEN(tmp
, 0);
3492 FL_SET(tmp
, FL_FREEZE
);
3494 /* tmp will be GC'ed. */
3495 RBASIC_SET_CLASS_RAW(tmp
, rb_cArray
); /* rb_cArray must be marked */
3503 * array.sort -> new_array
3504 * array.sort {|a, b| ... } -> new_array
3506 * Returns a new +Array+ whose elements are those from +self+, sorted.
3508 * With no block, compares elements using operator <tt>#<=></tt>
3511 * a = 'abcde'.split('').shuffle
3512 * a # => ["e", "b", "d", "a", "c"]
3514 * a1 # => ["a", "b", "c", "d", "e"]
3516 * With a block, calls the block with each element pair;
3517 * for each element pair +a+ and +b+, the block should return an integer:
3519 * - Negative when +b+ is to follow +a+.
3520 * - Zero when +a+ and +b+ are equivalent.
3521 * - Positive when +a+ is to follow +b+.
3525 * a = 'abcde'.split('').shuffle
3526 * a # => ["e", "b", "d", "a", "c"]
3527 * a1 = a.sort {|a, b| a <=> b }
3528 * a1 # => ["a", "b", "c", "d", "e"]
3529 * a2 = a.sort {|a, b| b <=> a }
3530 * a2 # => ["e", "d", "c", "b", "a"]
3532 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3533 * and may be unstable:
3535 * a = 'abcde'.split('').shuffle
3536 * a # => ["e", "b", "d", "a", "c"]
3537 * a1 = a.sort {|a, b| 0 }
3538 * a1 # => ["c", "e", "b", "d", "a"]
3540 * Related: Enumerable#sort_by.
3544 rb_ary_sort(VALUE ary
)
3546 ary
= rb_ary_dup(ary
);
3547 rb_ary_sort_bang(ary
);
3551 static VALUE
rb_ary_bsearch_index(VALUE ary
);
3555 * bsearch {|element| ... } -> found_element or nil
3556 * bsearch -> new_enumerator
3558 * Returns the element from +self+ found by a binary search,
3559 * or +nil+ if the search found no suitable element.
3561 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3563 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3567 rb_ary_bsearch(VALUE ary
)
3569 VALUE index_result
= rb_ary_bsearch_index(ary
);
3571 if (FIXNUM_P(index_result
)) {
3572 return rb_ary_entry(ary
, FIX2LONG(index_result
));
3574 return index_result
;
3579 * bsearch_index {|element| ... } -> integer or nil
3580 * bsearch_index -> new_enumerator
3582 * Returns the integer index of the element from +self+ found by a binary search,
3583 * or +nil+ if the search found no suitable element.
3585 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3587 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3591 rb_ary_bsearch_index(VALUE ary
)
3593 long low
= 0, high
= RARRAY_LEN(ary
), mid
;
3594 int smaller
= 0, satisfied
= 0;
3597 RETURN_ENUMERATOR(ary
, 0, 0);
3598 while (low
< high
) {
3599 mid
= low
+ ((high
- low
) / 2);
3600 val
= rb_ary_entry(ary
, mid
);
3603 if (v
== INT2FIX(0)) return INT2FIX(mid
);
3604 smaller
= (SIGNED_VALUE
)v
< 0; /* Fixnum preserves its sign-bit */
3606 else if (v
== Qtrue
) {
3610 else if (!RTEST(v
)) {
3613 else if (rb_obj_is_kind_of(v
, rb_cNumeric
)) {
3614 const VALUE zero
= INT2FIX(0);
3615 switch (rb_cmpint(rb_funcallv(v
, id_cmp
, 1, &zero
), v
, zero
)) {
3616 case 0: return INT2FIX(mid
);
3617 case 1: smaller
= 0; break;
3618 case -1: smaller
= 1;
3622 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
3623 " (must be numeric, true, false or nil)",
3633 if (!satisfied
) return Qnil
;
3634 return INT2FIX(low
);
3639 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, dummy
))
3646 * array.sort_by! {|element| ... } -> self
3647 * array.sort_by! -> new_enumerator
3649 * Sorts the elements of +self+ in place,
3650 * using an ordering determined by the block; returns self.
3652 * Calls the block with each successive element;
3653 * sorts elements based on the values returned from the block.
3655 * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
3657 * This example sorts strings based on their sizes:
3659 * a = ['aaaa', 'bbb', 'cc', 'd']
3660 * a.sort_by! {|element| element.size }
3661 * a # => ["d", "cc", "bbb", "aaaa"]
3663 * Returns a new Enumerator if no block given:
3665 * a = ['aaaa', 'bbb', 'cc', 'd']
3666 * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
3671 rb_ary_sort_by_bang(VALUE ary
)
3675 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3677 sorted
= rb_block_call(ary
, rb_intern("sort_by"), 0, 0, sort_by_i
, 0);
3678 rb_ary_replace(ary
, sorted
);
3685 * collect {|element| ... } -> new_array
3686 * collect -> new_enumerator
3687 * map {|element| ... } -> new_array
3688 * map -> new_enumerator
3690 * With a block given, calls the block with each element of +self+;
3691 * returns a new array whose elements are the return values from the block:
3693 * a = [:foo, 'bar', 2]
3694 * a1 = a.map {|element| element.class }
3695 * a1 # => [Symbol, String, Integer]
3697 * With no block given, returns a new Enumerator.
3699 * Related: #collect!;
3700 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3704 rb_ary_collect(VALUE ary
)
3709 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3710 collect
= rb_ary_new2(RARRAY_LEN(ary
));
3711 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3712 rb_ary_push(collect
, rb_yield(RARRAY_AREF(ary
, i
)));
3720 * collect! {|element| ... } -> new_array
3721 * collect! -> new_enumerator
3722 * map! {|element| ... } -> new_array
3723 * map! -> new_enumerator
3725 * With a block given, calls the block with each element of +self+
3726 * and replaces the element with the block's return value;
3729 * a = [:foo, 'bar', 2]
3730 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3732 * With no block given, returns a new Enumerator.
3734 * Related: #collect;
3735 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3739 rb_ary_collect_bang(VALUE ary
)
3743 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3745 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3746 rb_ary_store(ary
, i
, rb_yield(RARRAY_AREF(ary
, i
)));
3752 rb_get_values_at(VALUE obj
, long olen
, int argc
, const VALUE
*argv
, VALUE (*func
) (VALUE
, long))
3754 VALUE result
= rb_ary_new2(argc
);
3755 long beg
, len
, i
, j
;
3757 for (i
=0; i
<argc
; i
++) {
3758 if (FIXNUM_P(argv
[i
])) {
3759 rb_ary_push(result
, (*func
)(obj
, FIX2LONG(argv
[i
])));
3762 /* check if idx is Range */
3763 if (rb_range_beg_len(argv
[i
], &beg
, &len
, olen
, 1)) {
3764 long end
= olen
< beg
+len
? olen
: beg
+len
;
3765 for (j
= beg
; j
< end
; j
++) {
3766 rb_ary_push(result
, (*func
)(obj
, j
));
3769 rb_ary_resize(result
, RARRAY_LEN(result
) + (beg
+ len
) - j
);
3772 rb_ary_push(result
, (*func
)(obj
, NUM2LONG(argv
[i
])));
3778 append_values_at_single(VALUE result
, VALUE ary
, long olen
, VALUE idx
)
3781 if (FIXNUM_P(idx
)) {
3782 beg
= FIX2LONG(idx
);
3784 /* check if idx is Range */
3785 else if (rb_range_beg_len(idx
, &beg
, &len
, olen
, 1)) {
3787 const VALUE
*const src
= RARRAY_CONST_PTR(ary
);
3788 const long end
= beg
+ len
;
3789 const long prevlen
= RARRAY_LEN(result
);
3791 rb_ary_cat(result
, src
+ beg
, end
> olen
? olen
-beg
: len
);
3794 rb_ary_store(result
, prevlen
+ len
- 1, Qnil
);
3800 beg
= NUM2LONG(idx
);
3802 return rb_ary_push(result
, rb_ary_entry(ary
, beg
));
3807 * array.values_at(*indexes) -> new_array
3809 * Returns a new +Array+ whose elements are the elements
3810 * of +self+ at the given Integer or Range +indexes+.
3812 * For each positive +index+, returns the element at offset +index+:
3814 * a = [:foo, 'bar', 2]
3815 * a.values_at(0, 2) # => [:foo, 2]
3816 * a.values_at(0..1) # => [:foo, "bar"]
3818 * The given +indexes+ may be in any order, and may repeat:
3820 * a = [:foo, 'bar', 2]
3821 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3822 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3824 * Assigns +nil+ for an +index+ that is too large:
3826 * a = [:foo, 'bar', 2]
3827 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3829 * Returns a new empty +Array+ if no arguments given.
3831 * For each negative +index+, counts backward from the end of the array:
3833 * a = [:foo, 'bar', 2]
3834 * a.values_at(-1, -3) # => [2, :foo]
3836 * Assigns +nil+ for an +index+ that is too small:
3838 * a = [:foo, 'bar', 2]
3839 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3841 * The given +indexes+ may have a mixture of signs:
3843 * a = [:foo, 'bar', 2]
3844 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3849 rb_ary_values_at(int argc
, VALUE
*argv
, VALUE ary
)
3851 long i
, olen
= RARRAY_LEN(ary
);
3852 VALUE result
= rb_ary_new_capa(argc
);
3853 for (i
= 0; i
< argc
; ++i
) {
3854 append_values_at_single(result
, ary
, olen
, argv
[i
]);
3863 * select {|element| ... } -> new_array
3864 * select -> new_enumerator
3865 * filter {|element| ... } -> new_array
3866 * filter -> new_enumerator
3868 * With a block given, calls the block with each element of +self+;
3869 * returns a new array containing those elements of +self+
3870 * for which the block returns a truthy value:
3872 * a = [:foo, 'bar', 2, :bam]
3873 * a.select {|element| element.to_s.start_with?('b') }
3874 * # => ["bar", :bam]
3876 * With no block given, returns a new Enumerator.
3878 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3882 rb_ary_select(VALUE ary
)
3887 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3888 result
= rb_ary_new2(RARRAY_LEN(ary
));
3889 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3890 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
3891 rb_ary_push(result
, rb_ary_elt(ary
, i
));
3897 struct select_bang_arg
{
3903 select_bang_i(VALUE a
)
3905 volatile struct select_bang_arg
*arg
= (void *)a
;
3906 VALUE ary
= arg
->ary
;
3909 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
3910 VALUE v
= RARRAY_AREF(ary
, i1
);
3911 if (!RTEST(rb_yield(v
))) continue;
3913 rb_ary_store(ary
, i2
, v
);
3917 return (i1
== i2
) ? Qnil
: ary
;
3921 select_bang_ensure(VALUE a
)
3923 volatile struct select_bang_arg
*arg
= (void *)a
;
3924 VALUE ary
= arg
->ary
;
3925 long len
= RARRAY_LEN(ary
);
3926 long i1
= arg
->len
[0], i2
= arg
->len
[1];
3928 if (i2
< len
&& i2
< i1
) {
3933 RARRAY_PTR_USE(ary
, ptr
, {
3934 MEMMOVE(ptr
+ i2
, ptr
+ i1
, VALUE
, tail
);
3937 ARY_SET_LEN(ary
, i2
+ tail
);
3944 * select! {|element| ... } -> self or nil
3945 * select! -> new_enumerator
3946 * filter! {|element| ... } -> self or nil
3947 * filter! -> new_enumerator
3949 * With a block given, calls the block with each element of +self+;
3950 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3952 * Returns +self+ if any elements were removed:
3954 * a = [:foo, 'bar', 2, :bam]
3955 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3957 * Returns +nil+ if no elements were removed.
3959 * With no block given, returns a new Enumerator.
3961 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3965 rb_ary_select_bang(VALUE ary
)
3967 struct select_bang_arg args
;
3969 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3973 args
.len
[0] = args
.len
[1] = 0;
3974 return rb_ensure(select_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
3979 * keep_if {|element| ... } -> self
3980 * keep_if -> new_enumerator
3982 * With a block given, calls the block with each element of +self+;
3983 * removes the element from +self+ if the block does not return a truthy value:
3985 * a = [:foo, 'bar', 2, :bam]
3986 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3988 * With no block given, returns a new Enumerator.
3990 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
3994 rb_ary_keep_if(VALUE ary
)
3996 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3997 rb_ary_select_bang(ary
);
4002 ary_resize_smaller(VALUE ary
, long len
)
4005 if (RARRAY_LEN(ary
) > len
) {
4006 ARY_SET_LEN(ary
, len
);
4007 if (len
* 2 < ARY_CAPA(ary
) &&
4008 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
) {
4009 ary_resize_capa(ary
, len
* 2);
4016 * delete(object) -> last_removed_object
4017 * delete(object) {|element| ... } -> last_removed_object or block_return
4019 * Removes zero or more elements from +self+.
4021 * With no block given,
4022 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4023 * returns the last removed element:
4025 * a = [0, 1, 2, 2.0]
4026 * a.delete(2) # => 2.0
4029 * Returns +nil+ if no elements removed:
4031 * a.delete(2) # => nil
4033 * With a block given,
4034 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4036 * If any such elements are found, ignores the block
4037 * and returns the last removed element:
4039 * a = [0, 1, 2, 2.0]
4040 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4043 * If no such element is found, returns the block's return value:
4045 * a.delete(2) {|element| "Element #{element} not found." }
4046 * # => "Element 2 not found."
4048 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4052 rb_ary_delete(VALUE ary
, VALUE item
)
4057 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
4058 VALUE e
= RARRAY_AREF(ary
, i1
);
4060 if (rb_equal(e
, item
)) {
4065 rb_ary_store(ary
, i2
, e
);
4069 if (RARRAY_LEN(ary
) == i2
) {
4070 if (rb_block_given_p()) {
4071 return rb_yield(item
);
4076 ary_resize_smaller(ary
, i2
);
4083 rb_ary_delete_same(VALUE ary
, VALUE item
)
4087 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
4088 VALUE e
= RARRAY_AREF(ary
, i1
);
4094 rb_ary_store(ary
, i2
, e
);
4098 if (RARRAY_LEN(ary
) == i2
) {
4102 ary_resize_smaller(ary
, i2
);
4106 rb_ary_delete_at(VALUE ary
, long pos
)
4108 long len
= RARRAY_LEN(ary
);
4111 if (pos
>= len
) return Qnil
;
4114 if (pos
< 0) return Qnil
;
4118 del
= RARRAY_AREF(ary
, pos
);
4119 RARRAY_PTR_USE(ary
, ptr
, {
4120 MEMMOVE(ptr
+pos
, ptr
+pos
+1, VALUE
, len
-pos
-1);
4122 ARY_INCREASE_LEN(ary
, -1);
4129 * delete_at(index) -> removed_object or nil
4131 * Removes the element of +self+ at the given +index+, which must be an
4132 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4134 * When +index+ is non-negative, deletes the element at offset +index+:
4136 * a = [:foo, 'bar', 2]
4137 * a.delete_at(1) # => "bar"
4140 * When +index+ is negative, counts backward from the end of the array:
4142 * a = [:foo, 'bar', 2]
4143 * a.delete_at(-2) # => "bar"
4146 * When +index+ is out of range, returns +nil+.
4148 * a = [:foo, 'bar', 2]
4149 * a.delete_at(3) # => nil
4150 * a.delete_at(-4) # => nil
4152 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4156 rb_ary_delete_at_m(VALUE ary
, VALUE pos
)
4158 return rb_ary_delete_at(ary
, NUM2LONG(pos
));
4162 ary_slice_bang_by_rb_ary_splice(VALUE ary
, long pos
, long len
)
4164 const long orig_len
= RARRAY_LEN(ary
);
4169 else if (pos
< -orig_len
) {
4175 else if (orig_len
< pos
) {
4178 if (orig_len
< pos
+ len
) {
4179 len
= orig_len
- pos
;
4182 return rb_ary_new2(0);
4185 VALUE arg2
= rb_ary_new4(len
, RARRAY_CONST_PTR(ary
)+pos
);
4186 rb_ary_splice(ary
, pos
, len
, 0, 0);
4193 * array.slice!(n) -> object or nil
4194 * array.slice!(start, length) -> new_array or nil
4195 * array.slice!(range) -> new_array or nil
4197 * Removes and returns elements from +self+.
4199 * When the only argument is an Integer +n+,
4200 * removes and returns the _nth_ element in +self+:
4202 * a = [:foo, 'bar', 2]
4203 * a.slice!(1) # => "bar"
4206 * If +n+ is negative, counts backwards from the end of +self+:
4208 * a = [:foo, 'bar', 2]
4209 * a.slice!(-1) # => 2
4210 * a # => [:foo, "bar"]
4212 * If +n+ is out of range, returns +nil+.
4214 * When the only arguments are Integers +start+ and +length+,
4215 * removes +length+ elements from +self+ beginning at offset +start+;
4216 * returns the deleted objects in a new +Array+:
4218 * a = [:foo, 'bar', 2]
4219 * a.slice!(0, 2) # => [:foo, "bar"]
4222 * If <tt>start + length</tt> exceeds the array size,
4223 * removes and returns all elements from offset +start+ to the end:
4225 * a = [:foo, 'bar', 2]
4226 * a.slice!(1, 50) # => ["bar", 2]
4229 * If <tt>start == a.size</tt> and +length+ is non-negative,
4230 * returns a new empty +Array+.
4232 * If +length+ is negative, returns +nil+.
4234 * When the only argument is a Range object +range+,
4235 * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
4237 * a = [:foo, 'bar', 2]
4238 * a.slice!(1..2) # => ["bar", 2]
4241 * If <tt>range.start == a.size</tt>, returns a new empty +Array+.
4243 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
4245 * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
4247 * a = [:foo, 'bar', 2]
4248 * a.slice!(0..-2) # => [:foo, "bar"]
4251 * If <tt>range.start</tt> is negative,
4252 * calculates the start index backwards from the end of the array:
4254 * a = [:foo, 'bar', 2]
4255 * a.slice!(-2..2) # => ["bar", 2]
4261 rb_ary_slice_bang(int argc
, VALUE
*argv
, VALUE ary
)
4266 rb_ary_modify_check(ary
);
4267 rb_check_arity(argc
, 1, 2);
4271 pos
= NUM2LONG(argv
[0]);
4272 len
= NUM2LONG(argv
[1]);
4273 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4276 if (!FIXNUM_P(arg1
)) {
4277 switch (rb_range_beg_len(arg1
, &pos
, &len
, RARRAY_LEN(ary
), 0)) {
4280 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4290 return rb_ary_delete_at(ary
, NUM2LONG(arg1
));
4294 ary_reject(VALUE orig
, VALUE result
)
4298 for (i
= 0; i
< RARRAY_LEN(orig
); i
++) {
4299 VALUE v
= RARRAY_AREF(orig
, i
);
4301 if (!RTEST(rb_yield(v
))) {
4302 rb_ary_push(result
, v
);
4309 reject_bang_i(VALUE a
)
4311 volatile struct select_bang_arg
*arg
= (void *)a
;
4312 VALUE ary
= arg
->ary
;
4315 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
4316 VALUE v
= RARRAY_AREF(ary
, i1
);
4317 if (RTEST(rb_yield(v
))) continue;
4319 rb_ary_store(ary
, i2
, v
);
4323 return (i1
== i2
) ? Qnil
: ary
;
4327 ary_reject_bang(VALUE ary
)
4329 struct select_bang_arg args
;
4330 rb_ary_modify_check(ary
);
4332 args
.len
[0] = args
.len
[1] = 0;
4333 return rb_ensure(reject_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
4338 * reject! {|element| ... } -> self or nil
4339 * reject! -> new_enumerator
4341 * With a block given, calls the block with each element of +self+;
4342 * removes each element for which the block returns a truthy value.
4344 * Returns +self+ if any elements removed:
4346 * a = [:foo, 'bar', 2, 'bat']
4347 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4349 * Returns +nil+ if no elements removed.
4351 * With no block given, returns a new Enumerator.
4353 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4357 rb_ary_reject_bang(VALUE ary
)
4359 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4361 return ary_reject_bang(ary
);
4366 * reject {|element| ... } -> new_array
4367 * reject -> new_enumerator
4369 * With a block given, returns a new array whose elements are all those from +self+
4370 * for which the block returns +false+ or +nil+:
4372 * a = [:foo, 'bar', 2, 'bat']
4373 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4376 * With no block given, returns a new Enumerator.
4378 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4382 rb_ary_reject(VALUE ary
)
4386 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4387 rejected_ary
= rb_ary_new();
4388 ary_reject(ary
, rejected_ary
);
4389 return rejected_ary
;
4394 * delete_if {|element| ... } -> self
4395 * delete_if -> new_numerator
4397 * With a block given, calls the block with each element of +self+;
4398 * removes the element if the block returns a truthy value;
4401 * a = [:foo, 'bar', 2, 'bat']
4402 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4404 * With no block given, returns a new Enumerator.
4406 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4410 rb_ary_delete_if(VALUE ary
)
4413 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4414 ary_reject_bang(ary
);
4419 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val
, cbarg
))
4421 VALUE
*args
= (VALUE
*)cbarg
;
4422 if (argc
> 1) val
= rb_ary_new4(argc
, argv
);
4423 rb_ary_push(args
[0], val
);
4424 if (--args
[1] == 0) rb_iter_break();
4429 take_items(VALUE obj
, long n
)
4431 VALUE result
= rb_check_array_type(obj
);
4434 if (n
== 0) return result
;
4435 if (!NIL_P(result
)) return rb_ary_subseq(result
, 0, n
);
4436 result
= rb_ary_new2(n
);
4437 args
[0] = result
; args
[1] = (VALUE
)n
;
4438 if (UNDEF_P(rb_check_block_call(obj
, idEach
, 0, 0, take_i
, (VALUE
)args
)))
4439 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
" (must respond to :each)",
4447 * array.zip(*other_arrays) -> new_array
4448 * array.zip(*other_arrays) {|other_array| ... } -> nil
4450 * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
4451 * whose elements are Arrays.
4453 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4456 * - The _nth_ element of +self+.
4457 * - The _nth_ element of each of the +other_arrays+.
4459 * If all +other_arrays+ and +self+ are the same size:
4461 * a = [:a0, :a1, :a2, :a3]
4462 * b = [:b0, :b1, :b2, :b3]
4463 * c = [:c0, :c1, :c2, :c3]
4465 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4467 * If any array in +other_arrays+ is smaller than +self+,
4468 * fills to <tt>self.size</tt> with +nil+:
4470 * a = [:a0, :a1, :a2, :a3]
4471 * b = [:b0, :b1, :b2]
4474 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4476 * If any array in +other_arrays+ is larger than +self+,
4477 * its trailing elements are ignored:
4479 * a = [:a0, :a1, :a2, :a3]
4480 * b = [:b0, :b1, :b2, :b3, :b4]
4481 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4483 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4485 * If an argument is not an array, it extracts the values by calling #each:
4487 * a = [:a0, :a1, :a2, :a2]
4490 * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
4492 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
4494 * a = [:a0, :a1, :a2, :a3]
4495 * b = [:b0, :b1, :b2, :b3]
4496 * c = [:c0, :c1, :c2, :c3]
4497 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4509 rb_ary_zip(int argc
, VALUE
*argv
, VALUE ary
)
4512 long len
= RARRAY_LEN(ary
);
4513 VALUE result
= Qnil
;
4515 for (i
=0; i
<argc
; i
++) {
4516 argv
[i
] = take_items(argv
[i
], len
);
4519 if (rb_block_given_p()) {
4520 int arity
= rb_block_arity();
4525 tmp
= ALLOCV_N(VALUE
, work
, argc
+1);
4527 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4528 tmp
[0] = RARRAY_AREF(ary
, i
);
4529 for (j
=0; j
<argc
; j
++) {
4530 tmp
[j
+1] = rb_ary_elt(argv
[j
], i
);
4532 rb_yield_values2(argc
+1, tmp
);
4535 if (work
) ALLOCV_END(work
);
4538 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4539 VALUE tmp
= rb_ary_new2(argc
+1);
4541 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4542 for (j
=0; j
<argc
; j
++) {
4543 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4550 result
= rb_ary_new_capa(len
);
4552 for (i
=0; i
<len
; i
++) {
4553 VALUE tmp
= rb_ary_new_capa(argc
+1);
4555 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4556 for (j
=0; j
<argc
; j
++) {
4557 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4559 rb_ary_push(result
, tmp
);
4568 * array.transpose -> new_array
4570 * Transposes the rows and columns in an +Array+ of Arrays;
4571 * the nested Arrays must all be the same size:
4573 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4574 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4579 rb_ary_transpose(VALUE ary
)
4581 long elen
= -1, alen
, i
, j
;
4582 VALUE tmp
, result
= 0;
4584 alen
= RARRAY_LEN(ary
);
4585 if (alen
== 0) return rb_ary_dup(ary
);
4586 for (i
=0; i
<alen
; i
++) {
4587 tmp
= to_ary(rb_ary_elt(ary
, i
));
4588 if (elen
< 0) { /* first element */
4589 elen
= RARRAY_LEN(tmp
);
4590 result
= rb_ary_new2(elen
);
4591 for (j
=0; j
<elen
; j
++) {
4592 rb_ary_store(result
, j
, rb_ary_new2(alen
));
4595 else if (elen
!= RARRAY_LEN(tmp
)) {
4596 rb_raise(rb_eIndexError
, "element size differs (%ld should be %ld)",
4597 RARRAY_LEN(tmp
), elen
);
4599 for (j
=0; j
<elen
; j
++) {
4600 rb_ary_store(rb_ary_elt(result
, j
), i
, rb_ary_elt(tmp
, j
));
4608 * initialize_copy(other_array) -> self
4609 * replace(other_array) -> self
4611 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4612 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4615 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4616 * a.replace(['d', 'e']) # => ["d", "e"]
4618 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4622 rb_ary_replace(VALUE copy
, VALUE orig
)
4624 rb_ary_modify_check(copy
);
4625 orig
= to_ary(orig
);
4626 if (copy
== orig
) return copy
;
4630 /* orig has enough space to embed the contents of orig. */
4631 if (RARRAY_LEN(orig
) <= ary_embed_capa(copy
)) {
4632 RUBY_ASSERT(ARY_EMBED_P(copy
));
4633 ary_memcpy(copy
, 0, RARRAY_LEN(orig
), RARRAY_CONST_PTR(orig
));
4634 ARY_SET_EMBED_LEN(copy
, RARRAY_LEN(orig
));
4636 /* orig is embedded but copy does not have enough space to embed the
4637 * contents of orig. */
4638 else if (ARY_EMBED_P(orig
)) {
4639 long len
= ARY_EMBED_LEN(orig
);
4640 VALUE
*ptr
= ary_heap_alloc_buffer(len
);
4642 FL_UNSET_EMBED(copy
);
4643 ARY_SET_PTR(copy
, ptr
);
4644 ARY_SET_LEN(copy
, len
);
4645 ARY_SET_CAPA(copy
, len
);
4647 // No allocation and exception expected that could leave `copy` in a
4648 // bad state from the edits above.
4649 ary_memcpy(copy
, 0, len
, RARRAY_CONST_PTR(orig
));
4651 /* Otherwise, orig is on heap and copy does not have enough space to embed
4652 * the contents of orig. */
4654 VALUE shared_root
= ary_make_shared(orig
);
4655 FL_UNSET_EMBED(copy
);
4656 ARY_SET_PTR(copy
, ARY_HEAP_PTR(orig
));
4657 ARY_SET_LEN(copy
, ARY_HEAP_LEN(orig
));
4658 rb_ary_set_shared(copy
, shared_root
);
4668 * Removes all elements from +self+; returns +self+:
4670 * a = [:foo, 'bar', 2]
4673 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4677 rb_ary_clear(VALUE ary
)
4679 rb_ary_modify_check(ary
);
4680 if (ARY_SHARED_P(ary
)) {
4681 rb_ary_unshare(ary
);
4683 ARY_SET_EMBED_LEN(ary
, 0);
4686 ARY_SET_LEN(ary
, 0);
4687 if (ARY_DEFAULT_SIZE
* 2 < ARY_CAPA(ary
)) {
4688 ary_resize_capa(ary
, ARY_DEFAULT_SIZE
* 2);
4697 * fill(object, start = nil, count = nil) -> new_array
4698 * fill(object, range) -> new_array
4699 * fill(start = nil, count = nil) {|element| ... } -> new_array
4700 * fill(range) {|element| ... } -> new_array
4702 * Replaces selected elements in +self+;
4703 * may add elements to +self+;
4704 * always returns +self+ (never a new array).
4708 * # Non-negative start.
4709 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4710 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4712 * # Extends with specified values if necessary.
4713 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4714 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4716 * # Fills with nils if necessary.
4717 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4718 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4720 * # For negative start, counts backwards from the end.
4721 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4722 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4725 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4726 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4728 * When arguments +start+ and +count+ are given,
4729 * they select the elements of +self+ to be replaced;
4731 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
4734 * - +start+ specifies the zero-based offset of the first element to be replaced;
4736 * - +count+ is the number of consecutive elements to be replaced;
4737 * +nil+ means "all the rest."
4739 * With argument +object+ given,
4740 * that one object is used for all replacements:
4742 * o = Object.new # => #<Object:0x0000014e7bff7600>
4743 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4745 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
4747 * With a block given, the block is called once for each element to be replaced;
4748 * the value passed to the block is the _index_ of the element to be replaced
4749 * (not the element itself);
4750 * the block's return value replaces the element:
4752 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
4753 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
4755 * For arguments +start+ and +count+:
4757 * - If +start+ is non-negative,
4758 * replaces +count+ elements beginning at offset +start+:
4760 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
4761 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
4762 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
4764 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4765 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4766 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
4768 * Extends +self+ if necessary:
4770 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
4771 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
4773 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
4774 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
4776 * Fills with +nil+ if necessary:
4778 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
4779 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
4781 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
4782 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
4784 * Does nothing if +count+ is non-positive:
4786 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
4787 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
4788 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
4790 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4791 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4792 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4794 * - If +start+ is negative, counts backwards from the end of +self+:
4796 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
4797 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
4799 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
4800 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
4802 * Extends +self+ if necessary:
4804 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
4805 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
4807 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
4808 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
4810 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
4812 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
4813 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
4815 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4816 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
4818 * Does nothing if +count+ is non-positive:
4820 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
4821 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
4823 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4824 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4826 * When argument +range+ is given,
4827 * it must be a Range object whose members are numeric;
4828 * its +begin+ and +end+ values determine the elements of +self+
4831 * - If both +begin+ and +end+ are positive, they specify the first and last elements
4834 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
4835 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4837 * If +end+ is smaller than +begin+, replaces no elements:
4839 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
4840 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
4842 * - If either is negative (or both are negative), counts backwards from the end of +self+:
4844 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
4845 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
4846 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
4848 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4849 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4850 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
4852 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
4854 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
4855 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
4857 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4858 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
4860 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
4861 * replaces elements to the end of +self+:
4863 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
4864 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
4866 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
4867 * replaces elements from the beginning of +self+:
4869 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
4870 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
4872 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4876 rb_ary_fill(int argc
, VALUE
*argv
, VALUE ary
)
4878 VALUE item
= Qundef
, arg1
, arg2
;
4879 long beg
= 0, end
= 0, len
= 0;
4881 if (rb_block_given_p()) {
4882 rb_scan_args(argc
, argv
, "02", &arg1
, &arg2
);
4883 argc
+= 1; /* hackish */
4886 rb_scan_args(argc
, argv
, "12", &item
, &arg1
, &arg2
);
4891 len
= RARRAY_LEN(ary
);
4894 if (rb_range_beg_len(arg1
, &beg
, &len
, RARRAY_LEN(ary
), 1)) {
4899 beg
= NIL_P(arg1
) ? 0 : NUM2LONG(arg1
);
4901 beg
= RARRAY_LEN(ary
) + beg
;
4902 if (beg
< 0) beg
= 0;
4904 len
= NIL_P(arg2
) ? RARRAY_LEN(ary
) - beg
: NUM2LONG(arg2
);
4911 if (beg
>= ARY_MAX_SIZE
|| len
> ARY_MAX_SIZE
- beg
) {
4912 rb_raise(rb_eArgError
, "argument too big");
4915 if (RARRAY_LEN(ary
) < end
) {
4916 if (end
>= ARY_CAPA(ary
)) {
4917 ary_resize_capa(ary
, end
);
4919 ary_mem_clear(ary
, RARRAY_LEN(ary
), end
- RARRAY_LEN(ary
));
4920 ARY_SET_LEN(ary
, end
);
4923 if (UNDEF_P(item
)) {
4927 for (i
=beg
; i
<end
; i
++) {
4928 v
= rb_yield(LONG2NUM(i
));
4929 if (i
>=RARRAY_LEN(ary
)) break;
4934 ary_memfill(ary
, beg
, len
, item
);
4941 * self + other_array -> new_array
4943 * Returns a new array containing all elements of +self+
4944 * followed by all elements of +other_array+:
4946 * a = [0, 1] + [2, 3]
4947 * a # => [0, 1, 2, 3]
4949 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
4953 rb_ary_plus(VALUE x
, VALUE y
)
4956 long len
, xlen
, ylen
;
4959 xlen
= RARRAY_LEN(x
);
4960 ylen
= RARRAY_LEN(y
);
4962 z
= rb_ary_new2(len
);
4964 ary_memcpy(z
, 0, xlen
, RARRAY_CONST_PTR(x
));
4965 ary_memcpy(z
, xlen
, ylen
, RARRAY_CONST_PTR(y
));
4966 ARY_SET_LEN(z
, len
);
4971 ary_append(VALUE x
, VALUE y
)
4973 long n
= RARRAY_LEN(y
);
4975 rb_ary_splice(x
, RARRAY_LEN(x
), 0, RARRAY_CONST_PTR(y
), n
);
4983 * concat(*other_arrays) -> self
4985 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
4988 * a.concat(['two', 'three'], [:four, :five], a)
4989 * # => [0, 1, "two", "three", :four, :five, 0, 1]
4991 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4995 rb_ary_concat_multi(int argc
, VALUE
*argv
, VALUE ary
)
4997 rb_ary_modify_check(ary
);
5000 rb_ary_concat(ary
, argv
[0]);
5002 else if (argc
> 1) {
5004 VALUE args
= rb_ary_hidden_new(argc
);
5005 for (i
= 0; i
< argc
; i
++) {
5006 rb_ary_concat(args
, argv
[i
]);
5008 ary_append(ary
, args
);
5016 rb_ary_concat(VALUE x
, VALUE y
)
5018 return ary_append(x
, to_ary(y
));
5023 * self * n -> new_array
5024 * self * string_separator -> new_string
5026 * When non-negative integer argument +n+ is given,
5027 * returns a new array built by concatenating +n+ copies of +self+:
5030 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5032 * When string argument +string_separator+ is given,
5033 * equivalent to <tt>self.join(string_separator)</tt>:
5035 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
5040 rb_ary_times(VALUE ary
, VALUE times
)
5046 tmp
= rb_check_string_type(times
);
5048 return rb_ary_join(ary
, tmp
);
5051 len
= NUM2LONG(times
);
5053 ary2
= ary_new(rb_cArray
, 0);
5057 rb_raise(rb_eArgError
, "negative argument");
5059 if (ARY_MAX_SIZE
/len
< RARRAY_LEN(ary
)) {
5060 rb_raise(rb_eArgError
, "argument too big");
5062 len
*= RARRAY_LEN(ary
);
5064 ary2
= ary_new(rb_cArray
, len
);
5065 ARY_SET_LEN(ary2
, len
);
5067 ptr
= RARRAY_CONST_PTR(ary
);
5068 t
= RARRAY_LEN(ary
);
5070 ary_memcpy(ary2
, 0, t
, ptr
);
5071 while (t
<= len
/2) {
5072 ary_memcpy(ary2
, t
, t
, RARRAY_CONST_PTR(ary2
));
5076 ary_memcpy(ary2
, t
, len
-t
, RARRAY_CONST_PTR(ary2
));
5085 * assoc(object) -> found_array or nil
5087 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5088 * and <tt>ele[0] == object</tt>:
5090 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5091 * a.assoc(4) # => [4, 5, 6]
5093 * Returns +nil+ if no such element is found.
5095 * Related: Array#rassoc;
5096 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5100 rb_ary_assoc(VALUE ary
, VALUE key
)
5105 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5106 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5107 if (!NIL_P(v
) && RARRAY_LEN(v
) > 0 &&
5108 rb_equal(RARRAY_AREF(v
, 0), key
))
5116 * rassoc(object) -> found_array or nil
5118 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5119 * and <tt>ele[1] == object</tt>:
5121 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5122 * a.rassoc(4) # => [2, 4]
5123 * a.rassoc(5) # => [4, 5, 6]
5125 * Returns +nil+ if no such element is found.
5127 * Related: Array#assoc;
5128 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5132 rb_ary_rassoc(VALUE ary
, VALUE value
)
5137 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5138 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
5139 if (RB_TYPE_P(v
, T_ARRAY
) &&
5140 RARRAY_LEN(v
) > 1 &&
5141 rb_equal(RARRAY_AREF(v
, 1), value
))
5148 recursive_equal(VALUE ary1
, VALUE ary2
, int recur
)
5151 const VALUE
*p1
, *p2
;
5153 if (recur
) return Qtrue
; /* Subtle! */
5155 /* rb_equal() can evacuate ptrs */
5156 p1
= RARRAY_CONST_PTR(ary1
);
5157 p2
= RARRAY_CONST_PTR(ary2
);
5158 len1
= RARRAY_LEN(ary1
);
5160 for (i
= 0; i
< len1
; i
++) {
5162 if (rb_equal(*p1
, *p2
)) {
5163 len1
= RARRAY_LEN(ary1
);
5164 if (len1
!= RARRAY_LEN(ary2
))
5168 p1
= RARRAY_CONST_PTR(ary1
) + i
;
5169 p2
= RARRAY_CONST_PTR(ary2
) + i
;
5183 * self == other_array -> true or false
5185 * Returns whether both:
5187 * - +self+ and +other_array+ are the same size.
5188 * - Their corresponding elements are the same;
5189 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5190 * <tt>self[i] == other_array[i]</tt>.
5194 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5195 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5196 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5197 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5199 * This method is different from method Array#eql?,
5200 * which compares elements using <tt>Object#eql?</tt>.
5202 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5206 rb_ary_equal(VALUE ary1
, VALUE ary2
)
5208 if (ary1
== ary2
) return Qtrue
;
5209 if (!RB_TYPE_P(ary2
, T_ARRAY
)) {
5210 if (!rb_respond_to(ary2
, idTo_ary
)) {
5213 return rb_equal(ary2
, ary1
);
5215 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5216 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5217 return rb_exec_recursive_paired(recursive_equal
, ary1
, ary2
, ary2
);
5221 recursive_eql(VALUE ary1
, VALUE ary2
, int recur
)
5225 if (recur
) return Qtrue
; /* Subtle! */
5226 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5227 if (!rb_eql(rb_ary_elt(ary1
, i
), rb_ary_elt(ary2
, i
)))
5235 * eql?(other_array) -> true or false
5237 * Returns +true+ if +self+ and +other_array+ are the same size,
5238 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5240 * a0 = [:foo, 'bar', 2]
5241 * a1 = [:foo, 'bar', 2]
5242 * a1.eql?(a0) # => true
5244 * Otherwise, returns +false+.
5246 * This method is different from method Array#==,
5247 * which compares using method <tt>Object#==</tt>.
5249 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5253 rb_ary_eql(VALUE ary1
, VALUE ary2
)
5255 if (ary1
== ary2
) return Qtrue
;
5256 if (!RB_TYPE_P(ary2
, T_ARRAY
)) return Qfalse
;
5257 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5258 if (RARRAY_CONST_PTR(ary1
) == RARRAY_CONST_PTR(ary2
)) return Qtrue
;
5259 return rb_exec_recursive_paired(recursive_eql
, ary1
, ary2
, ary2
);
5263 rb_ary_hash_values(long len
, const VALUE
*elements
)
5269 h
= rb_hash_start(len
);
5270 h
= rb_hash_uint(h
, (st_index_t
)rb_ary_hash_values
);
5271 for (i
=0; i
<len
; i
++) {
5272 n
= rb_hash(elements
[i
]);
5273 h
= rb_hash_uint(h
, NUM2LONG(n
));
5283 * Returns the integer hash value for +self+.
5285 * Two arrays with the same content will have the same hash value
5286 * (and will compare using eql?):
5288 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5289 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5290 * ['a', 'b'].hash == ['a'].hash # => false
5295 rb_ary_hash(VALUE ary
)
5297 return rb_ary_hash_values(RARRAY_LEN(ary
), RARRAY_CONST_PTR(ary
));
5302 * include?(object) -> true or false
5304 * Returns whether for some element +element+ in +self+,
5305 * <tt>object == element</tt>:
5307 * [0, 1, 2].include?(2) # => true
5308 * [0, 1, 2].include?(2.0) # => true
5309 * [0, 1, 2].include?(2.1) # => false
5311 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5315 rb_ary_includes(VALUE ary
, VALUE item
)
5320 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5321 e
= RARRAY_AREF(ary
, i
);
5322 if (rb_equal(e
, item
)) {
5330 rb_ary_includes_by_eql(VALUE ary
, VALUE item
)
5335 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5336 e
= RARRAY_AREF(ary
, i
);
5337 if (rb_eql(item
, e
)) {
5345 recursive_cmp(VALUE ary1
, VALUE ary2
, int recur
)
5349 if (recur
) return Qundef
; /* Subtle! */
5350 len
= RARRAY_LEN(ary1
);
5351 if (len
> RARRAY_LEN(ary2
)) {
5352 len
= RARRAY_LEN(ary2
);
5354 for (i
=0; i
<len
; i
++) {
5355 VALUE e1
= rb_ary_elt(ary1
, i
), e2
= rb_ary_elt(ary2
, i
);
5356 VALUE v
= rb_funcallv(e1
, id_cmp
, 1, &e2
);
5357 if (v
!= INT2FIX(0)) {
5366 * self <=> other_array -> -1, 0, or 1
5368 * Returns -1, 0, or 1 as +self+ is determined
5369 * to be less than, equal to, or greater than +other_array+.
5371 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5373 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5374 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5376 * [0, 1, 2] <=> [0, 0, 2] # => 1
5378 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5380 * [0, 1, 2] <=> [0, 2, 2] # => -1
5382 * - Continues if <tt>result[i]</tt> is 0.
5384 * When every +result+ is 0,
5385 * returns <tt>self.size <=> other_array.size</tt>
5386 * (see Integer#<=>):
5388 * [0, 1, 2] <=> [0, 1] # => 1
5389 * [0, 1, 2] <=> [0, 1, 2] # => 0
5390 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5392 * Note that when +other_array+ is larger than +self+,
5393 * its trailing elements do not affect the result:
5395 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5396 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5397 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5399 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5403 rb_ary_cmp(VALUE ary1
, VALUE ary2
)
5408 ary2
= rb_check_array_type(ary2
);
5409 if (NIL_P(ary2
)) return Qnil
;
5410 if (ary1
== ary2
) return INT2FIX(0);
5411 v
= rb_exec_recursive_paired(recursive_cmp
, ary1
, ary2
, ary2
);
5412 if (!UNDEF_P(v
)) return v
;
5413 len
= RARRAY_LEN(ary1
) - RARRAY_LEN(ary2
);
5414 if (len
== 0) return INT2FIX(0);
5415 if (len
> 0) return INT2FIX(1);
5420 ary_add_hash(VALUE hash
, VALUE ary
)
5424 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5425 VALUE elt
= RARRAY_AREF(ary
, i
);
5426 rb_hash_add_new_element(hash
, elt
, elt
);
5432 ary_tmp_hash_new(VALUE ary
)
5434 long size
= RARRAY_LEN(ary
);
5435 VALUE hash
= rb_hash_new_with_size(size
);
5437 RBASIC_CLEAR_CLASS(hash
);
5442 ary_make_hash(VALUE ary
)
5444 VALUE hash
= ary_tmp_hash_new(ary
);
5445 return ary_add_hash(hash
, ary
);
5449 ary_add_hash_by(VALUE hash
, VALUE ary
)
5453 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5454 VALUE v
= rb_ary_elt(ary
, i
), k
= rb_yield(v
);
5455 rb_hash_add_new_element(hash
, k
, v
);
5461 ary_make_hash_by(VALUE ary
)
5463 VALUE hash
= ary_tmp_hash_new(ary
);
5464 return ary_add_hash_by(hash
, ary
);
5469 * self - other_array -> new_array
5471 * Returns a new array containing only those elements of +self+
5472 * that are not found in +other_array+;
5473 * the order from +self+ is preserved:
5475 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5476 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5477 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5479 * Element are compared using method <tt>#eql?</tt>
5480 * (as defined in each element of +self+).
5482 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5486 rb_ary_diff(VALUE ary1
, VALUE ary2
)
5492 ary2
= to_ary(ary2
);
5493 if (RARRAY_LEN(ary2
) == 0) { return ary_make_shared_copy(ary1
); }
5494 ary3
= rb_ary_new();
5496 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
|| RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5497 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5498 VALUE elt
= rb_ary_elt(ary1
, i
);
5499 if (rb_ary_includes_by_eql(ary2
, elt
)) continue;
5500 rb_ary_push(ary3
, elt
);
5505 hash
= ary_make_hash(ary2
);
5506 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5507 if (rb_hash_stlike_lookup(hash
, RARRAY_AREF(ary1
, i
), NULL
)) continue;
5508 rb_ary_push(ary3
, rb_ary_elt(ary1
, i
));
5516 * difference(*other_arrays = []) -> new_array
5518 * Returns a new array containing only those elements from +self+
5519 * that are not found in any of the given +other_arrays+;
5520 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5522 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5523 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5524 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5525 * [0, 1, 2].difference # => [0, 1, 2]
5527 * Returns a copy of +self+ if no arguments are given.
5530 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5534 rb_ary_difference_multi(int argc
, VALUE
*argv
, VALUE ary
)
5539 bool *is_hash
= ALLOCV_N(bool, t0
, argc
);
5540 ary_diff
= rb_ary_new();
5541 length
= RARRAY_LEN(ary
);
5543 for (i
= 0; i
< argc
; i
++) {
5544 argv
[i
] = to_ary(argv
[i
]);
5545 is_hash
[i
] = (length
> SMALL_ARRAY_LEN
&& RARRAY_LEN(argv
[i
]) > SMALL_ARRAY_LEN
);
5546 if (is_hash
[i
]) argv
[i
] = ary_make_hash(argv
[i
]);
5549 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5551 VALUE elt
= rb_ary_elt(ary
, i
);
5552 for (j
= 0; j
< argc
; j
++) {
5554 if (rb_hash_stlike_lookup(argv
[j
], RARRAY_AREF(ary
, i
), NULL
))
5558 if (rb_ary_includes_by_eql(argv
[j
], elt
)) break;
5561 if (j
== argc
) rb_ary_push(ary_diff
, elt
);
5572 * self & other_array -> new_array
5574 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5575 * that is, containing those elements found in both +self+ and +other_array+:
5577 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5581 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5583 * Preserves order from +self+:
5585 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5587 * Identifies common elements using method <tt>#eql?</tt>
5588 * (as defined in each element of +self+).
5590 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5595 rb_ary_and(VALUE ary1
, VALUE ary2
)
5597 VALUE hash
, ary3
, v
;
5601 ary2
= to_ary(ary2
);
5602 ary3
= rb_ary_new();
5603 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return ary3
;
5605 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5606 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5607 v
= RARRAY_AREF(ary1
, i
);
5608 if (!rb_ary_includes_by_eql(ary2
, v
)) continue;
5609 if (rb_ary_includes_by_eql(ary3
, v
)) continue;
5610 rb_ary_push(ary3
, v
);
5615 hash
= ary_make_hash(ary2
);
5617 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5618 v
= RARRAY_AREF(ary1
, i
);
5620 if (rb_hash_stlike_delete(hash
, &vv
, 0)) {
5621 rb_ary_push(ary3
, v
);
5630 * intersection(*other_arrays) -> new_array
5632 * Returns a new array containing each element in +self+ that is +#eql?+
5633 * to at least one element in each of the given +other_arrays+;
5634 * duplicates are omitted:
5636 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5638 * Each element must correctly implement method <tt>#hash</tt>.
5640 * Order from +self+ is preserved:
5642 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5644 * Returns a copy of +self+ if no arguments are given.
5646 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5650 rb_ary_intersection_multi(int argc
, VALUE
*argv
, VALUE ary
)
5652 VALUE result
= rb_ary_dup(ary
);
5655 for (i
= 0; i
< argc
; i
++) {
5656 result
= rb_ary_and(result
, argv
[i
]);
5663 ary_hash_orset(st_data_t
*key
, st_data_t
*value
, st_data_t arg
, int existing
)
5665 if (existing
) return ST_STOP
;
5666 *key
= *value
= (VALUE
)arg
;
5671 rb_ary_union(VALUE ary_union
, VALUE ary
)
5674 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5675 VALUE elt
= rb_ary_elt(ary
, i
);
5676 if (rb_ary_includes_by_eql(ary_union
, elt
)) continue;
5677 rb_ary_push(ary_union
, elt
);
5682 rb_ary_union_hash(VALUE hash
, VALUE ary2
)
5685 for (i
= 0; i
< RARRAY_LEN(ary2
); i
++) {
5686 VALUE elt
= RARRAY_AREF(ary2
, i
);
5687 if (!rb_hash_stlike_update(hash
, (st_data_t
)elt
, ary_hash_orset
, (st_data_t
)elt
)) {
5688 RB_OBJ_WRITTEN(hash
, Qundef
, elt
);
5695 * array | other_array -> new_array
5697 * Returns the union of +array+ and +Array+ +other_array+;
5698 * duplicates are removed; order is preserved;
5699 * items are compared using <tt>eql?</tt>:
5701 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5702 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5703 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5705 * Related: Array#union.
5709 rb_ary_or(VALUE ary1
, VALUE ary2
)
5713 ary2
= to_ary(ary2
);
5714 if (RARRAY_LEN(ary1
) + RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5715 VALUE ary3
= rb_ary_new();
5716 rb_ary_union(ary3
, ary1
);
5717 rb_ary_union(ary3
, ary2
);
5721 hash
= ary_make_hash(ary1
);
5722 rb_ary_union_hash(hash
, ary2
);
5724 return rb_hash_values(hash
);
5729 * array.union(*other_arrays) -> new_array
5731 * Returns a new +Array+ that is the union of +self+ and all given Arrays +other_arrays+;
5732 * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
5734 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5735 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5736 * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
5738 * Returns a copy of +self+ if no arguments given.
5744 rb_ary_union_multi(int argc
, VALUE
*argv
, VALUE ary
)
5750 sum
= RARRAY_LEN(ary
);
5751 for (i
= 0; i
< argc
; i
++) {
5752 argv
[i
] = to_ary(argv
[i
]);
5753 sum
+= RARRAY_LEN(argv
[i
]);
5756 if (sum
<= SMALL_ARRAY_LEN
) {
5757 VALUE ary_union
= rb_ary_new();
5759 rb_ary_union(ary_union
, ary
);
5760 for (i
= 0; i
< argc
; i
++) rb_ary_union(ary_union
, argv
[i
]);
5765 hash
= ary_make_hash(ary
);
5766 for (i
= 0; i
< argc
; i
++) rb_ary_union_hash(hash
, argv
[i
]);
5768 return rb_hash_values(hash
);
5773 * intersect?(other_array) -> true or false
5775 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
5777 * [1, 2, 3].intersect?([3, 4, 5]) # => true
5778 * [1, 2, 3].intersect?([4, 5, 6]) # => false
5780 * Each element must correctly implement method <tt>#hash</tt>.
5782 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5786 rb_ary_intersect_p(VALUE ary1
, VALUE ary2
)
5788 VALUE hash
, v
, result
, shorter
, longer
;
5792 ary2
= to_ary(ary2
);
5793 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return Qfalse
;
5795 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5796 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5797 v
= RARRAY_AREF(ary1
, i
);
5798 if (rb_ary_includes_by_eql(ary2
, v
)) return Qtrue
;
5805 if (RARRAY_LEN(ary1
) > RARRAY_LEN(ary2
)) {
5810 hash
= ary_make_hash(shorter
);
5813 for (i
=0; i
<RARRAY_LEN(longer
); i
++) {
5814 v
= RARRAY_AREF(longer
, i
);
5816 if (rb_hash_stlike_lookup(hash
, vv
, 0)) {
5826 ary_max_generic(VALUE ary
, long i
, VALUE vmax
)
5828 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5831 for (; i
< RARRAY_LEN(ary
); ++i
) {
5832 v
= RARRAY_AREF(ary
, i
);
5834 if (rb_cmpint(rb_funcallv(vmax
, id_cmp
, 1, &v
), vmax
, v
) < 0) {
5843 ary_max_opt_fixnum(VALUE ary
, long i
, VALUE vmax
)
5845 const long n
= RARRAY_LEN(ary
);
5846 RUBY_ASSERT(i
> 0 && i
< n
);
5847 RUBY_ASSERT(FIXNUM_P(vmax
));
5850 for (; i
< n
; ++i
) {
5851 v
= RARRAY_AREF(ary
, i
);
5854 if ((long)vmax
< (long)v
) {
5859 return ary_max_generic(ary
, i
, vmax
);
5867 ary_max_opt_float(VALUE ary
, long i
, VALUE vmax
)
5869 const long n
= RARRAY_LEN(ary
);
5870 RUBY_ASSERT(i
> 0 && i
< n
);
5871 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax
));
5874 for (; i
< n
; ++i
) {
5875 v
= RARRAY_AREF(ary
, i
);
5877 if (RB_FLOAT_TYPE_P(v
)) {
5878 if (rb_float_cmp(vmax
, v
) < 0) {
5883 return ary_max_generic(ary
, i
, vmax
);
5891 ary_max_opt_string(VALUE ary
, long i
, VALUE vmax
)
5893 const long n
= RARRAY_LEN(ary
);
5894 RUBY_ASSERT(i
> 0 && i
< n
);
5895 RUBY_ASSERT(STRING_P(vmax
));
5898 for (; i
< n
; ++i
) {
5899 v
= RARRAY_AREF(ary
, i
);
5902 if (rb_str_cmp(vmax
, v
) < 0) {
5907 return ary_max_generic(ary
, i
, vmax
);
5917 * max(n) -> new_array
5918 * max {|a, b| ... } -> element
5919 * max(n) {|a, b| ... } -> new_array
5921 * Returns one of the following:
5923 * - The maximum-valued element from +self+.
5924 * - A new array of maximum-valued elements from +self+.
5926 * Does not modify +self+.
5928 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
5931 * With no argument and no block, returns the element in +self+
5932 * having the maximum value per method <tt>#<=></tt>:
5934 * [1, 0, 3, 2].max # => 3
5936 * With non-negative numeric argument +n+ and no block,
5937 * returns a new array with at most +n+ elements,
5938 * in descending order, per method <tt>#<=></tt>:
5940 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
5941 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
5942 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
5943 * [1, 0, 3, 2].max(0) # => []
5945 * With a block given, the block must return a numeric.
5947 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
5948 * returns the element having the maximum value per the block:
5950 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
5953 * With non-negative numeric argument +n+ and a block,
5954 * returns a new array with at most +n+ elements,
5955 * in descending order, per the block:
5957 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
5958 * # => ["000", "00"]
5960 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5963 rb_ary_max(int argc
, VALUE
*argv
, VALUE ary
)
5965 VALUE result
= Qundef
, v
;
5969 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
5970 return rb_nmin_run(ary
, num
, 0, 1, 1);
5972 const long n
= RARRAY_LEN(ary
);
5973 if (rb_block_given_p()) {
5974 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5975 v
= RARRAY_AREF(ary
, i
);
5976 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) > 0) {
5982 result
= RARRAY_AREF(ary
, 0);
5984 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
5985 return ary_max_opt_fixnum(ary
, 1, result
);
5987 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
5988 return ary_max_opt_string(ary
, 1, result
);
5990 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
5991 return ary_max_opt_float(ary
, 1, result
);
5994 return ary_max_generic(ary
, 1, result
);
5998 if (UNDEF_P(result
)) return Qnil
;
6003 ary_min_generic(VALUE ary
, long i
, VALUE vmin
)
6005 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
6008 for (; i
< RARRAY_LEN(ary
); ++i
) {
6009 v
= RARRAY_AREF(ary
, i
);
6011 if (rb_cmpint(rb_funcallv(vmin
, id_cmp
, 1, &v
), vmin
, v
) > 0) {
6020 ary_min_opt_fixnum(VALUE ary
, long i
, VALUE vmin
)
6022 const long n
= RARRAY_LEN(ary
);
6023 RUBY_ASSERT(i
> 0 && i
< n
);
6024 RUBY_ASSERT(FIXNUM_P(vmin
));
6027 for (; i
< n
; ++i
) {
6028 a
= RARRAY_AREF(ary
, i
);
6031 if ((long)vmin
> (long)a
) {
6036 return ary_min_generic(ary
, i
, vmin
);
6044 ary_min_opt_float(VALUE ary
, long i
, VALUE vmin
)
6046 const long n
= RARRAY_LEN(ary
);
6047 RUBY_ASSERT(i
> 0 && i
< n
);
6048 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin
));
6051 for (; i
< n
; ++i
) {
6052 a
= RARRAY_AREF(ary
, i
);
6054 if (RB_FLOAT_TYPE_P(a
)) {
6055 if (rb_float_cmp(vmin
, a
) > 0) {
6060 return ary_min_generic(ary
, i
, vmin
);
6068 ary_min_opt_string(VALUE ary
, long i
, VALUE vmin
)
6070 const long n
= RARRAY_LEN(ary
);
6071 RUBY_ASSERT(i
> 0 && i
< n
);
6072 RUBY_ASSERT(STRING_P(vmin
));
6075 for (; i
< n
; ++i
) {
6076 a
= RARRAY_AREF(ary
, i
);
6079 if (rb_str_cmp(vmin
, a
) > 0) {
6084 return ary_min_generic(ary
, i
, vmin
);
6094 * min(n) -> new_array
6095 * min {|a, b| ... } -> element
6096 * min(n) {|a, b| ... } -> new_array
6098 * Returns one of the following:
6100 * - The minimum-valued element from +self+.
6101 * - A new array of minimum-valued elements from +self+.
6103 * Does not modify +self+.
6105 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6108 * With no argument and no block, returns the element in +self+
6109 * having the minimum value per method <tt>#<=></tt>:
6111 * [1, 0, 3, 2].min # => 0
6113 * With non-negative numeric argument +n+ and no block,
6114 * returns a new array with at most +n+ elements,
6115 * in ascending order, per method <tt>#<=></tt>:
6117 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6118 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6119 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6120 * [1, 0, 3, 2].min(0) # => []
6122 * With a block given, the block must return a numeric.
6124 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6125 * returns the element having the minimum value per the block:
6127 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6130 * With non-negative numeric argument +n+ and a block,
6131 * returns a new array with at most +n+ elements,
6132 * in ascending order, per the block:
6134 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6137 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6140 rb_ary_min(int argc
, VALUE
*argv
, VALUE ary
)
6142 VALUE result
= Qundef
, v
;
6146 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
6147 return rb_nmin_run(ary
, num
, 0, 0, 1);
6149 const long n
= RARRAY_LEN(ary
);
6150 if (rb_block_given_p()) {
6151 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6152 v
= RARRAY_AREF(ary
, i
);
6153 if (UNDEF_P(result
) || rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) < 0) {
6159 result
= RARRAY_AREF(ary
, 0);
6161 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(INTEGER
)) {
6162 return ary_min_opt_fixnum(ary
, 1, result
);
6164 else if (STRING_P(result
) && CMP_OPTIMIZABLE(STRING
)) {
6165 return ary_min_opt_string(ary
, 1, result
);
6167 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(FLOAT
)) {
6168 return ary_min_opt_float(ary
, 1, result
);
6171 return ary_min_generic(ary
, 1, result
);
6175 if (UNDEF_P(result
)) return Qnil
;
6182 * minmax {|a, b| ... } -> array
6184 * Returns a 2-element array containing the minimum-valued and maximum-valued
6185 * elements from +self+;
6186 * does not modify +self+.
6188 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6190 * [1, 0, 3, 2].minmax # => [0, 3]
6192 * With a block given, the block must return a numeric;
6193 * the block is called <tt>self.size - 1</tt> times to compare elements;
6194 * returns the elements having the minimum and maximum values per the block:
6196 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6199 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6202 rb_ary_minmax(VALUE ary
)
6204 if (rb_block_given_p()) {
6205 return rb_call_super(0, NULL
);
6207 return rb_assoc_new(rb_ary_min(0, 0, ary
), rb_ary_max(0, 0, ary
));
6211 push_value(st_data_t key
, st_data_t val
, st_data_t ary
)
6213 rb_ary_push((VALUE
)ary
, (VALUE
)val
);
6219 * array.uniq! -> self or nil
6220 * array.uniq! {|element| ... } -> self or nil
6222 * Removes duplicate elements from +self+, the first occurrence always being retained;
6223 * returns +self+ if any elements removed, +nil+ otherwise.
6225 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6228 * Returns +self+ if any elements removed:
6230 * a = [0, 0, 1, 1, 2, 2]
6231 * a.uniq! # => [0, 1, 2]
6233 * Returns +nil+ if no elements removed.
6235 * With a block given, calls the block for each element;
6236 * identifies (using method <tt>eql?</tt>) and removes
6237 * elements for which the block returns duplicate values.
6239 * Returns +self+ if any elements removed:
6241 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6242 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
6244 * Returns +nil+ if no elements removed.
6247 rb_ary_uniq_bang(VALUE ary
)
6252 rb_ary_modify_check(ary
);
6253 if (RARRAY_LEN(ary
) <= 1)
6255 if (rb_block_given_p())
6256 hash
= ary_make_hash_by(ary
);
6258 hash
= ary_make_hash(ary
);
6260 hash_size
= RHASH_SIZE(hash
);
6261 if (RARRAY_LEN(ary
) == hash_size
) {
6264 rb_ary_modify_check(ary
);
6265 ARY_SET_LEN(ary
, 0);
6266 if (ARY_SHARED_P(ary
)) {
6267 rb_ary_unshare(ary
);
6270 ary_resize_capa(ary
, hash_size
);
6271 rb_hash_foreach(hash
, push_value
, ary
);
6278 * array.uniq -> new_array
6279 * array.uniq {|element| ... } -> new_array
6281 * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
6282 * the first occurrence always being retained.
6284 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
6287 * a = [0, 0, 1, 1, 2, 2]
6288 * a.uniq # => [0, 1, 2]
6290 * With a block given, calls the block for each element;
6291 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
6292 * that is, those elements for which the block returns the same value:
6294 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6295 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6300 rb_ary_uniq(VALUE ary
)
6304 if (RARRAY_LEN(ary
) <= 1) {
6306 uniq
= rb_ary_dup(ary
);
6308 else if (rb_block_given_p()) {
6309 hash
= ary_make_hash_by(ary
);
6310 uniq
= rb_hash_values(hash
);
6313 hash
= ary_make_hash(ary
);
6314 uniq
= rb_hash_values(hash
);
6322 * compact! -> self or nil
6324 * Removes all +nil+ elements from +self+;
6325 * Returns +self+ if any elements are removed, +nil+ otherwise:
6327 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6328 * a.compact! # => [0, false, "", [], {}]
6329 * a # => [0, false, "", [], {}]
6330 * a.compact! # => nil
6332 * Related: Array#compact;
6333 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6337 rb_ary_compact_bang(VALUE ary
)
6343 p
= t
= (VALUE
*)RARRAY_CONST_PTR(ary
); /* WB: no new reference */
6344 end
= p
+ RARRAY_LEN(ary
);
6350 n
= p
- RARRAY_CONST_PTR(ary
);
6351 if (RARRAY_LEN(ary
) == n
) {
6354 ary_resize_smaller(ary
, n
);
6361 * compact -> new_array
6363 * Returns a new array containing only the non-+nil+ elements from +self+;
6364 * element order is preserved:
6366 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6367 * a.compact # => [0, false, "", [], {}]
6369 * Related: Array#compact!;
6370 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6374 rb_ary_compact(VALUE ary
)
6376 ary
= rb_ary_dup(ary
);
6377 rb_ary_compact_bang(ary
);
6384 * count(object) -> integer
6385 * count {|element| ... } -> integer
6387 * Returns a count of specified elements.
6389 * With no argument and no block, returns the count of all elements:
6391 * [0, :one, 'two', 3, 3.0].count # => 5
6393 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6395 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6397 * With no argument and a block given, calls the block with each element;
6398 * returns the count of elements for which the block returns a truthy value:
6400 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6402 * With argument +object+ and a block given, issues a warning, ignores the block,
6403 * and returns the count of elements <tt>==</tt> to +object+.
6405 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6409 rb_ary_count(int argc
, VALUE
*argv
, VALUE ary
)
6413 if (rb_check_arity(argc
, 0, 1) == 0) {
6416 if (!rb_block_given_p())
6417 return LONG2NUM(RARRAY_LEN(ary
));
6419 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6420 v
= RARRAY_AREF(ary
, i
);
6421 if (RTEST(rb_yield(v
))) n
++;
6425 VALUE obj
= argv
[0];
6427 if (rb_block_given_p()) {
6428 rb_warn("given block not used");
6430 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6431 if (rb_equal(RARRAY_AREF(ary
, i
), obj
)) n
++;
6439 flatten(VALUE ary
, int level
)
6442 VALUE stack
, result
, tmp
= 0, elt
;
6443 VALUE memo
= Qfalse
;
6445 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6446 elt
= RARRAY_AREF(ary
, i
);
6447 tmp
= rb_check_array_type(elt
);
6452 if (i
== RARRAY_LEN(ary
)) {
6456 result
= ary_new(0, RARRAY_LEN(ary
));
6457 ary_memcpy(result
, 0, i
, RARRAY_CONST_PTR(ary
));
6458 ARY_SET_LEN(result
, i
);
6460 stack
= ary_new(0, ARY_DEFAULT_SIZE
);
6461 rb_ary_push(stack
, ary
);
6462 rb_ary_push(stack
, LONG2NUM(i
+ 1));
6465 memo
= rb_obj_hide(rb_ident_hash_new());
6466 rb_hash_aset(memo
, ary
, Qtrue
);
6467 rb_hash_aset(memo
, tmp
, Qtrue
);
6474 while (i
< RARRAY_LEN(ary
)) {
6475 elt
= RARRAY_AREF(ary
, i
++);
6476 if (level
>= 0 && RARRAY_LEN(stack
) / 2 >= level
) {
6477 rb_ary_push(result
, elt
);
6480 tmp
= rb_check_array_type(elt
);
6481 if (RBASIC(result
)->klass
) {
6483 rb_hash_clear(memo
);
6485 rb_raise(rb_eRuntimeError
, "flatten reentered");
6488 rb_ary_push(result
, elt
);
6492 if (rb_hash_aref(memo
, tmp
) == Qtrue
) {
6493 rb_hash_clear(memo
);
6494 rb_raise(rb_eArgError
, "tried to flatten recursive array");
6496 rb_hash_aset(memo
, tmp
, Qtrue
);
6498 rb_ary_push(stack
, ary
);
6499 rb_ary_push(stack
, LONG2NUM(i
));
6504 if (RARRAY_LEN(stack
) == 0) {
6508 rb_hash_delete(memo
, ary
);
6510 tmp
= rb_ary_pop(stack
);
6512 ary
= rb_ary_pop(stack
);
6516 rb_hash_clear(memo
);
6519 RBASIC_SET_CLASS(result
, rb_cArray
);
6525 * flatten!(depth = nil) -> self or nil
6527 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6528 * +depth+ must be an
6529 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6531 * At each level of recursion:
6533 * - Each element that is an array is "flattened"
6534 * (that is, replaced by its individual array elements).
6535 * - Each element that is not an array is unchanged
6536 * (even if the element is an object that has instance method +flatten+).
6538 * Returns +nil+ if no elements were flattened.
6540 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6542 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6543 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6544 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6545 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6546 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6547 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6549 * With +nil+ or negative argument +depth+, flattens all levels:
6551 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6552 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6554 * Related: Array#flatten;
6555 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6559 rb_ary_flatten_bang(int argc
, VALUE
*argv
, VALUE ary
)
6561 int mod
= 0, level
= -1;
6564 lv
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : Qnil
);
6565 rb_ary_modify_check(ary
);
6566 if (!NIL_P(lv
)) level
= NUM2INT(lv
);
6567 if (level
== 0) return Qnil
;
6569 result
= flatten(ary
, level
);
6570 if (result
== ary
) {
6573 if (!(mod
= ARY_EMBED_P(result
))) rb_ary_freeze(result
);
6574 rb_ary_replace(ary
, result
);
6575 if (mod
) ARY_SET_EMBED_LEN(result
, 0);
6582 * flatten(depth = nil) -> new_array
6584 * Returns a new array that is a recursive flattening of +self+
6585 * to +depth+ levels of recursion;
6586 * +depth+ must be an
6587 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6589 * At each level of recursion:
6591 * - Each element that is an array is "flattened"
6592 * (that is, replaced by its individual array elements).
6593 * - Each element that is not an array is unchanged
6594 * (even if the element is an object that has instance method +flatten+).
6596 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6598 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6599 * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6600 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
6601 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6602 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6603 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6604 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6606 * With +nil+ or negative +depth+, flattens all levels.
6608 * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6609 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
6611 * Related: Array#flatten!;
6612 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6616 rb_ary_flatten(int argc
, VALUE
*argv
, VALUE ary
)
6621 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0])) {
6622 level
= NUM2INT(argv
[0]);
6623 if (level
== 0) return ary_make_shared_copy(ary
);
6626 result
= flatten(ary
, level
);
6627 if (result
== ary
) {
6628 result
= ary_make_shared_copy(ary
);
6634 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6637 rb_ary_shuffle_bang(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6642 i
= len
= RARRAY_LEN(ary
);
6643 RARRAY_PTR_USE(ary
, ptr
, {
6645 long j
= RAND_UPTO(i
);
6647 if (len
!= RARRAY_LEN(ary
) || ptr
!= RARRAY_CONST_PTR(ary
)) {
6648 rb_raise(rb_eRuntimeError
, "modified during shuffle");
6654 }); /* WB: no new reference */
6659 rb_ary_shuffle(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6661 ary
= rb_ary_dup(ary
);
6662 rb_ary_shuffle_bang(ec
, ary
, randgen
);
6666 static const rb_data_type_t ary_sample_memo_type
= {
6667 .wrap_struct_name
= "ary_sample_memo",
6669 .dfree
= (RUBY_DATA_FUNC
)st_free_table
,
6671 .flags
= RUBY_TYPED_WB_PROTECTED
| RUBY_TYPED_FREE_IMMEDIATELY
6675 ary_sample(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
, VALUE nv
, VALUE to_array
)
6678 long n
, len
, i
, j
, k
, idx
[10];
6679 long rnds
[numberof(idx
)];
6680 long memo_threshold
;
6682 len
= RARRAY_LEN(ary
);
6689 return rb_ary_elt(ary
, i
);
6692 if (n
< 0) rb_raise(rb_eArgError
, "negative sample number");
6693 if (n
> len
) n
= len
;
6694 if (n
<= numberof(idx
)) {
6695 for (i
= 0; i
< n
; ++i
) {
6696 rnds
[i
] = RAND_UPTO(len
- i
);
6700 len
= RARRAY_LEN(ary
);
6701 if (len
< k
&& n
<= numberof(idx
)) {
6702 for (i
= 0; i
< n
; ++i
) {
6703 if (rnds
[i
] >= len
) return rb_ary_new_capa(0);
6706 if (n
> len
) n
= len
;
6709 return rb_ary_new_capa(0);
6712 return rb_ary_new_from_args(1, RARRAY_AREF(ary
, i
));
6717 return rb_ary_new_from_args(2, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
));
6724 if (j
>= i
) l
= i
, g
= ++j
;
6725 if (k
>= l
&& (++k
>= g
)) ++k
;
6727 return rb_ary_new_from_args(3, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
), RARRAY_AREF(ary
, k
));
6730 len
< 2560 ? len
/ 128 :
6731 len
< 5120 ? len
/ 64 :
6732 len
< 10240 ? len
/ 32 :
6734 if (n
<= numberof(idx
)) {
6735 long sorted
[numberof(idx
)];
6736 sorted
[0] = idx
[0] = rnds
[0];
6737 for (i
=1; i
<n
; i
++) {
6739 for (j
= 0; j
< i
; ++j
) {
6740 if (k
< sorted
[j
]) break;
6743 memmove(&sorted
[j
+1], &sorted
[j
], sizeof(sorted
[0])*(i
-j
));
6744 sorted
[j
] = idx
[i
] = k
;
6746 result
= rb_ary_new_capa(n
);
6747 RARRAY_PTR_USE(result
, ptr_result
, {
6748 for (i
=0; i
<n
; i
++) {
6749 ptr_result
[i
] = RARRAY_AREF(ary
, idx
[i
]);
6753 else if (n
<= memo_threshold
/ 2) {
6755 VALUE vmemo
= TypedData_Wrap_Struct(0, &ary_sample_memo_type
, 0);
6756 st_table
*memo
= st_init_numtable_with_size(n
);
6757 RTYPEDDATA_DATA(vmemo
) = memo
;
6758 result
= rb_ary_new_capa(n
);
6759 RARRAY_PTR_USE(result
, ptr_result
, {
6760 for (i
=0; i
<n
; i
++) {
6761 long r
= RAND_UPTO(len
-i
) + i
;
6763 if (r
> max_idx
) max_idx
= r
;
6765 len
= RARRAY_LEN(ary
);
6766 if (len
<= max_idx
) n
= 0;
6767 else if (n
> len
) n
= len
;
6768 RARRAY_PTR_USE(ary
, ptr_ary
, {
6769 for (i
=0; i
<n
; i
++) {
6770 long j2
= j
= ptr_result
[i
];
6773 if (st_lookup(memo
, (st_data_t
)i
, &value
)) i2
= (long)value
;
6774 if (st_lookup(memo
, (st_data_t
)j
, &value
)) j2
= (long)value
;
6775 st_insert(memo
, (st_data_t
)j
, (st_data_t
)i2
);
6776 ptr_result
[i
] = ptr_ary
[j2
];
6780 RTYPEDDATA_DATA(vmemo
) = 0;
6781 st_free_table(memo
);
6785 result
= rb_ary_dup(ary
);
6786 RBASIC_CLEAR_CLASS(result
);
6788 RARRAY_PTR_USE(result
, ptr_result
, {
6789 for (i
=0; i
<n
; i
++) {
6790 j
= RAND_UPTO(len
-i
) + i
;
6792 ptr_result
[j
] = ptr_result
[i
];
6796 RBASIC_SET_CLASS_RAW(result
, rb_cArray
);
6798 ARY_SET_LEN(result
, n
);
6804 ary_sample0(rb_execution_context_t
*ec
, VALUE ary
)
6806 return ary_sample(ec
, ary
, rb_cRandom
, Qfalse
, Qfalse
);
6810 rb_ary_cycle_size(VALUE self
, VALUE args
, VALUE eobj
)
6814 if (args
&& (RARRAY_LEN(args
) > 0)) {
6815 n
= RARRAY_AREF(args
, 0);
6817 if (RARRAY_LEN(self
) == 0) return INT2FIX(0);
6818 if (NIL_P(n
)) return DBL2NUM(HUGE_VAL
);
6820 if (mul
<= 0) return INT2FIX(0);
6822 return rb_fix_mul_fix(rb_ary_length(self
), n
);
6827 * cycle(count = nil) {|element| ... } -> nil
6828 * cycle(count = nil) -> new_enumerator
6830 * With a block given, may call the block, depending on the value of argument +count+;
6831 * +count+ must be an
6832 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6835 * When +count+ is positive,
6836 * calls the block with each element, then does so repeatedly,
6837 * until it has done so +count+ times; returns +nil+:
6840 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6841 * output # => [0, 1, 0, 1]
6843 * When +count+ is zero or negative, does not call the block:
6845 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6846 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6848 * When +count+ is +nil+, cycles forever:
6850 * # Prints 0 and 1 forever.
6851 * [0, 1].cycle {|element| puts element }
6852 * [0, 1].cycle(nil) {|element| puts element }
6854 * With no block given, returns a new Enumerator.
6856 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
6859 rb_ary_cycle(int argc
, VALUE
*argv
, VALUE ary
)
6863 rb_check_arity(argc
, 0, 1);
6865 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_cycle_size
);
6866 if (argc
== 0 || NIL_P(argv
[0])) {
6870 n
= NUM2LONG(argv
[0]);
6871 if (n
<= 0) return Qnil
;
6874 while (RARRAY_LEN(ary
) > 0 && (n
< 0 || 0 < n
--)) {
6875 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
6876 rb_yield(RARRAY_AREF(ary
, i
));
6883 * Build a ruby array of the corresponding values and yield it to the
6885 * Return the class of +values+ for reentry check.
6888 yield_indexed_values(const VALUE values
, const long r
, const long *const p
)
6890 const VALUE result
= rb_ary_new2(r
);
6893 for (i
= 0; i
< r
; i
++) ARY_SET(result
, i
, RARRAY_AREF(values
, p
[i
]));
6894 ARY_SET_LEN(result
, r
);
6896 return !RBASIC(values
)->klass
;
6900 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6902 * When we have a complete permutation of array indices, copy the values
6903 * at those indices into a new array and yield that array.
6905 * n: the size of the set
6906 * r: the number of elements in each permutation
6907 * p: the array (of size r) that we're filling in
6908 * used: an array of booleans: whether a given index is already used
6909 * values: the Ruby array that holds the actual values to permute
6912 permute0(const long n
, const long r
, long *const p
, char *const used
, const VALUE values
)
6914 long i
= 0, index
= 0;
6917 const char *const unused
= memchr(&used
[i
], 0, n
-i
);
6920 i
= p
[--index
]; /* pop index */
6921 used
[i
++] = 0; /* index unused */
6926 used
[i
] = 1; /* mark index used */
6928 if (index
< r
-1) { /* if not done yet */
6932 for (i
= 0; i
< n
; ++i
) {
6933 if (used
[i
]) continue;
6935 if (!yield_indexed_values(values
, r
, p
)) {
6936 rb_raise(rb_eRuntimeError
, "permute reentered");
6939 i
= p
[--index
]; /* pop index */
6940 used
[i
] = 0; /* index unused */
6947 * Returns the product of from, from-1, ..., from - how_many + 1.
6948 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6951 descending_factorial(long from
, long how_many
)
6955 cnt
= LONG2FIX(from
);
6956 while (--how_many
> 0) {
6958 cnt
= rb_int_mul(cnt
, LONG2FIX(v
));
6962 cnt
= LONG2FIX(how_many
== 0);
6968 binomial_coefficient(long comb
, long size
)
6972 if (comb
> size
-comb
) {
6978 else if (comb
== 0) {
6982 for (i
= 1; i
< comb
; ++i
) {
6983 r
= rb_int_mul(r
, LONG2FIX(size
- i
));
6984 r
= rb_int_idiv(r
, LONG2FIX(i
+ 1));
6990 rb_ary_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
6992 long n
= RARRAY_LEN(ary
);
6993 long k
= (args
&& (RARRAY_LEN(args
) > 0)) ? NUM2LONG(RARRAY_AREF(args
, 0)) : n
;
6995 return descending_factorial(n
, k
);
7000 * permutation(n = self.size) {|permutation| ... } -> self
7001 * permutation(n = self.size) -> new_enumerator
7003 * Iterates over permutations of the elements of +self+;
7004 * the order of permutations is indeterminate.
7006 * With a block and an in-range positive integer argument +n+ (<tt>0 < n <= self.size</tt>) given,
7007 * calls the block with each +n+-tuple permutations of +self+;
7012 * a.permutation(1) {|perm| perms.push(perm) }
7013 * perms # => [[0], [1], [2]]
7016 * a.permutation(2) {|perm| perms.push(perm) }
7017 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7020 * a.permutation(3) {|perm| perms.push(perm) }
7021 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7023 * When +n+ is zero, calls the block once with a new empty array:
7026 * a.permutation(0) {|perm| perms.push(perm) }
7029 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
7030 * does not call the block:
7032 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7033 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7035 * With no block given, returns a new Enumerator.
7037 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7041 rb_ary_permutation(int argc
, VALUE
*argv
, VALUE ary
)
7045 n
= RARRAY_LEN(ary
); /* Array length */
7046 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_permutation_size
); /* Return enumerator if no block */
7048 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0]))
7049 r
= NUM2LONG(argv
[0]); /* Permutation size from argument */
7051 if (r
< 0 || n
< r
) {
7052 /* no permutations: yield nothing */
7054 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7055 rb_yield(rb_ary_new2(0));
7057 else if (r
== 1) { /* this is a special, easy case */
7058 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7059 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7062 else { /* this is the general case */
7064 long *p
= ALLOCV_N(long, t0
, r
+roomof(n
, sizeof(long)));
7065 char *used
= (char*)(p
+ r
);
7066 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7067 RBASIC_CLEAR_CLASS(ary0
);
7069 MEMZERO(used
, char, n
); /* initialize array */
7071 permute0(n
, r
, p
, used
, ary0
); /* compute and yield permutations */
7073 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7079 combinate0(const long len
, const long n
, long *const stack
, const VALUE values
)
7083 MEMZERO(stack
+1, long, n
);
7086 for (lev
++; lev
< n
; lev
++) {
7087 stack
[lev
+1] = stack
[lev
]+1;
7089 if (!yield_indexed_values(values
, n
, stack
+1)) {
7090 rb_raise(rb_eRuntimeError
, "combination reentered");
7093 if (lev
== 0) return;
7095 } while (stack
[lev
+1]+n
== len
+lev
+1);
7100 rb_ary_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7102 long n
= RARRAY_LEN(ary
);
7103 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7105 return binomial_coefficient(k
, n
);
7110 * combination(n) {|element| ... } -> self
7111 * combination(n) -> new_enumerator
7113 * When a block and a positive
7114 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7115 * argument +n+ (<tt>0 < n <= self.size</tt>)
7116 * are given, calls the block with all +n+-tuple combinations of +self+;
7119 * a = %w[a b c] # => ["a", "b", "c"]
7120 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7128 * The order of the yielded combinations is not guaranteed.
7130 * When +n+ is zero, calls the block once with a new empty array:
7132 * a.combination(0) {|combination| p combination }
7133 * [].combination(0) {|combination| p combination }
7140 * When +n+ is negative or larger than +self.size+ and +self+ is non-empty,
7141 * does not call the block:
7143 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7144 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7146 * With no block given, returns a new Enumerator.
7148 * Related: Array#permutation;
7149 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7153 rb_ary_combination(VALUE ary
, VALUE num
)
7158 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_combination_size
);
7159 len
= RARRAY_LEN(ary
);
7160 if (n
< 0 || len
< n
) {
7164 rb_yield(rb_ary_new2(0));
7167 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7168 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7172 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7174 long *stack
= ALLOCV_N(long, t0
, n
+1);
7176 RBASIC_CLEAR_CLASS(ary0
);
7177 combinate0(len
, n
, stack
, ary0
);
7179 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7185 * Compute repeated permutations of +r+ elements of the set
7186 * <code>[0..n-1]</code>.
7188 * When we have a complete repeated permutation of array indices, copy the
7189 * values at those indices into a new array and yield that array.
7191 * n: the size of the set
7192 * r: the number of elements in each permutation
7193 * p: the array (of size r) that we're filling in
7194 * values: the Ruby array that holds the actual values to permute
7197 rpermute0(const long n
, const long r
, long *const p
, const VALUE values
)
7199 long i
= 0, index
= 0;
7203 if (++index
< r
-1) {
7207 for (i
= 0; i
< n
; ++i
) {
7209 if (!yield_indexed_values(values
, r
, p
)) {
7210 rb_raise(rb_eRuntimeError
, "repeated permute reentered");
7214 if (index
<= 0) return;
7215 } while ((i
= ++p
[--index
]) >= n
);
7220 rb_ary_repeated_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
7222 long n
= RARRAY_LEN(ary
);
7223 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7229 return LONG2FIX(!k
);
7231 return rb_int_positive_pow(n
, (unsigned long)k
);
7236 * array.repeated_permutation(n) {|permutation| ... } -> self
7237 * array.repeated_permutation(n) -> new_enumerator
7239 * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
7240 * each permutation is an +Array+;
7241 * returns +self+. The order of the permutations is indeterminate.
7243 * When a block and a positive Integer argument +n+ are given, calls the block with each
7244 * +n+-tuple repeated permutation of the elements of +self+.
7245 * The number of permutations is <tt>self.size**n</tt>.
7250 * a.repeated_permutation(1) {|permutation| p permutation }
7260 * a.repeated_permutation(2) {|permutation| p permutation }
7274 * If +n+ is zero, calls the block once with an empty +Array+.
7276 * If +n+ is negative, does not call the block:
7278 * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7280 * Returns a new Enumerator if no block given:
7283 * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
7285 * Using Enumerators, it's convenient to show the permutations and counts
7286 * for some values of +n+:
7288 * e = a.repeated_permutation(0)
7291 * e = a.repeated_permutation(1)
7293 * e.to_a # => [[0], [1], [2]]
7294 * e = a.repeated_permutation(2)
7296 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7300 rb_ary_repeated_permutation(VALUE ary
, VALUE num
)
7304 n
= RARRAY_LEN(ary
); /* Array length */
7305 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_permutation_size
); /* Return Enumerator if no block */
7306 r
= NUM2LONG(num
); /* Permutation size from argument */
7309 /* no permutations: yield nothing */
7311 else if (r
== 0) { /* exactly one permutation: the zero-length array */
7312 rb_yield(rb_ary_new2(0));
7314 else if (r
== 1) { /* this is a special, easy case */
7315 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7316 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7319 else { /* this is the general case */
7321 long *p
= ALLOCV_N(long, t0
, r
);
7322 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7323 RBASIC_CLEAR_CLASS(ary0
);
7325 rpermute0(n
, r
, p
, ary0
); /* compute and yield repeated permutations */
7327 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7333 rcombinate0(const long n
, const long r
, long *const p
, const long rest
, const VALUE values
)
7335 long i
= 0, index
= 0;
7339 if (++index
< r
-1) {
7343 for (; i
< n
; ++i
) {
7345 if (!yield_indexed_values(values
, r
, p
)) {
7346 rb_raise(rb_eRuntimeError
, "repeated combination reentered");
7350 if (index
<= 0) return;
7351 } while ((i
= ++p
[--index
]) >= n
);
7356 rb_ary_repeated_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7358 long n
= RARRAY_LEN(ary
);
7359 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7363 return binomial_coefficient(k
, n
+ k
- 1);
7368 * repeated_combination(size) {|combination| ... } -> self
7369 * repeated_combination(size) -> new_enumerator
7371 * With a block given, calls the block with each repeated combination of length +size+
7372 * of the elements of +self+;
7373 * each combination is an array;
7374 * returns +self+. The order of the combinations is indeterminate.
7376 * If a positive integer argument +size+ is given,
7377 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7378 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7385 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7386 * c # => [[0], [1], [2]]
7391 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7392 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7394 * If +size+ is zero, calls the block once with an empty array.
7396 * If +size+ is negative, does not call the block:
7398 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7400 * With no block given, returns a new Enumerator.
7402 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7406 rb_ary_repeated_combination(VALUE ary
, VALUE num
)
7410 n
= NUM2LONG(num
); /* Combination size from argument */
7411 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_combination_size
); /* Return enumerator if no block */
7412 len
= RARRAY_LEN(ary
);
7417 rb_yield(rb_ary_new2(0));
7420 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7421 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7424 else if (len
== 0) {
7429 long *p
= ALLOCV_N(long, t0
, n
);
7430 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7431 RBASIC_CLEAR_CLASS(ary0
);
7433 rcombinate0(len
, n
, p
, n
, ary0
); /* compute and yield repeated combinations */
7435 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7442 * product(*other_arrays) -> new_array
7443 * product(*other_arrays) {|combination| ... } -> self
7445 * Computes all combinations of elements from all the arrays,
7446 * including both +self+ and +other_arrays+:
7448 * - The number of combinations is the product of the sizes of all the arrays,
7449 * including both +self+ and +other_arrays+.
7450 * - The order of the returned combinations is indeterminate.
7452 * With no block given, returns the combinations as an array of arrays:
7454 * p = [0, 1].product([2, 3])
7455 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7457 * p = [0, 1].product([2, 3], [4, 5])
7458 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7461 * If +self+ or any argument is empty, returns an empty array:
7463 * [].product([2, 3], [4, 5]) # => []
7464 * [0, 1].product([2, 3], []) # => []
7466 * If no argument is given, returns an array of 1-element arrays,
7467 * each containing an element of +self+:
7469 * a.product # => [[0], [1], [2]]
7471 * With a block given, calls the block with each combination; returns +self+:
7474 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7475 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7477 * If +self+ or any argument is empty, does not call the block:
7479 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7481 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7484 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7487 * [0, 1].product {|combination| p.push(combination) }
7490 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7494 rb_ary_product(int argc
, VALUE
*argv
, VALUE ary
)
7496 int n
= argc
+1; /* How many arrays we're operating on */
7497 volatile VALUE t0
= rb_ary_hidden_new(n
);
7498 volatile VALUE t1
= Qundef
;
7499 VALUE
*arrays
= RARRAY_PTR(t0
); /* The arrays we're computing the product of */
7500 int *counters
= ALLOCV_N(int, t1
, n
); /* The current position in each one */
7501 VALUE result
= Qnil
; /* The array we'll be returning, when no block given */
7505 RBASIC_CLEAR_CLASS(t0
);
7507 /* initialize the arrays of arrays */
7510 for (i
= 1; i
< n
; i
++) arrays
[i
] = Qnil
;
7511 for (i
= 1; i
< n
; i
++) arrays
[i
] = to_ary(argv
[i
-1]);
7513 /* initialize the counters for the arrays */
7514 for (i
= 0; i
< n
; i
++) counters
[i
] = 0;
7516 /* Otherwise, allocate and fill in an array of results */
7517 if (rb_block_given_p()) {
7518 /* Make defensive copies of arrays; exit if any is empty */
7519 for (i
= 0; i
< n
; i
++) {
7520 if (RARRAY_LEN(arrays
[i
]) == 0) goto done
;
7521 arrays
[i
] = ary_make_shared_copy(arrays
[i
]);
7525 /* Compute the length of the result array; return [] if any is empty */
7526 for (i
= 0; i
< n
; i
++) {
7527 long k
= RARRAY_LEN(arrays
[i
]);
7529 result
= rb_ary_new2(0);
7532 if (MUL_OVERFLOW_LONG_P(resultlen
, k
))
7533 rb_raise(rb_eRangeError
, "too big to product");
7536 result
= rb_ary_new2(resultlen
);
7540 /* fill in one subarray */
7541 VALUE subarray
= rb_ary_new2(n
);
7542 for (j
= 0; j
< n
; j
++) {
7543 rb_ary_push(subarray
, rb_ary_entry(arrays
[j
], counters
[j
]));
7546 /* put it on the result array */
7547 if (NIL_P(result
)) {
7548 FL_SET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7550 if (!FL_TEST(t0
, RARRAY_SHARED_ROOT_FLAG
)) {
7551 rb_raise(rb_eRuntimeError
, "product reentered");
7554 FL_UNSET(t0
, RARRAY_SHARED_ROOT_FLAG
);
7558 rb_ary_push(result
, subarray
);
7562 * Increment the last counter. If it overflows, reset to 0
7563 * and increment the one before it.
7567 while (counters
[m
] == RARRAY_LEN(arrays
[m
])) {
7569 /* If the first counter overflows, we are done */
7570 if (--m
< 0) goto done
;
7578 return NIL_P(result
) ? ary
: result
;
7583 * array.take(n) -> new_array
7585 * Returns a new +Array+ containing the first +n+ element of +self+,
7586 * where +n+ is a non-negative Integer;
7587 * does not modify +self+.
7591 * a = [0, 1, 2, 3, 4, 5]
7592 * a.take(1) # => [0]
7593 * a.take(2) # => [0, 1]
7594 * a.take(50) # => [0, 1, 2, 3, 4, 5]
7595 * a # => [0, 1, 2, 3, 4, 5]
7600 rb_ary_take(VALUE obj
, VALUE n
)
7602 long len
= NUM2LONG(n
);
7604 rb_raise(rb_eArgError
, "attempt to take negative size");
7606 return rb_ary_subseq(obj
, 0, len
);
7611 * array.take_while {|element| ... } -> new_array
7612 * array.take_while -> new_enumerator
7614 * Returns a new +Array+ containing zero or more leading elements of +self+;
7615 * does not modify +self+.
7617 * With a block given, calls the block with each successive element of +self+;
7618 * stops if the block returns +false+ or +nil+;
7619 * returns a new +Array+ containing those elements for which the block returned a truthy value:
7621 * a = [0, 1, 2, 3, 4, 5]
7622 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7623 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7624 * a # => [0, 1, 2, 3, 4, 5]
7626 * With no block given, returns a new Enumerator:
7628 * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
7633 rb_ary_take_while(VALUE ary
)
7637 RETURN_ENUMERATOR(ary
, 0, 0);
7638 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7639 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7641 return rb_ary_take(ary
, LONG2FIX(i
));
7646 * drop(n) -> new_array
7648 * Returns a new array containing all but the first +n+ element of +self+,
7649 * where +n+ is a non-negative Integer;
7650 * does not modify +self+.
7654 * a = [0, 1, 2, 3, 4, 5]
7655 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7656 * a.drop(1) # => [1, 2, 3, 4, 5]
7657 * a.drop(2) # => [2, 3, 4, 5]
7660 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7664 rb_ary_drop(VALUE ary
, VALUE n
)
7667 long pos
= NUM2LONG(n
);
7669 rb_raise(rb_eArgError
, "attempt to drop negative size");
7672 result
= rb_ary_subseq(ary
, pos
, RARRAY_LEN(ary
));
7673 if (NIL_P(result
)) result
= rb_ary_new();
7679 * drop_while {|element| ... } -> new_array
7680 * drop_while -> new_enumerator
7682 * With a block given, calls the block with each successive element of +self+;
7683 * stops if the block returns +false+ or +nil+;
7684 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7685 * does not modify +self+:
7687 * a = [0, 1, 2, 3, 4, 5]
7688 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7690 * With no block given, returns a new Enumerator.
7692 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7696 rb_ary_drop_while(VALUE ary
)
7700 RETURN_ENUMERATOR(ary
, 0, 0);
7701 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7702 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7704 return rb_ary_drop(ary
, LONG2FIX(i
));
7709 * any? -> true or false
7710 * any?(object) -> true or false
7711 * any? {|element| ... } -> true or false
7713 * Returns whether for any element of +self+, a given criterion is satisfied.
7715 * With no block and no argument, returns whether any element of +self+ is truthy:
7717 * [nil, false, []].any? # => true # Array object is truthy.
7718 * [nil, false, {}].any? # => true # Hash object is truthy.
7719 * [nil, false, ''].any? # => true # String object is truthy.
7720 * [nil, false].any? # => false # Nil and false are not truthy.
7722 * With argument +object+ given,
7723 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
7725 * [nil, false, 0].any?(0) # => true
7726 * [nil, false, 1].any?(0) # => false
7727 * [nil, false, 'food'].any?(/foo/) # => true
7728 * [nil, false, 'food'].any?(/bar/) # => false
7730 * With a block given,
7731 * calls the block with each element in +self+;
7732 * returns whether the block returns any truthy value:
7734 * [0, 1, 2].any? {|ele| ele < 1 } # => true
7735 * [0, 1, 2].any? {|ele| ele < 0 } # => false
7737 * With both a block and argument +object+ given,
7738 * ignores the block and uses +object+ as above.
7740 * <b>Special case</b>: returns +false+ if +self+ is empty
7741 * (regardless of any given argument or block).
7743 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7747 rb_ary_any_p(int argc
, VALUE
*argv
, VALUE ary
)
7749 long i
, len
= RARRAY_LEN(ary
);
7751 rb_check_arity(argc
, 0, 1);
7752 if (!len
) return Qfalse
;
7754 if (rb_block_given_p()) {
7755 rb_warn("given block not used");
7757 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7758 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qtrue
;
7761 else if (!rb_block_given_p()) {
7762 for (i
= 0; i
< len
; ++i
) {
7763 if (RTEST(RARRAY_AREF(ary
, i
))) return Qtrue
;
7767 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7768 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qtrue
;
7776 * all? -> true or false
7777 * all?(object) -> true or false
7778 * all? {|element| ... } -> true or false
7780 * Returns whether for every element of +self+,
7781 * a given criterion is satisfied.
7783 * With no block and no argument,
7784 * returns whether every element of +self+ is truthy:
7786 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
7787 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
7788 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
7790 * With argument +object+ given, returns whether <tt>object === ele</tt>
7791 * for every element +ele+ in +self+:
7793 * [0, 0, 0].all?(0) # => true
7794 * [0, 1, 2].all?(1) # => false
7795 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7796 * ['food', 'drink'].all?(/foo/) # => false
7798 * With a block given, calls the block with each element in +self+;
7799 * returns whether the block returns only truthy values:
7801 * [0, 1, 2].all? { |ele| ele < 3 } # => true
7802 * [0, 1, 2].all? { |ele| ele < 2 } # => false
7804 * With both a block and argument +object+ given,
7805 * ignores the block and uses +object+ as above.
7807 * <b>Special case</b>: returns +true+ if +self+ is empty
7808 * (regardless of any given argument or block).
7810 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7814 rb_ary_all_p(int argc
, VALUE
*argv
, VALUE ary
)
7816 long i
, len
= RARRAY_LEN(ary
);
7818 rb_check_arity(argc
, 0, 1);
7819 if (!len
) return Qtrue
;
7821 if (rb_block_given_p()) {
7822 rb_warn("given block not used");
7824 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7825 if (!RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7828 else if (!rb_block_given_p()) {
7829 for (i
= 0; i
< len
; ++i
) {
7830 if (!RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7834 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7835 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7843 * none? -> true or false
7844 * none?(object) -> true or false
7845 * none? {|element| ... } -> true or false
7847 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
7849 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7850 * +false+ otherwise:
7852 * [nil, false].none? # => true
7853 * [nil, 0, false].none? # => false
7854 * [].none? # => true
7856 * With argument +object+ given, returns +false+ if for any element +element+,
7857 * <tt>object === element</tt>; +true+ otherwise:
7859 * ['food', 'drink'].none?(/bar/) # => true
7860 * ['food', 'drink'].none?(/foo/) # => false
7861 * [].none?(/foo/) # => true
7862 * [0, 1, 2].none?(3) # => true
7863 * [0, 1, 2].none?(1) # => false
7865 * With a block given, calls the block with each element in +self+;
7866 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7868 * [0, 1, 2].none? {|element| element > 3 } # => true
7869 * [0, 1, 2].none? {|element| element > 1 } # => false
7871 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7875 rb_ary_none_p(int argc
, VALUE
*argv
, VALUE ary
)
7877 long i
, len
= RARRAY_LEN(ary
);
7879 rb_check_arity(argc
, 0, 1);
7880 if (!len
) return Qtrue
;
7882 if (rb_block_given_p()) {
7883 rb_warn("given block not used");
7885 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7886 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7889 else if (!rb_block_given_p()) {
7890 for (i
= 0; i
< len
; ++i
) {
7891 if (RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7895 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7896 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7904 * one? -> true or false
7905 * one? {|element| ... } -> true or false
7906 * one?(object) -> true or false
7908 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7910 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7911 * +false+ otherwise:
7913 * [nil, 0].one? # => true
7914 * [0, 0].one? # => false
7915 * [nil, nil].one? # => false
7916 * [].one? # => false
7918 * With a block given, calls the block with each element in +self+;
7919 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7921 * [0, 1, 2].one? {|element| element > 0 } # => false
7922 * [0, 1, 2].one? {|element| element > 1 } # => true
7923 * [0, 1, 2].one? {|element| element > 2 } # => false
7925 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
7926 * +false+ otherwise:
7928 * [0, 1, 2].one?(0) # => true
7929 * [0, 0, 1].one?(0) # => false
7930 * [1, 1, 2].one?(0) # => false
7931 * ['food', 'drink'].one?(/bar/) # => false
7932 * ['food', 'drink'].one?(/foo/) # => true
7933 * [].one?(/foo/) # => false
7935 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
7939 rb_ary_one_p(int argc
, VALUE
*argv
, VALUE ary
)
7941 long i
, len
= RARRAY_LEN(ary
);
7942 VALUE result
= Qfalse
;
7944 rb_check_arity(argc
, 0, 1);
7945 if (!len
) return Qfalse
;
7947 if (rb_block_given_p()) {
7948 rb_warn("given block not used");
7950 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7951 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) {
7952 if (result
) return Qfalse
;
7957 else if (!rb_block_given_p()) {
7958 for (i
= 0; i
< len
; ++i
) {
7959 if (RTEST(RARRAY_AREF(ary
, i
))) {
7960 if (result
) return Qfalse
;
7966 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7967 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
7968 if (result
) return Qfalse
;
7978 * array.dig(index, *identifiers) -> object
7980 * Finds and returns the object in nested object
7981 * specified by +index+ and +identifiers+;
7982 * the nested objects may be instances of various classes.
7983 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
7987 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
7988 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
7989 * a.dig(1, 2) # => [:bat, :bam]
7990 * a.dig(1, 2, 0) # => :bat
7991 * a.dig(1, 2, 3) # => nil
7993 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7997 rb_ary_dig(int argc
, VALUE
*argv
, VALUE self
)
7999 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
8000 self
= rb_ary_at(self
, *argv
);
8001 if (!--argc
) return self
;
8003 return rb_obj_dig(argc
, argv
, self
, Qnil
);
8007 finish_exact_sum(long n
, VALUE r
, VALUE v
, int z
)
8010 v
= rb_fix_plus(LONG2FIX(n
), v
);
8012 v
= rb_rational_plus(r
, v
);
8015 v
= rb_fix_plus(LONG2FIX(0), v
);
8022 * array.sum(init = 0) -> object
8023 * array.sum(init = 0) {|element| ... } -> object
8025 * When no block is given, returns the object equivalent to:
8028 * array.each {|element| sum += element }
8031 * For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
8037 * a.sum(100) # => 106
8039 * The elements need not be numeric, but must be <tt>+</tt>-compatible
8040 * with each other and with +init+:
8042 * a = ['abc', 'def', 'ghi']
8043 * a.sum('jkl') # => "jklabcdefghi"
8045 * When a block is given, it is called with each element
8046 * and the block's return value (instead of the element itself) is used as the addend:
8048 * a = ['zero', 1, :two]
8049 * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
8050 * s # => "Coerced and concatenated: zero1two"
8054 * - Array#join and Array#flatten may be faster than Array#sum
8055 * for an +Array+ of Strings or an +Array+ of Arrays.
8056 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8061 rb_ary_sum(int argc
, VALUE
*argv
, VALUE ary
)
8067 v
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : LONG2FIX(0));
8069 block_given
= rb_block_given_p();
8071 if (RARRAY_LEN(ary
) == 0)
8077 if (!FIXNUM_P(v
) && !RB_BIGNUM_TYPE_P(v
) && !RB_TYPE_P(v
, T_RATIONAL
)) {
8079 goto init_is_a_value
;
8082 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
8083 e
= RARRAY_AREF(ary
, i
);
8087 n
+= FIX2LONG(e
); /* should not overflow long type */
8089 v
= rb_big_plus(LONG2NUM(n
), v
);
8093 else if (RB_BIGNUM_TYPE_P(e
))
8094 v
= rb_big_plus(e
, v
);
8095 else if (RB_TYPE_P(e
, T_RATIONAL
)) {
8099 r
= rb_rational_plus(r
, e
);
8104 v
= finish_exact_sum(n
, r
, v
, argc
!=0);
8108 v
= finish_exact_sum(n
, r
, v
, i
!=0);
8110 if (RB_FLOAT_TYPE_P(e
)) {
8112 * Kahan-Babuska balancing compensated summation algorithm
8113 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8120 goto has_float_value
;
8121 for (; i
< RARRAY_LEN(ary
); i
++) {
8122 e
= RARRAY_AREF(ary
, i
);
8125 if (RB_FLOAT_TYPE_P(e
))
8127 x
= RFLOAT_VALUE(e
);
8128 else if (FIXNUM_P(e
))
8130 else if (RB_BIGNUM_TYPE_P(e
))
8132 else if (RB_TYPE_P(e
, T_RATIONAL
))
8137 if (isnan(f
)) continue;
8143 if (isinf(f
) && signbit(x
) != signbit(f
))
8149 if (isinf(f
)) continue;
8152 if (fabs(f
) >= fabs(x
))
8165 goto has_some_value
;
8167 for (; i
< RARRAY_LEN(ary
); i
++) {
8168 e
= RARRAY_AREF(ary
, i
);
8172 v
= rb_funcall(v
, idPLUS
, 1, e
);
8179 rb_ary_deconstruct(VALUE ary
)
8185 * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
8186 * Any object (even another array) may be an array element,
8187 * and an array can contain objects of different types.
8189 * == +Array+ Indexes
8191 * +Array+ indexing starts at 0, as in C or Java.
8193 * A positive index is an offset from the first element:
8195 * - Index 0 indicates the first element.
8196 * - Index 1 indicates the second element.
8199 * A negative index is an offset, backwards, from the end of the array:
8201 * - Index -1 indicates the last element.
8202 * - Index -2 indicates the next-to-last element.
8205 * A non-negative index is <i>in range</i> if and only if it is smaller than
8206 * the size of the array. For a 3-element array:
8208 * - Indexes 0 through 2 are in range.
8209 * - Index 3 is out of range.
8211 * A negative index is <i>in range</i> if and only if its absolute value is
8212 * not larger than the size of the array. For a 3-element array:
8214 * - Indexes -1 through -3 are in range.
8215 * - Index -4 is out of range.
8217 * Although the effective index into an array is always an integer,
8218 * some methods (both within and outside of class +Array+)
8219 * accept one or more non-integer arguments that are
8220 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8223 * == Creating Arrays
8225 * You can create an +Array+ object explicitly with:
8227 * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
8229 * [1, 'one', :one, [2, 'two', :two]]
8231 * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
8233 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8234 * %w[1 % *] # => ["1", "%", "*"]
8236 * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
8238 * %i[foo bar baz] # => [:foo, :bar, :baz]
8239 * %i[1 % *] # => [:"1", :%, :*]
8241 * - \Method Kernel#Array:
8243 * Array(["a", "b"]) # => ["a", "b"]
8244 * Array(1..5) # => [1, 2, 3, 4, 5]
8245 * Array(key: :value) # => [[:key, :value]]
8246 * Array(nil) # => []
8248 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8250 * - \Method Array.new:
8253 * Array.new(3) # => [nil, nil, nil]
8254 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8255 * Array.new(3, true) # => [true, true, true]
8257 * Note that the last example above populates the array
8258 * with references to the same object.
8259 * This is recommended only in cases where that object is a natively immutable object
8260 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8262 * Another way to create an array with various objects, using a block;
8263 * this usage is safe for mutable objects such as hashes, strings or
8266 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8268 * Here is a way to create a multi-dimensional array:
8270 * Array.new(3) {Array.new(3)}
8271 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8273 * A number of Ruby methods, both in the core and in the standard library,
8274 * provide instance method +to_a+, which converts an object to an array.
8282 * - OptionParser#to_a
8287 * - Benchmark::Tms#to_a
8289 * - Enumerator::Lazy#to_a
8291 * - Gem::NameTuple#to_a
8292 * - Gem::Platform#to_a
8293 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8294 * - Gem::SourceList#to_a
8295 * - OpenSSL::X509::Extension#to_a
8296 * - OpenSSL::X509::Name#to_a
8298 * - Rinda::RingFinger#to_a
8299 * - Ripper::Lexer::Elem#to_a
8300 * - RubyVM::InstructionSequence#to_a
8305 * In addition to the methods it mixes in through the Enumerable module, the
8306 * +Array+ class has proprietary methods for accessing, searching and otherwise
8307 * manipulating arrays.
8309 * Some of the more common ones are illustrated below.
8311 * == Accessing Elements
8313 * Elements in an array can be retrieved using the Array#[] method. It can
8314 * take a single integer argument (a numeric index), a pair of arguments
8315 * (start and length) or a range. Negative indices start counting from the end,
8316 * with -1 being the last element.
8318 * arr = [1, 2, 3, 4, 5, 6]
8322 * arr[2, 3] #=> [3, 4, 5]
8323 * arr[1..4] #=> [2, 3, 4, 5]
8324 * arr[1..-3] #=> [2, 3, 4]
8326 * Another way to access a particular array element is by using the #at method
8330 * The #slice method works in an identical manner to Array#[].
8332 * To raise an error for indices outside of the array bounds or else to
8333 * provide a default value when that happens, you can use #fetch.
8335 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8336 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8337 * arr.fetch(100, "oops") #=> "oops"
8339 * The special methods #first and #last will return the first and last
8340 * elements of an array, respectively.
8345 * To return the first +n+ elements of an array, use #take
8347 * arr.take(3) #=> [1, 2, 3]
8349 * #drop does the opposite of #take, by returning the elements after +n+
8350 * elements have been dropped:
8352 * arr.drop(3) #=> [4, 5, 6]
8354 * == Obtaining Information about an +Array+
8356 * Arrays keep track of their own length at all times. To query an array
8357 * about the number of elements it contains, use #length, #count or #size.
8359 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8360 * browsers.length #=> 5
8361 * browsers.count #=> 5
8363 * To check whether an array contains any elements at all
8365 * browsers.empty? #=> false
8367 * To check whether a particular item is included in the array
8369 * browsers.include?('Konqueror') #=> false
8371 * == Adding Items to Arrays
8373 * Items can be added to the end of an array by using either #push or #<<
8375 * arr = [1, 2, 3, 4]
8376 * arr.push(5) #=> [1, 2, 3, 4, 5]
8377 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8379 * #unshift will add a new item to the beginning of an array.
8381 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8383 * With #insert you can add a new element to an array at any position.
8385 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8387 * Using the #insert method, you can also insert multiple values at once:
8389 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8390 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8392 * == Removing Items from an +Array+
8394 * The method #pop removes the last element in an array and returns it:
8396 * arr = [1, 2, 3, 4, 5, 6]
8398 * arr #=> [1, 2, 3, 4, 5]
8400 * To retrieve and at the same time remove the first item, use #shift:
8403 * arr #=> [2, 3, 4, 5]
8405 * To delete an element at a particular index:
8407 * arr.delete_at(2) #=> 4
8410 * To delete a particular element anywhere in an array, use #delete:
8412 * arr = [1, 2, 2, 3]
8413 * arr.delete(2) #=> 2
8416 * A useful method if you need to remove +nil+ values from an array is
8419 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8420 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8421 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8422 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8423 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8425 * Another common need is to remove duplicate elements from an array.
8427 * It has the non-destructive #uniq, and destructive method #uniq!
8429 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8430 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8432 * == Iterating over Arrays
8434 * Like all classes that include the Enumerable module, +Array+ has an each
8435 * method, which defines what elements should be iterated over and how. In
8436 * case of Array's #each, all elements in the +Array+ instance are yielded to
8437 * the supplied block in sequence.
8439 * Note that this operation leaves the array unchanged.
8441 * arr = [1, 2, 3, 4, 5]
8442 * arr.each {|a| print a -= 10, " "}
8443 * # prints: -9 -8 -7 -6 -5
8444 * #=> [1, 2, 3, 4, 5]
8446 * Another sometimes useful iterator is #reverse_each which will iterate over
8447 * the elements in the array in reverse order.
8449 * words = %w[first second third fourth fifth sixth]
8451 * words.reverse_each {|word| str += "#{word} "}
8452 * p str #=> "sixth fifth fourth third second first "
8454 * The #map method can be used to create a new array based on the original
8455 * array, but with the values modified by the supplied block:
8457 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8458 * arr #=> [1, 2, 3, 4, 5]
8459 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8460 * arr #=> [1, 4, 9, 16, 25]
8463 * == Selecting Items from an +Array+
8465 * Elements can be selected from an array according to criteria defined in a
8466 * block. The selection can happen in a destructive or a non-destructive
8467 * manner. While the destructive operations will modify the array they were
8468 * called on, the non-destructive methods usually return a new array with the
8469 * selected elements, but leave the original array unchanged.
8471 * === Non-destructive Selection
8473 * arr = [1, 2, 3, 4, 5, 6]
8474 * arr.select {|a| a > 3} #=> [4, 5, 6]
8475 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8476 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8477 * arr #=> [1, 2, 3, 4, 5, 6]
8479 * === Destructive Selection
8481 * #select! and #reject! are the corresponding destructive methods to #select
8484 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8485 * opposite result when supplied with the same block:
8487 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8490 * arr = [1, 2, 3, 4, 5, 6]
8491 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8496 * First, what's elsewhere. \Class +Array+:
8498 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
8499 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
8500 * which provides dozens of additional methods.
8502 * Here, class +Array+ provides methods that are useful for:
8504 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8505 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8506 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8507 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8508 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8509 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8510 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8511 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8512 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8513 * - {And more....}[rdoc-ref:Array@Other+Methods]
8515 * === Methods for Creating an +Array+
8517 * - ::[]: Returns a new array populated with given objects.
8518 * - ::new: Returns a new array.
8519 * - ::try_convert: Returns a new array created from a given object.
8521 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8523 * === Methods for Querying
8525 * - #length (aliased as #size): Returns the count of elements.
8526 * - #include?: Returns whether any element <tt>==</tt> a given object.
8527 * - #empty?: Returns whether there are no elements.
8528 * - #all?: Returns whether all elements meet a given criterion.
8529 * - #any?: Returns whether any element meets a given criterion.
8530 * - #none?: Returns whether no element <tt>==</tt> a given object.
8531 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8532 * - #count: Returns the count of elements that meet a given criterion.
8533 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8534 * - #rindex: Returns the index of the last element that meets a given criterion.
8535 * - #hash: Returns the integer hash code.
8537 * === Methods for Comparing
8539 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or
8540 * greater than a given object.
8541 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
8542 * in a given object.
8543 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8544 * element in a given object.
8546 * === Methods for Fetching
8548 * These methods do not modify +self+.
8550 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8551 * - #fetch: Returns the element at a given offset.
8552 * - #fetch_values: Returns elements at given offsets.
8553 * - #first: Returns one or more leading elements.
8554 * - #last: Returns one or more trailing elements.
8555 * - #max: Returns one or more maximum-valued elements,
8556 * as determined by <tt>#<=></tt> or a given block.
8557 * - #min: Returns one or more minimum-valued elements,
8558 * as determined by <tt>#<=></tt> or a given block.
8559 * - #minmax: Returns the minimum-valued and maximum-valued elements,
8560 * as determined by <tt>#<=></tt> or a given block.
8561 * - #assoc: Returns the first element that is an array
8562 * whose first element <tt>==</tt> a given object.
8563 * - #rassoc: Returns the first element that is an array
8564 * whose second element <tt>==</tt> a given object.
8565 * - #at: Returns the element at a given offset.
8566 * - #values_at: Returns the elements at given offsets.
8567 * - #dig: Returns the object in nested objects
8568 * that is specified by a given index and additional arguments.
8569 * - #drop: Returns trailing elements as determined by a given index.
8570 * - #take: Returns leading elements as determined by a given index.
8571 * - #drop_while: Returns trailing elements as determined by a given block.
8572 * - #take_while: Returns leading elements as determined by a given block.
8573 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8574 * - #reverse: Returns all elements in reverse order.
8575 * - #compact: Returns an array containing all non-+nil+ elements.
8576 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8577 * - #uniq: Returns an array containing non-duplicate elements.
8578 * - #rotate: Returns all elements with some rotated from one end to the other.
8579 * - #bsearch: Returns an element selected via a binary search
8580 * as determined by a given block.
8581 * - #bsearch_index: Returns the index of an element selected via a binary search
8582 * as determined by a given block.
8583 * - #sample: Returns one or more random elements.
8584 * - #shuffle: Returns elements in a random order.
8585 * - #reject: Returns an array containing elements not rejected by a given block.
8587 * === Methods for Assigning
8589 * These methods add, replace, or reorder elements in +self+.
8591 * - #[]=: Assigns specified elements with a given object.
8592 * - #<<: Appends an element.
8593 * - #push (aliased as #append): Appends elements.
8594 * - #unshift (aliased as #prepend): Prepends leading elements.
8595 * - #insert: Inserts given objects at a given offset; does not replace elements.
8596 * - #concat: Appends all elements from given arrays.
8597 * - #fill: Replaces specified elements with specified objects.
8598 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8599 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8600 * - #reverse!: Replaces +self+ with its elements reversed.
8601 * - #rotate!: Replaces +self+ with its elements rotated.
8602 * - #shuffle!: Replaces +self+ with its elements in random order.
8603 * - #sort!: Replaces +self+ with its elements sorted,
8604 * as determined by <tt>#<=></tt> or a given block.
8605 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8607 * === Methods for Deleting
8609 * Each of these methods removes elements from +self+:
8611 * - #pop: Removes and returns the last element.
8612 * - #shift: Removes and returns the first element.
8613 * - #compact!: Removes all +nil+ elements.
8614 * - #delete: Removes elements equal to a given object.
8615 * - #delete_at: Removes the element at a given offset.
8616 * - #delete_if: Removes elements specified by a given block.
8617 * - #clear: Removes all elements.
8618 * - #keep_if: Removes elements not specified by a given block.
8619 * - #reject!: Removes elements specified by a given block.
8620 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8621 * - #slice!: Removes and returns a sequence of elements.
8622 * - #uniq!: Removes duplicates.
8624 * === Methods for Combining
8626 * - #&: Returns an array containing elements found both in +self+ and a given array.
8627 * - #intersection: Returns an array containing elements found both in +self+
8628 * and in each given array.
8629 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8630 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8631 * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
8632 * duplicates removed.
8633 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
8634 * duplicates removed.
8635 * - #difference: Returns an array containing all elements of +self+ that are not found
8636 * in any of the given arrays..
8637 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8638 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8640 * === Methods for Iterating
8642 * - #each: Passes each element to a given block.
8643 * - #reverse_each: Passes each element, in reverse order, to a given block.
8644 * - #each_index: Passes each element index to a given block.
8645 * - #cycle: Calls a given block with each element, then does so again,
8646 * for a specified number of times, or forever.
8647 * - #combination: Calls a given block with combinations of elements of +self+;
8648 * a combination does not use the same element more than once.
8649 * - #permutation: Calls a given block with permutations of elements of +self+;
8650 * a permutation does not use the same element more than once.
8651 * - #repeated_combination: Calls a given block with combinations of elements of +self+;
8652 * a combination may use the same element more than once.
8653 * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
8654 * a permutation may use the same element more than once.
8656 * === Methods for Converting
8658 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8659 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8660 * - #flatten: Returns an array that is a recursive flattening of +self+.
8661 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8662 * - #join: Returns a newsString containing the elements joined by the field separator.
8663 * - #to_a: Returns +self+ or a new array containing all elements.
8664 * - #to_ary: Returns +self+.
8665 * - #to_h: Returns a new hash formed from the elements.
8666 * - #transpose: Transposes +self+, which must be an array of arrays.
8667 * - #zip: Returns a new array of arrays containing +self+ and given arrays;
8668 * follow the link for details.
8672 * - #*: Returns one of the following:
8674 * - With integer argument +n+, a new array that is the concatenation
8675 * of +n+ copies of +self+.
8676 * - With string argument +field_separator+, a new string that is equivalent to
8677 * <tt>join(field_separator)</tt>.
8679 * - #pack: Packs the elements into a binary sequence.
8680 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8686 fake_ary_flags
= init_fake_ary_flags();
8688 rb_cArray
= rb_define_class("Array", rb_cObject
);
8689 rb_include_module(rb_cArray
, rb_mEnumerable
);
8691 rb_define_alloc_func(rb_cArray
, empty_ary_alloc
);
8692 rb_define_singleton_method(rb_cArray
, "new", rb_ary_s_new
, -1);
8693 rb_define_singleton_method(rb_cArray
, "[]", rb_ary_s_create
, -1);
8694 rb_define_singleton_method(rb_cArray
, "try_convert", rb_ary_s_try_convert
, 1);
8695 rb_define_method(rb_cArray
, "initialize", rb_ary_initialize
, -1);
8696 rb_define_method(rb_cArray
, "initialize_copy", rb_ary_replace
, 1);
8698 rb_define_method(rb_cArray
, "inspect", rb_ary_inspect
, 0);
8699 rb_define_alias(rb_cArray
, "to_s", "inspect");
8700 rb_define_method(rb_cArray
, "to_a", rb_ary_to_a
, 0);
8701 rb_define_method(rb_cArray
, "to_h", rb_ary_to_h
, 0);
8702 rb_define_method(rb_cArray
, "to_ary", rb_ary_to_ary_m
, 0);
8704 rb_define_method(rb_cArray
, "==", rb_ary_equal
, 1);
8705 rb_define_method(rb_cArray
, "eql?", rb_ary_eql
, 1);
8706 rb_define_method(rb_cArray
, "hash", rb_ary_hash
, 0);
8708 rb_define_method(rb_cArray
, "[]", rb_ary_aref
, -1);
8709 rb_define_method(rb_cArray
, "[]=", rb_ary_aset
, -1);
8710 rb_define_method(rb_cArray
, "at", rb_ary_at
, 1);
8711 rb_define_method(rb_cArray
, "fetch", rb_ary_fetch
, -1);
8712 rb_define_method(rb_cArray
, "concat", rb_ary_concat_multi
, -1);
8713 rb_define_method(rb_cArray
, "union", rb_ary_union_multi
, -1);
8714 rb_define_method(rb_cArray
, "difference", rb_ary_difference_multi
, -1);
8715 rb_define_method(rb_cArray
, "intersection", rb_ary_intersection_multi
, -1);
8716 rb_define_method(rb_cArray
, "intersect?", rb_ary_intersect_p
, 1);
8717 rb_define_method(rb_cArray
, "<<", rb_ary_push
, 1);
8718 rb_define_method(rb_cArray
, "push", rb_ary_push_m
, -1);
8719 rb_define_alias(rb_cArray
, "append", "push");
8720 rb_define_method(rb_cArray
, "pop", rb_ary_pop_m
, -1);
8721 rb_define_method(rb_cArray
, "shift", rb_ary_shift_m
, -1);
8722 rb_define_method(rb_cArray
, "unshift", rb_ary_unshift_m
, -1);
8723 rb_define_alias(rb_cArray
, "prepend", "unshift");
8724 rb_define_method(rb_cArray
, "insert", rb_ary_insert
, -1);
8725 rb_define_method(rb_cArray
, "each_index", rb_ary_each_index
, 0);
8726 rb_define_method(rb_cArray
, "reverse_each", rb_ary_reverse_each
, 0);
8727 rb_define_method(rb_cArray
, "length", rb_ary_length
, 0);
8728 rb_define_method(rb_cArray
, "size", rb_ary_length
, 0);
8729 rb_define_method(rb_cArray
, "empty?", rb_ary_empty_p
, 0);
8730 rb_define_method(rb_cArray
, "find_index", rb_ary_index
, -1);
8731 rb_define_method(rb_cArray
, "index", rb_ary_index
, -1);
8732 rb_define_method(rb_cArray
, "rindex", rb_ary_rindex
, -1);
8733 rb_define_method(rb_cArray
, "join", rb_ary_join_m
, -1);
8734 rb_define_method(rb_cArray
, "reverse", rb_ary_reverse_m
, 0);
8735 rb_define_method(rb_cArray
, "reverse!", rb_ary_reverse_bang
, 0);
8736 rb_define_method(rb_cArray
, "rotate", rb_ary_rotate_m
, -1);
8737 rb_define_method(rb_cArray
, "rotate!", rb_ary_rotate_bang
, -1);
8738 rb_define_method(rb_cArray
, "sort", rb_ary_sort
, 0);
8739 rb_define_method(rb_cArray
, "sort!", rb_ary_sort_bang
, 0);
8740 rb_define_method(rb_cArray
, "sort_by!", rb_ary_sort_by_bang
, 0);
8741 rb_define_method(rb_cArray
, "collect", rb_ary_collect
, 0);
8742 rb_define_method(rb_cArray
, "collect!", rb_ary_collect_bang
, 0);
8743 rb_define_method(rb_cArray
, "map", rb_ary_collect
, 0);
8744 rb_define_method(rb_cArray
, "map!", rb_ary_collect_bang
, 0);
8745 rb_define_method(rb_cArray
, "select", rb_ary_select
, 0);
8746 rb_define_method(rb_cArray
, "select!", rb_ary_select_bang
, 0);
8747 rb_define_method(rb_cArray
, "filter", rb_ary_select
, 0);
8748 rb_define_method(rb_cArray
, "filter!", rb_ary_select_bang
, 0);
8749 rb_define_method(rb_cArray
, "keep_if", rb_ary_keep_if
, 0);
8750 rb_define_method(rb_cArray
, "values_at", rb_ary_values_at
, -1);
8751 rb_define_method(rb_cArray
, "delete", rb_ary_delete
, 1);
8752 rb_define_method(rb_cArray
, "delete_at", rb_ary_delete_at_m
, 1);
8753 rb_define_method(rb_cArray
, "delete_if", rb_ary_delete_if
, 0);
8754 rb_define_method(rb_cArray
, "reject", rb_ary_reject
, 0);
8755 rb_define_method(rb_cArray
, "reject!", rb_ary_reject_bang
, 0);
8756 rb_define_method(rb_cArray
, "zip", rb_ary_zip
, -1);
8757 rb_define_method(rb_cArray
, "transpose", rb_ary_transpose
, 0);
8758 rb_define_method(rb_cArray
, "replace", rb_ary_replace
, 1);
8759 rb_define_method(rb_cArray
, "clear", rb_ary_clear
, 0);
8760 rb_define_method(rb_cArray
, "fill", rb_ary_fill
, -1);
8761 rb_define_method(rb_cArray
, "include?", rb_ary_includes
, 1);
8762 rb_define_method(rb_cArray
, "<=>", rb_ary_cmp
, 1);
8764 rb_define_method(rb_cArray
, "slice", rb_ary_aref
, -1);
8765 rb_define_method(rb_cArray
, "slice!", rb_ary_slice_bang
, -1);
8767 rb_define_method(rb_cArray
, "assoc", rb_ary_assoc
, 1);
8768 rb_define_method(rb_cArray
, "rassoc", rb_ary_rassoc
, 1);
8770 rb_define_method(rb_cArray
, "+", rb_ary_plus
, 1);
8771 rb_define_method(rb_cArray
, "*", rb_ary_times
, 1);
8773 rb_define_method(rb_cArray
, "-", rb_ary_diff
, 1);
8774 rb_define_method(rb_cArray
, "&", rb_ary_and
, 1);
8775 rb_define_method(rb_cArray
, "|", rb_ary_or
, 1);
8777 rb_define_method(rb_cArray
, "max", rb_ary_max
, -1);
8778 rb_define_method(rb_cArray
, "min", rb_ary_min
, -1);
8779 rb_define_method(rb_cArray
, "minmax", rb_ary_minmax
, 0);
8781 rb_define_method(rb_cArray
, "uniq", rb_ary_uniq
, 0);
8782 rb_define_method(rb_cArray
, "uniq!", rb_ary_uniq_bang
, 0);
8783 rb_define_method(rb_cArray
, "compact", rb_ary_compact
, 0);
8784 rb_define_method(rb_cArray
, "compact!", rb_ary_compact_bang
, 0);
8785 rb_define_method(rb_cArray
, "flatten", rb_ary_flatten
, -1);
8786 rb_define_method(rb_cArray
, "flatten!", rb_ary_flatten_bang
, -1);
8787 rb_define_method(rb_cArray
, "count", rb_ary_count
, -1);
8788 rb_define_method(rb_cArray
, "cycle", rb_ary_cycle
, -1);
8789 rb_define_method(rb_cArray
, "permutation", rb_ary_permutation
, -1);
8790 rb_define_method(rb_cArray
, "combination", rb_ary_combination
, 1);
8791 rb_define_method(rb_cArray
, "repeated_permutation", rb_ary_repeated_permutation
, 1);
8792 rb_define_method(rb_cArray
, "repeated_combination", rb_ary_repeated_combination
, 1);
8793 rb_define_method(rb_cArray
, "product", rb_ary_product
, -1);
8795 rb_define_method(rb_cArray
, "take", rb_ary_take
, 1);
8796 rb_define_method(rb_cArray
, "take_while", rb_ary_take_while
, 0);
8797 rb_define_method(rb_cArray
, "drop", rb_ary_drop
, 1);
8798 rb_define_method(rb_cArray
, "drop_while", rb_ary_drop_while
, 0);
8799 rb_define_method(rb_cArray
, "bsearch", rb_ary_bsearch
, 0);
8800 rb_define_method(rb_cArray
, "bsearch_index", rb_ary_bsearch_index
, 0);
8801 rb_define_method(rb_cArray
, "any?", rb_ary_any_p
, -1);
8802 rb_define_method(rb_cArray
, "all?", rb_ary_all_p
, -1);
8803 rb_define_method(rb_cArray
, "none?", rb_ary_none_p
, -1);
8804 rb_define_method(rb_cArray
, "one?", rb_ary_one_p
, -1);
8805 rb_define_method(rb_cArray
, "dig", rb_ary_dig
, -1);
8806 rb_define_method(rb_cArray
, "sum", rb_ary_sum
, -1);
8807 rb_define_method(rb_cArray
, "freeze", rb_ary_freeze
, 0);
8809 rb_define_method(rb_cArray
, "deconstruct", rb_ary_deconstruct
, 0);
8811 rb_cArray_empty_frozen
= rb_ary_freeze(rb_ary_new());
8812 rb_vm_register_global_object(rb_cArray_empty_frozen
);
8815 #include "array.rbinc"