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"
31 #include "transient_heap.h"
38 #include "ruby_assert.h"
42 /* for OPTIMIZED_CMP: */
45 #define ARY_DEFAULT_SIZE 16
46 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
47 #define SMALL_ARRAY_LEN 16
49 RBIMPL_ATTR_MAYBE_UNUSED()
51 should_be_T_ARRAY(VALUE ary
)
53 return RB_TYPE_P(ary
, T_ARRAY
);
56 RBIMPL_ATTR_MAYBE_UNUSED()
58 should_not_be_shared_and_embedded(VALUE ary
)
60 return !FL_TEST((ary
), ELTS_SHARED
) || !FL_TEST((ary
), RARRAY_EMBED_FLAG
);
63 #define ARY_SHARED_P(ary) \
64 (assert(should_be_T_ARRAY((VALUE)(ary))), \
65 assert(should_not_be_shared_and_embedded((VALUE)ary)), \
66 FL_TEST_RAW((ary),ELTS_SHARED)!=0)
68 #define ARY_EMBED_P(ary) \
69 (assert(should_be_T_ARRAY((VALUE)(ary))), \
70 assert(should_not_be_shared_and_embedded((VALUE)ary)), \
71 FL_TEST_RAW((ary), RARRAY_EMBED_FLAG) != 0)
73 #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
74 #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
75 #define ARY_HEAP_CAPA(a) (assert(!ARY_EMBED_P(a)), assert(!ARY_SHARED_ROOT_P(a)), \
76 RARRAY(a)->as.heap.aux.capa)
78 #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
79 #define ARY_EMBED_LEN(a) \
80 (assert(ARY_EMBED_P(a)), \
81 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
82 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
83 #define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
85 #define ARY_OWNS_HEAP_P(a) (assert(should_be_T_ARRAY((VALUE)(a))), \
86 !FL_TEST_RAW((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
88 #define FL_SET_EMBED(a) do { \
89 assert(!ARY_SHARED_P(a)); \
90 FL_SET((a), RARRAY_EMBED_FLAG); \
91 RARY_TRANSIENT_UNSET(a); \
95 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
96 #define FL_SET_SHARED(ary) do { \
97 assert(!ARY_EMBED_P(ary)); \
98 FL_SET((ary), ELTS_SHARED); \
100 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
102 #define ARY_SET_PTR(ary, p) do { \
103 assert(!ARY_EMBED_P(ary)); \
104 assert(!OBJ_FROZEN(ary)); \
105 RARRAY(ary)->as.heap.ptr = (p); \
107 #define ARY_SET_EMBED_LEN(ary, n) do { \
109 assert(ARY_EMBED_P(ary)); \
110 assert(!OBJ_FROZEN(ary)); \
111 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
112 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
114 #define ARY_SET_HEAP_LEN(ary, n) do { \
115 assert(!ARY_EMBED_P(ary)); \
116 RARRAY(ary)->as.heap.len = (n); \
118 #define ARY_SET_LEN(ary, n) do { \
119 if (ARY_EMBED_P(ary)) { \
120 ARY_SET_EMBED_LEN((ary), (n)); \
123 ARY_SET_HEAP_LEN((ary), (n)); \
125 assert(RARRAY_LEN(ary) == (n)); \
127 #define ARY_INCREASE_PTR(ary, n) do { \
128 assert(!ARY_EMBED_P(ary)); \
129 assert(!OBJ_FROZEN(ary)); \
130 RARRAY(ary)->as.heap.ptr += (n); \
132 #define ARY_INCREASE_LEN(ary, n) do { \
133 assert(!OBJ_FROZEN(ary)); \
134 if (ARY_EMBED_P(ary)) { \
135 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
138 RARRAY(ary)->as.heap.len += (n); \
142 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
143 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
144 #define ARY_SET_CAPA(ary, n) do { \
145 assert(!ARY_EMBED_P(ary)); \
146 assert(!ARY_SHARED_P(ary)); \
147 assert(!OBJ_FROZEN(ary)); \
148 RARRAY(ary)->as.heap.aux.capa = (n); \
151 #define ARY_SHARED_ROOT(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared_root)
152 #define ARY_SET_SHARED(ary, value) do { \
153 const VALUE _ary_ = (ary); \
154 const VALUE _value_ = (value); \
155 assert(!ARY_EMBED_P(_ary_)); \
156 assert(ARY_SHARED_P(_ary_)); \
157 assert(ARY_SHARED_ROOT_P(_value_)); \
158 RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared_root, _value_); \
160 #define RARRAY_SHARED_ROOT_FLAG FL_USER5
161 #define ARY_SHARED_ROOT_P(ary) (assert(should_be_T_ARRAY((VALUE)(ary))), \
162 FL_TEST_RAW((ary), RARRAY_SHARED_ROOT_FLAG))
163 #define ARY_SHARED_ROOT_REFCNT(ary) \
164 (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
165 #define ARY_SHARED_ROOT_OCCUPIED(ary) (ARY_SHARED_ROOT_REFCNT(ary) == 1)
166 #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
167 assert(ARY_SHARED_ROOT_P(ary)); \
168 RARRAY(ary)->as.heap.aux.capa = (value); \
170 #define FL_SET_SHARED_ROOT(ary) do { \
171 assert(!ARY_EMBED_P(ary)); \
172 assert(!RARRAY_TRANSIENT_P(ary)); \
173 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
177 ARY_SET(VALUE a
, long i
, VALUE v
)
179 assert(!ARY_SHARED_P(a
));
180 assert(!OBJ_FROZEN(a
));
182 RARRAY_ASET(a
, i
, v
);
188 #define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
191 ary_verify_(VALUE ary
, const char *file
, int line
)
193 assert(RB_TYPE_P(ary
, T_ARRAY
));
195 if (FL_TEST(ary
, ELTS_SHARED
)) {
196 VALUE root
= RARRAY(ary
)->as
.heap
.aux
.shared_root
;
197 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
198 const VALUE
*root_ptr
= RARRAY_CONST_PTR_TRANSIENT(root
);
199 long len
= ARY_HEAP_LEN(ary
), root_len
= RARRAY_LEN(root
);
200 assert(FL_TEST(root
, RARRAY_SHARED_ROOT_FLAG
));
201 assert(root_ptr
<= ptr
&& ptr
+ len
<= root_ptr
+ root_len
);
204 else if (ARY_EMBED_P(ary
)) {
205 assert(!RARRAY_TRANSIENT_P(ary
));
206 assert(!ARY_SHARED_P(ary
));
207 assert(RARRAY_LEN(ary
) <= RARRAY_EMBED_LEN_MAX
);
211 const VALUE
*ptr
= RARRAY_CONST_PTR_TRANSIENT(ary
);
212 long i
, len
= RARRAY_LEN(ary
);
214 if (len
> 1) len
= 1; /* check only HEAD */
215 for (i
=0; i
<len
; i
++) {
216 v
= ptr
[i
]; /* access check */
222 #if USE_TRANSIENT_HEAP
223 if (RARRAY_TRANSIENT_P(ary
)) {
224 assert(rb_transient_heap_managed_ptr_p(RARRAY_CONST_PTR_TRANSIENT(ary
)));
228 rb_transient_heap_verify();
234 rb_ary_verify(VALUE ary
)
239 #define ary_verify(ary) ((void)0)
243 rb_ary_ptr_use_start(VALUE ary
)
246 FL_SET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
248 return (VALUE
*)RARRAY_CONST_PTR_TRANSIENT(ary
);
252 rb_ary_ptr_use_end(VALUE ary
)
255 FL_UNSET_RAW(ary
, RARRAY_PTR_IN_USE_FLAG
);
260 rb_mem_clear(VALUE
*mem
, long size
)
268 ary_mem_clear(VALUE ary
, long beg
, long size
)
270 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
271 rb_mem_clear(ptr
+ beg
, size
);
276 memfill(register VALUE
*mem
, register long size
, register VALUE val
)
284 ary_memfill(VALUE ary
, long beg
, long size
, VALUE val
)
286 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
287 memfill(ptr
+ beg
, size
, val
);
288 RB_OBJ_WRITTEN(ary
, Qundef
, val
);
293 ary_memcpy0(VALUE ary
, long beg
, long argc
, const VALUE
*argv
, VALUE buff_owner_ary
)
295 assert(!ARY_SHARED_P(buff_owner_ary
));
297 if (argc
> (int)(128/sizeof(VALUE
)) /* is magic number (cache line size) */) {
298 rb_gc_writebarrier_remember(buff_owner_ary
);
299 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
300 MEMCPY(ptr
+beg
, argv
, VALUE
, argc
);
305 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
306 for (i
=0; i
<argc
; i
++) {
307 RB_OBJ_WRITE(buff_owner_ary
, &ptr
[i
+beg
], argv
[i
]);
314 ary_memcpy(VALUE ary
, long beg
, long argc
, const VALUE
*argv
)
316 ary_memcpy0(ary
, beg
, argc
, argv
, ary
);
320 ary_heap_alloc(VALUE ary
, size_t capa
)
322 VALUE
*ptr
= rb_transient_heap_alloc(ary
, sizeof(VALUE
) * capa
);
325 RARY_TRANSIENT_SET(ary
);
328 RARY_TRANSIENT_UNSET(ary
);
329 ptr
= ALLOC_N(VALUE
, capa
);
336 ary_heap_free_ptr(VALUE ary
, const VALUE
*ptr
, long size
)
338 if (RARRAY_TRANSIENT_P(ary
)) {
342 ruby_sized_xfree((void *)ptr
, size
);
347 ary_heap_free(VALUE ary
)
349 if (RARRAY_TRANSIENT_P(ary
)) {
350 RARY_TRANSIENT_UNSET(ary
);
353 ary_heap_free_ptr(ary
, ARY_HEAP_PTR(ary
), ARY_HEAP_SIZE(ary
));
358 ary_heap_realloc(VALUE ary
, size_t new_capa
)
360 size_t alloc_capa
= new_capa
;
361 size_t old_capa
= ARY_HEAP_CAPA(ary
);
363 if (RARRAY_TRANSIENT_P(ary
)) {
364 if (new_capa
<= old_capa
) {
366 alloc_capa
= old_capa
;
369 VALUE
*new_ptr
= rb_transient_heap_alloc(ary
, sizeof(VALUE
) * new_capa
);
371 if (new_ptr
== NULL
) {
372 new_ptr
= ALLOC_N(VALUE
, new_capa
);
373 RARY_TRANSIENT_UNSET(ary
);
376 MEMCPY(new_ptr
, ARY_HEAP_PTR(ary
), VALUE
, old_capa
);
377 ARY_SET_PTR(ary
, new_ptr
);
381 SIZED_REALLOC_N(RARRAY(ary
)->as
.heap
.ptr
, VALUE
, new_capa
, old_capa
);
388 #if USE_TRANSIENT_HEAP
390 rb_ary_transient_heap_evacuate_(VALUE ary
, int transient
, int promote
)
394 const VALUE
*old_ptr
= ARY_HEAP_PTR(ary
);
395 long capa
= ARY_HEAP_CAPA(ary
);
396 long len
= ARY_HEAP_LEN(ary
);
398 if (ARY_SHARED_ROOT_P(ary
)) {
402 assert(ARY_OWNS_HEAP_P(ary
));
403 assert(RARRAY_TRANSIENT_P(ary
));
404 assert(!ARY_PTR_USING_P(ary
));
407 new_ptr
= ALLOC_N(VALUE
, capa
);
408 RARY_TRANSIENT_UNSET(ary
);
411 new_ptr
= ary_heap_alloc(ary
, capa
);
414 MEMCPY(new_ptr
, old_ptr
, VALUE
, capa
);
415 /* do not use ARY_SET_PTR() because they assert !frozen */
416 RARRAY(ary
)->as
.heap
.ptr
= new_ptr
;
423 rb_ary_transient_heap_evacuate(VALUE ary
, int promote
)
425 rb_ary_transient_heap_evacuate_(ary
, RARRAY_TRANSIENT_P(ary
), promote
);
429 rb_ary_detransient(VALUE ary
)
431 assert(RARRAY_TRANSIENT_P(ary
));
432 rb_ary_transient_heap_evacuate_(ary
, TRUE
, TRUE
);
436 rb_ary_detransient(VALUE ary
)
443 ary_resize_capa(VALUE ary
, long capacity
)
445 assert(RARRAY_LEN(ary
) <= capacity
);
446 assert(!OBJ_FROZEN(ary
));
447 assert(!ARY_SHARED_P(ary
));
449 if (capacity
> RARRAY_EMBED_LEN_MAX
) {
450 size_t new_capa
= capacity
;
451 if (ARY_EMBED_P(ary
)) {
452 long len
= ARY_EMBED_LEN(ary
);
453 VALUE
*ptr
= ary_heap_alloc(ary
, capacity
);
455 MEMCPY(ptr
, ARY_EMBED_PTR(ary
), VALUE
, len
);
457 ARY_SET_PTR(ary
, ptr
);
458 ARY_SET_HEAP_LEN(ary
, len
);
461 new_capa
= ary_heap_realloc(ary
, capacity
);
463 ARY_SET_CAPA(ary
, new_capa
);
466 if (!ARY_EMBED_P(ary
)) {
467 long len
= ARY_HEAP_LEN(ary
);
468 long old_capa
= ARY_HEAP_CAPA(ary
);
469 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
471 if (len
> capacity
) len
= capacity
;
472 MEMCPY((VALUE
*)RARRAY(ary
)->as
.ary
, ptr
, VALUE
, len
);
473 ary_heap_free_ptr(ary
, ptr
, old_capa
);
476 ARY_SET_LEN(ary
, len
);
484 ary_shrink_capa(VALUE ary
)
486 long capacity
= ARY_HEAP_LEN(ary
);
487 long old_capa
= ARY_HEAP_CAPA(ary
);
488 assert(!ARY_SHARED_P(ary
));
489 assert(old_capa
>= capacity
);
490 if (old_capa
> capacity
) ary_heap_realloc(ary
, capacity
);
496 ary_double_capa(VALUE ary
, long min
)
498 long new_capa
= ARY_CAPA(ary
) / 2;
500 if (new_capa
< ARY_DEFAULT_SIZE
) {
501 new_capa
= ARY_DEFAULT_SIZE
;
503 if (new_capa
>= ARY_MAX_SIZE
- min
) {
504 new_capa
= (ARY_MAX_SIZE
- min
) / 2;
507 ary_resize_capa(ary
, new_capa
);
513 rb_ary_decrement_share(VALUE shared_root
)
516 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
) - 1;
518 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
);
524 rb_ary_unshare(VALUE ary
)
526 VALUE shared_root
= RARRAY(ary
)->as
.heap
.aux
.shared_root
;
527 rb_ary_decrement_share(shared_root
);
528 FL_UNSET_SHARED(ary
);
532 rb_ary_unshare_safe(VALUE ary
)
534 if (ARY_SHARED_P(ary
) && !ARY_EMBED_P(ary
)) {
540 rb_ary_increment_share(VALUE shared_root
)
542 long num
= ARY_SHARED_ROOT_REFCNT(shared_root
);
544 ARY_SET_SHARED_ROOT_REFCNT(shared_root
, num
+ 1);
550 rb_ary_set_shared(VALUE ary
, VALUE shared_root
)
552 rb_ary_increment_share(shared_root
);
554 RB_DEBUG_COUNTER_INC(obj_ary_shared_create
);
555 ARY_SET_SHARED(ary
, shared_root
);
559 rb_ary_modify_check(VALUE ary
)
561 rb_check_frozen(ary
);
566 rb_ary_cancel_sharing(VALUE ary
)
568 if (ARY_SHARED_P(ary
)) {
569 long shared_len
, len
= RARRAY_LEN(ary
);
570 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
572 ary_verify(shared_root
);
574 if (len
<= RARRAY_EMBED_LEN_MAX
) {
575 const VALUE
*ptr
= ARY_HEAP_PTR(ary
);
576 FL_UNSET_SHARED(ary
);
578 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), ptr
, VALUE
, len
);
579 rb_ary_decrement_share(shared_root
);
580 ARY_SET_EMBED_LEN(ary
, len
);
582 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root
) && len
> ((shared_len
= RARRAY_LEN(shared_root
))>>1)) {
583 long shift
= RARRAY_CONST_PTR_TRANSIENT(ary
) - RARRAY_CONST_PTR_TRANSIENT(shared_root
);
584 FL_UNSET_SHARED(ary
);
585 ARY_SET_PTR(ary
, RARRAY_CONST_PTR_TRANSIENT(shared_root
));
586 ARY_SET_CAPA(ary
, shared_len
);
587 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
588 MEMMOVE(ptr
, ptr
+shift
, VALUE
, len
);
590 FL_SET_EMBED(shared_root
);
591 rb_ary_decrement_share(shared_root
);
594 VALUE
*ptr
= ary_heap_alloc(ary
, len
);
595 MEMCPY(ptr
, ARY_HEAP_PTR(ary
), VALUE
, len
);
597 ARY_SET_CAPA(ary
, len
);
598 ARY_SET_PTR(ary
, ptr
);
601 rb_gc_writebarrier_remember(ary
);
607 rb_ary_modify(VALUE ary
)
609 rb_ary_modify_check(ary
);
610 rb_ary_cancel_sharing(ary
);
614 ary_ensure_room_for_push(VALUE ary
, long add_len
)
616 long old_len
= RARRAY_LEN(ary
);
617 long new_len
= old_len
+ add_len
;
620 if (old_len
> ARY_MAX_SIZE
- add_len
) {
621 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
623 if (ARY_SHARED_P(ary
)) {
624 if (new_len
> RARRAY_EMBED_LEN_MAX
) {
625 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
626 if (ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
627 if (ARY_HEAP_PTR(ary
) - RARRAY_CONST_PTR_TRANSIENT(shared_root
) + new_len
<= RARRAY_LEN(shared_root
)) {
628 rb_ary_modify_check(ary
);
631 ary_verify(shared_root
);
635 /* if array is shared, then it is likely it participate in push/shift pattern */
637 capa
= ARY_CAPA(ary
);
638 if (new_len
> capa
- (capa
>> 6)) {
639 ary_double_capa(ary
, new_len
);
650 rb_ary_modify_check(ary
);
652 capa
= ARY_CAPA(ary
);
653 if (new_len
> capa
) {
654 ary_double_capa(ary
, new_len
);
663 * array.freeze -> self
665 * Freezes +self+; returns +self+:
667 * a.frozen? # => false
669 * a.frozen? # => true
671 * An attempt to modify a frozen \Array raises FrozenError.
675 rb_ary_freeze(VALUE ary
)
677 return rb_obj_freeze(ary
);
680 /* This can be used to take a snapshot of an array (with
681 e.g. rb_ary_replace) and check later whether the array has been
682 modified from the snapshot. The snapshot is cheap, though if
683 something does modify the array it will pay the cost of copying
684 it. If Array#pop or Array#shift has been called, the array will
685 be still shared with the snapshot, but the array length will
688 rb_ary_shared_with_p(VALUE ary1
, VALUE ary2
)
690 if (!ARY_EMBED_P(ary1
) && ARY_SHARED_P(ary1
) &&
691 !ARY_EMBED_P(ary2
) && ARY_SHARED_P(ary2
) &&
692 RARRAY(ary1
)->as
.heap
.aux
.shared_root
== RARRAY(ary2
)->as
.heap
.aux
.shared_root
&&
693 RARRAY(ary1
)->as
.heap
.len
== RARRAY(ary2
)->as
.heap
.len
) {
700 ary_alloc(VALUE klass
)
702 NEWOBJ_OF(ary
, struct RArray
, klass
, T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0));
704 * FL_SET_EMBED((VALUE)ary);
705 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
711 empty_ary_alloc(VALUE klass
)
713 RUBY_DTRACE_CREATE_HOOK(ARRAY
, 0);
714 return ary_alloc(klass
);
718 ary_new(VALUE klass
, long capa
)
723 rb_raise(rb_eArgError
, "negative array size (or size too big)");
725 if (capa
> ARY_MAX_SIZE
) {
726 rb_raise(rb_eArgError
, "array size too big");
729 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
731 ary
= ary_alloc(klass
);
732 if (capa
> RARRAY_EMBED_LEN_MAX
) {
733 ptr
= ary_heap_alloc(ary
, capa
);
735 ARY_SET_PTR(ary
, ptr
);
736 ARY_SET_CAPA(ary
, capa
);
737 ARY_SET_HEAP_LEN(ary
, 0);
744 rb_ary_new_capa(long capa
)
746 return ary_new(rb_cArray
, capa
);
752 return rb_ary_new2(RARRAY_EMBED_LEN_MAX
);
756 (rb_ary_new_from_args
)(long n
, ...)
762 ary
= rb_ary_new2(n
);
765 for (i
=0; i
<n
; i
++) {
766 ARY_SET(ary
, i
, va_arg(ar
, VALUE
));
774 MJIT_FUNC_EXPORTED VALUE
775 rb_ary_tmp_new_from_values(VALUE klass
, long n
, const VALUE
*elts
)
779 ary
= ary_new(klass
, n
);
781 ary_memcpy(ary
, 0, n
, elts
);
789 rb_ary_new_from_values(long n
, const VALUE
*elts
)
791 return rb_ary_tmp_new_from_values(rb_cArray
, n
, elts
);
795 ec_ary_alloc(rb_execution_context_t
*ec
, VALUE klass
)
797 RB_EC_NEWOBJ_OF(ec
, ary
, struct RArray
, klass
, T_ARRAY
| RARRAY_EMBED_FLAG
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0));
799 * FL_SET_EMBED((VALUE)ary);
800 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
806 ec_ary_new(rb_execution_context_t
*ec
, VALUE klass
, long capa
)
811 rb_raise(rb_eArgError
, "negative array size (or size too big)");
813 if (capa
> ARY_MAX_SIZE
) {
814 rb_raise(rb_eArgError
, "array size too big");
817 RUBY_DTRACE_CREATE_HOOK(ARRAY
, capa
);
819 ary
= ec_ary_alloc(ec
, klass
);
821 if (capa
> RARRAY_EMBED_LEN_MAX
) {
822 ptr
= ary_heap_alloc(ary
, capa
);
824 ARY_SET_PTR(ary
, ptr
);
825 ARY_SET_CAPA(ary
, capa
);
826 ARY_SET_HEAP_LEN(ary
, 0);
833 rb_ec_ary_new_from_values(rb_execution_context_t
*ec
, long n
, const VALUE
*elts
)
837 ary
= ec_ary_new(ec
, rb_cArray
, n
);
839 ary_memcpy(ary
, 0, n
, elts
);
847 rb_ary_tmp_new(long capa
)
849 VALUE ary
= ary_new(0, capa
);
850 rb_ary_transient_heap_evacuate(ary
, TRUE
);
855 rb_ary_tmp_new_fill(long capa
)
857 VALUE ary
= ary_new(0, capa
);
858 ary_memfill(ary
, 0, capa
, Qnil
);
859 ARY_SET_LEN(ary
, capa
);
860 rb_ary_transient_heap_evacuate(ary
, TRUE
);
865 rb_ary_free(VALUE ary
)
867 if (ARY_OWNS_HEAP_P(ary
)) {
868 if (USE_DEBUG_COUNTER
&&
869 !ARY_SHARED_ROOT_P(ary
) &&
870 ARY_HEAP_CAPA(ary
) > RARRAY_LEN(ary
)) {
871 RB_DEBUG_COUNTER_INC(obj_ary_extracapa
);
874 if (RARRAY_TRANSIENT_P(ary
)) {
875 RB_DEBUG_COUNTER_INC(obj_ary_transient
);
878 RB_DEBUG_COUNTER_INC(obj_ary_ptr
);
883 RB_DEBUG_COUNTER_INC(obj_ary_embed
);
886 if (ARY_SHARED_P(ary
)) {
887 RB_DEBUG_COUNTER_INC(obj_ary_shared
);
889 if (ARY_SHARED_ROOT_P(ary
) && ARY_SHARED_ROOT_OCCUPIED(ary
)) {
890 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied
);
894 RUBY_FUNC_EXPORTED
size_t
895 rb_ary_memsize(VALUE ary
)
897 if (ARY_OWNS_HEAP_P(ary
)) {
898 return ARY_CAPA(ary
) * sizeof(VALUE
);
906 ary_discard(VALUE ary
)
909 RBASIC(ary
)->flags
|= RARRAY_EMBED_FLAG
;
910 RBASIC(ary
)->flags
&= ~(RARRAY_EMBED_LEN_MASK
| RARRAY_TRANSIENT_FLAG
);
914 ary_make_shared(VALUE ary
)
916 assert(!ARY_EMBED_P(ary
));
919 if (ARY_SHARED_P(ary
)) {
920 return ARY_SHARED_ROOT(ary
);
922 else if (ARY_SHARED_ROOT_P(ary
)) {
925 else if (OBJ_FROZEN(ary
)) {
926 rb_ary_transient_heap_evacuate(ary
, TRUE
);
927 ary_shrink_capa(ary
);
928 FL_SET_SHARED_ROOT(ary
);
929 ARY_SET_SHARED_ROOT_REFCNT(ary
, 1);
933 long capa
= ARY_CAPA(ary
), len
= RARRAY_LEN(ary
);
935 NEWOBJ_OF(shared
, struct RArray
, 0, T_ARRAY
| (RGENGC_WB_PROTECTED_ARRAY
? FL_WB_PROTECTED
: 0));
936 VALUE vshared
= (VALUE
)shared
;
938 rb_ary_transient_heap_evacuate(ary
, TRUE
);
939 ptr
= ARY_HEAP_PTR(ary
);
941 FL_UNSET_EMBED(vshared
);
942 ARY_SET_LEN(vshared
, capa
);
943 ARY_SET_PTR(vshared
, ptr
);
944 ary_mem_clear(vshared
, len
, capa
- len
);
945 FL_SET_SHARED_ROOT(vshared
);
946 ARY_SET_SHARED_ROOT_REFCNT(vshared
, 1);
948 RB_DEBUG_COUNTER_INC(obj_ary_shared_create
);
949 ARY_SET_SHARED(ary
, vshared
);
960 ary_make_substitution(VALUE ary
)
962 long len
= RARRAY_LEN(ary
);
964 if (len
<= RARRAY_EMBED_LEN_MAX
) {
965 VALUE subst
= rb_ary_new2(len
);
966 ary_memcpy(subst
, 0, len
, RARRAY_CONST_PTR_TRANSIENT(ary
));
967 ARY_SET_EMBED_LEN(subst
, len
);
971 return rb_ary_increment_share(ary_make_shared(ary
));
976 rb_assoc_new(VALUE car
, VALUE cdr
)
978 return rb_ary_new3(2, car
, cdr
);
982 rb_to_array_type(VALUE ary
)
984 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
986 #define to_ary rb_to_array_type
989 rb_check_array_type(VALUE ary
)
991 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_ary
);
994 MJIT_FUNC_EXPORTED VALUE
995 rb_check_to_array(VALUE ary
)
997 return rb_check_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1001 rb_to_array(VALUE ary
)
1003 return rb_convert_type_with_id(ary
, T_ARRAY
, "Array", idTo_a
);
1008 * Array.try_convert(object) -> object, new_array, or nil
1010 * If +object+ is an \Array object, returns +object+.
1012 * Otherwise if +object+ responds to <tt>:to_ary</tt>,
1013 * calls <tt>object.to_ary</tt> and returns the result.
1015 * Returns +nil+ if +object+ does not respond to <tt>:to_ary</tt>
1017 * Raises an exception unless <tt>object.to_ary</tt> returns an \Array object.
1021 rb_ary_s_try_convert(VALUE dummy
, VALUE ary
)
1023 return rb_check_array_type(ary
);
1028 * Array.new -> new_empty_array
1029 * Array.new(array) -> new_array
1030 * Array.new(size) -> new_array
1031 * Array.new(size, default_value) -> new_array
1032 * Array.new(size) {|index| ... } -> new_array
1034 * Returns a new \Array.
1036 * With no block and no arguments, returns a new empty \Array object.
1038 * With no block and a single \Array argument +array+,
1039 * returns a new \Array formed from +array+:
1040 * a = Array.new([:foo, 'bar', 2])
1041 * a.class # => Array
1042 * a # => [:foo, "bar", 2]
1044 * With no block and a single \Integer argument +size+,
1045 * returns a new \Array of the given size
1046 * whose elements are all +nil+:
1048 * a # => [nil, nil, nil]
1050 * With no block and arguments +size+ and +default_value+,
1051 * returns an \Array of the given size;
1052 * each element is that same +default_value+:
1053 * a = Array.new(3, 'x')
1054 * a # => ['x', 'x', 'x']
1056 * With a block and argument +size+,
1057 * returns an \Array of the given size;
1058 * the block is called with each successive integer +index+;
1059 * the element for that +index+ is the return value from the block:
1060 * a = Array.new(3) {|index| "Element #{index}" }
1061 * a # => ["Element 0", "Element 1", "Element 2"]
1063 * Raises ArgumentError if +size+ is negative.
1065 * With a block and no argument,
1066 * or a single argument +0+,
1067 * ignores the block and returns a new empty \Array.
1071 rb_ary_initialize(int argc
, VALUE
*argv
, VALUE ary
)
1078 if (ARY_OWNS_HEAP_P(ary
) && ARY_HEAP_PTR(ary
) != NULL
) {
1081 rb_ary_unshare_safe(ary
);
1083 ARY_SET_EMBED_LEN(ary
, 0);
1084 if (rb_block_given_p()) {
1085 rb_warning("given block not used");
1089 rb_scan_args(argc
, argv
, "02", &size
, &val
);
1090 if (argc
== 1 && !FIXNUM_P(size
)) {
1091 val
= rb_check_array_type(size
);
1093 rb_ary_replace(ary
, val
);
1098 len
= NUM2LONG(size
);
1099 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1101 rb_raise(rb_eArgError
, "negative array size");
1103 if (len
> ARY_MAX_SIZE
) {
1104 rb_raise(rb_eArgError
, "array size too big");
1106 /* recheck after argument conversion */
1108 ary_resize_capa(ary
, len
);
1109 if (rb_block_given_p()) {
1113 rb_warn("block supersedes default value argument");
1115 for (i
=0; i
<len
; i
++) {
1116 rb_ary_store(ary
, i
, rb_yield(LONG2NUM(i
)));
1117 ARY_SET_LEN(ary
, i
+ 1);
1121 ary_memfill(ary
, 0, len
, val
);
1122 ARY_SET_LEN(ary
, len
);
1128 * Returns a new array populated with the given objects.
1130 * Array.[]( 1, 'a', /^A/) # => [1, "a", /^A/]
1131 * Array[ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1132 * [ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1136 rb_ary_s_create(int argc
, VALUE
*argv
, VALUE klass
)
1138 VALUE ary
= ary_new(klass
, argc
);
1139 if (argc
> 0 && argv
) {
1140 ary_memcpy(ary
, 0, argc
, argv
);
1141 ARY_SET_LEN(ary
, argc
);
1148 rb_ary_store(VALUE ary
, long idx
, VALUE val
)
1150 long len
= RARRAY_LEN(ary
);
1155 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
1159 else if (idx
>= ARY_MAX_SIZE
) {
1160 rb_raise(rb_eIndexError
, "index %ld too big", idx
);
1164 if (idx
>= ARY_CAPA(ary
)) {
1165 ary_double_capa(ary
, idx
);
1168 ary_mem_clear(ary
, len
, idx
- len
+ 1);
1172 ARY_SET_LEN(ary
, idx
+ 1);
1174 ARY_SET(ary
, idx
, val
);
1178 ary_make_partial(VALUE ary
, VALUE klass
, long offset
, long len
)
1180 assert(offset
>= 0);
1182 assert(offset
+len
<= RARRAY_LEN(ary
));
1184 if (len
<= RARRAY_EMBED_LEN_MAX
) {
1185 VALUE result
= ary_alloc(klass
);
1186 ary_memcpy(result
, 0, len
, RARRAY_CONST_PTR_TRANSIENT(ary
) + offset
);
1187 ARY_SET_EMBED_LEN(result
, len
);
1191 VALUE shared
, result
= ary_alloc(klass
);
1192 FL_UNSET_EMBED(result
);
1194 shared
= ary_make_shared(ary
);
1195 ARY_SET_PTR(result
, RARRAY_CONST_PTR_TRANSIENT(ary
));
1196 ARY_SET_LEN(result
, RARRAY_LEN(ary
));
1197 rb_ary_set_shared(result
, shared
);
1199 ARY_INCREASE_PTR(result
, offset
);
1200 ARY_SET_LEN(result
, len
);
1209 ary_make_partial_step(VALUE ary
, VALUE klass
, long offset
, long len
, long step
)
1211 assert(offset
>= 0);
1213 assert(offset
+len
<= RARRAY_LEN(ary
));
1216 const VALUE
*values
= RARRAY_CONST_PTR_TRANSIENT(ary
);
1217 const long orig_len
= len
;
1219 if ((step
> 0 && step
>= len
) || (step
< 0 && (step
< -len
))) {
1220 VALUE result
= ary_new(klass
, 1);
1221 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1222 RB_OBJ_WRITE(result
, ptr
, values
[offset
]);
1223 ARY_SET_EMBED_LEN(result
, 1);
1227 long ustep
= (step
< 0) ? -step
: step
;
1228 len
= (len
+ ustep
- 1) / ustep
;
1231 long j
= offset
+ ((step
> 0) ? 0 : (orig_len
- 1));
1232 VALUE result
= ary_new(klass
, len
);
1233 if (len
<= RARRAY_EMBED_LEN_MAX
) {
1234 VALUE
*ptr
= (VALUE
*)ARY_EMBED_PTR(result
);
1235 for (i
= 0; i
< len
; ++i
) {
1236 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1239 ARY_SET_EMBED_LEN(result
, len
);
1242 RARRAY_PTR_USE_TRANSIENT(result
, ptr
, {
1243 for (i
= 0; i
< len
; ++i
) {
1244 RB_OBJ_WRITE(result
, ptr
+i
, values
[j
]);
1248 ARY_SET_LEN(result
, len
);
1255 ary_make_shared_copy(VALUE ary
)
1257 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
1260 enum ary_take_pos_flags
1267 ary_take_first_or_last(int argc
, const VALUE
*argv
, VALUE ary
, enum ary_take_pos_flags last
)
1273 argc
= rb_check_arity(argc
, 0, 1);
1274 /* the case optional argument is omitted should be handled in
1275 * callers of this function. if another arity case is added,
1276 * this arity check needs to rewrite. */
1277 RUBY_ASSERT_ALWAYS(argc
== 1);
1279 n
= NUM2LONG(argv
[0]);
1280 len
= RARRAY_LEN(ary
);
1285 rb_raise(rb_eArgError
, "negative array size");
1290 return ary_make_partial(ary
, rb_cArray
, offset
, n
);
1295 * array << object -> self
1297 * Appends +object+ to +self+; returns +self+:
1298 * a = [:foo, 'bar', 2]
1299 * a << :baz # => [:foo, "bar", 2, :baz]
1301 * Appends +object+ as one element, even if it is another \Array:
1302 * a = [:foo, 'bar', 2]
1304 * a1 # => [:foo, "bar", 2, [3, 4]]
1308 rb_ary_push(VALUE ary
, VALUE item
)
1310 long idx
= RARRAY_LEN((ary_verify(ary
), ary
));
1311 VALUE target_ary
= ary_ensure_room_for_push(ary
, 1);
1312 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
1313 RB_OBJ_WRITE(target_ary
, &ptr
[idx
], item
);
1315 ARY_SET_LEN(ary
, idx
+ 1);
1321 rb_ary_cat(VALUE ary
, const VALUE
*argv
, long len
)
1323 long oldlen
= RARRAY_LEN(ary
);
1324 VALUE target_ary
= ary_ensure_room_for_push(ary
, len
);
1325 ary_memcpy0(ary
, oldlen
, len
, argv
, target_ary
);
1326 ARY_SET_LEN(ary
, oldlen
+ len
);
1332 * array.push(*objects) -> self
1334 * Appends trailing elements.
1336 * Appends each argument in +objects+ to +self+; returns +self+:
1337 * a = [:foo, 'bar', 2]
1338 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1340 * Appends each argument as one element, even if it is another \Array:
1341 * a = [:foo, 'bar', 2]
1342 * a1 = a.push([:baz, :bat], [:bam, :bad])
1343 * a1 # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1345 * Array#append is an alias for \Array#push.
1347 * Related: #pop, #shift, #unshift.
1351 rb_ary_push_m(int argc
, VALUE
*argv
, VALUE ary
)
1353 return rb_ary_cat(ary
, argv
, argc
);
1357 rb_ary_pop(VALUE ary
)
1360 rb_ary_modify_check(ary
);
1361 n
= RARRAY_LEN(ary
);
1362 if (n
== 0) return Qnil
;
1363 if (ARY_OWNS_HEAP_P(ary
) &&
1364 n
* 3 < ARY_CAPA(ary
) &&
1365 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
)
1367 ary_resize_capa(ary
, n
* 2);
1370 ARY_SET_LEN(ary
, n
);
1372 return RARRAY_AREF(ary
, n
);
1377 * array.pop -> object or nil
1378 * array.pop(n) -> new_array
1380 * Removes and returns trailing elements.
1382 * When no argument is given and +self+ is not empty,
1383 * removes and returns the last element:
1384 * a = [:foo, 'bar', 2]
1386 * a # => [:foo, "bar"]
1388 * Returns +nil+ if the array is empty.
1390 * When a non-negative \Integer argument +n+ is given and is in range,
1391 * removes and returns the last +n+ elements in a new \Array:
1392 * a = [:foo, 'bar', 2]
1393 * a.pop(2) # => ["bar", 2]
1395 * If +n+ is positive and out of range,
1396 * removes and returns all elements:
1397 * a = [:foo, 'bar', 2]
1398 * a.pop(50) # => [:foo, "bar", 2]
1400 * Related: #push, #shift, #unshift.
1404 rb_ary_pop_m(int argc
, VALUE
*argv
, VALUE ary
)
1409 return rb_ary_pop(ary
);
1412 rb_ary_modify_check(ary
);
1413 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
1414 ARY_INCREASE_LEN(ary
, -RARRAY_LEN(result
));
1420 rb_ary_shift(VALUE ary
)
1423 long len
= RARRAY_LEN(ary
);
1425 rb_ary_modify_check(ary
);
1426 if (len
== 0) return Qnil
;
1427 top
= RARRAY_AREF(ary
, 0);
1428 if (!ARY_SHARED_P(ary
)) {
1429 if (len
< ARY_DEFAULT_SIZE
) {
1430 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
1431 MEMMOVE(ptr
, ptr
+1, VALUE
, len
-1);
1432 }); /* WB: no new reference */
1433 ARY_INCREASE_LEN(ary
, -1);
1437 assert(!ARY_EMBED_P(ary
)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
1439 ARY_SET(ary
, 0, Qnil
);
1440 ary_make_shared(ary
);
1442 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
))) {
1443 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, ptr
[0] = Qnil
);
1445 ARY_INCREASE_PTR(ary
, 1); /* shift ptr */
1446 ARY_INCREASE_LEN(ary
, -1);
1455 * array.shift -> object or nil
1456 * array.shift(n) -> new_array
1458 * Removes and returns leading elements.
1460 * When no argument is given, removes and returns the first element:
1461 * a = [:foo, 'bar', 2]
1465 * Returns +nil+ if +self+ is empty.
1467 * When positive \Integer argument +n+ is given, removes the first +n+ elements;
1468 * returns those elements in a new \Array:
1469 * a = [:foo, 'bar', 2]
1470 * a.shift(2) # => [:foo, 'bar']
1473 * If +n+ is as large as or larger than <tt>self.length</tt>,
1474 * removes all elements; returns those elements in a new \Array:
1475 * a = [:foo, 'bar', 2]
1476 * a.shift(3) # => [:foo, 'bar', 2]
1478 * If +n+ is zero, returns a new empty \Array; +self+ is unmodified.
1480 * Related: #push, #pop, #unshift.
1484 rb_ary_shift_m(int argc
, VALUE
*argv
, VALUE ary
)
1490 return rb_ary_shift(ary
);
1493 rb_ary_modify_check(ary
);
1494 result
= ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1495 n
= RARRAY_LEN(result
);
1496 rb_ary_behead(ary
,n
);
1502 behead_shared(VALUE ary
, long n
)
1504 assert(ARY_SHARED_P(ary
));
1505 rb_ary_modify_check(ary
);
1506 if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
))) {
1507 ary_mem_clear(ary
, 0, n
);
1509 ARY_INCREASE_PTR(ary
, n
);
1510 ARY_INCREASE_LEN(ary
, -n
);
1516 behead_transient(VALUE ary
, long n
)
1518 rb_ary_modify_check(ary
);
1519 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
1520 MEMMOVE(ptr
, ptr
+n
, VALUE
, RARRAY_LEN(ary
)-n
);
1521 }); /* WB: no new reference */
1522 ARY_INCREASE_LEN(ary
, -n
);
1527 MJIT_FUNC_EXPORTED VALUE
1528 rb_ary_behead(VALUE ary
, long n
)
1533 else if (ARY_SHARED_P(ary
)) {
1534 return behead_shared(ary
, n
);
1536 else if (RARRAY_LEN(ary
) >= ARY_DEFAULT_SIZE
) {
1537 ary_make_shared(ary
);
1538 return behead_shared(ary
, n
);
1541 return behead_transient(ary
, n
);
1546 make_room_for_unshift(VALUE ary
, const VALUE
*head
, VALUE
*sharedp
, int argc
, long capa
, long len
)
1548 if (head
- sharedp
< argc
) {
1549 long room
= capa
- len
- argc
;
1552 MEMMOVE((VALUE
*)sharedp
+ argc
+ room
, head
, VALUE
, len
);
1553 head
= sharedp
+ argc
+ room
;
1555 ARY_SET_PTR(ary
, head
- argc
);
1556 assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary
)));
1559 return ARY_SHARED_ROOT(ary
);
1563 ary_modify_for_unshift(VALUE ary
, int argc
)
1565 long len
= RARRAY_LEN(ary
);
1566 long new_len
= len
+ argc
;
1568 const VALUE
*head
, *sharedp
;
1571 capa
= ARY_CAPA(ary
);
1572 if (capa
- (capa
>> 6) <= new_len
) {
1573 ary_double_capa(ary
, new_len
);
1576 /* use shared array for big "queues" */
1577 if (new_len
> ARY_DEFAULT_SIZE
* 4) {
1580 /* make a room for unshifted items */
1581 capa
= ARY_CAPA(ary
);
1582 ary_make_shared(ary
);
1584 head
= sharedp
= RARRAY_CONST_PTR_TRANSIENT(ary
);
1585 return make_room_for_unshift(ary
, head
, (void *)sharedp
, argc
, capa
, len
);
1589 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
1590 MEMMOVE(ptr
+ argc
, ptr
, VALUE
, len
);
1599 ary_ensure_room_for_unshift(VALUE ary
, int argc
)
1601 long len
= RARRAY_LEN(ary
);
1602 long new_len
= len
+ argc
;
1604 if (len
> ARY_MAX_SIZE
- argc
) {
1605 rb_raise(rb_eIndexError
, "index %ld too big", new_len
);
1607 else if (! ARY_SHARED_P(ary
)) {
1608 return ary_modify_for_unshift(ary
, argc
);
1611 VALUE shared_root
= ARY_SHARED_ROOT(ary
);
1612 long capa
= RARRAY_LEN(shared_root
);
1614 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root
)) {
1615 return ary_modify_for_unshift(ary
, argc
);
1617 else if (new_len
> capa
) {
1618 return ary_modify_for_unshift(ary
, argc
);
1621 const VALUE
* head
= RARRAY_CONST_PTR_TRANSIENT(ary
);
1622 void *sharedp
= (void *)RARRAY_CONST_PTR_TRANSIENT(shared_root
);
1624 rb_ary_modify_check(ary
);
1625 return make_room_for_unshift(ary
, head
, sharedp
, argc
, capa
, len
);
1632 * array.unshift(*objects) -> self
1634 * Prepends the given +objects+ to +self+:
1635 * a = [:foo, 'bar', 2]
1636 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1638 * Array#prepend is an alias for Array#unshift.
1640 * Related: #push, #pop, #shift.
1644 rb_ary_unshift_m(int argc
, VALUE
*argv
, VALUE ary
)
1646 long len
= RARRAY_LEN(ary
);
1650 rb_ary_modify_check(ary
);
1654 target_ary
= ary_ensure_room_for_unshift(ary
, argc
);
1655 ary_memcpy0(ary
, 0, argc
, argv
, target_ary
);
1656 ARY_SET_LEN(ary
, len
+ argc
);
1661 rb_ary_unshift(VALUE ary
, VALUE item
)
1663 return rb_ary_unshift_m(1,&item
,ary
);
1666 /* faster version - use this if you don't need to treat negative offset */
1668 rb_ary_elt(VALUE ary
, long offset
)
1670 long len
= RARRAY_LEN(ary
);
1671 if (len
== 0) return Qnil
;
1672 if (offset
< 0 || len
<= offset
) {
1675 return RARRAY_AREF(ary
, offset
);
1679 rb_ary_entry(VALUE ary
, long offset
)
1681 return rb_ary_entry_internal(ary
, offset
);
1685 rb_ary_subseq_step(VALUE ary
, long beg
, long len
, long step
)
1688 long alen
= RARRAY_LEN(ary
);
1690 if (beg
> alen
) return Qnil
;
1691 if (beg
< 0 || len
< 0) return Qnil
;
1693 if (alen
< len
|| alen
< beg
+ len
) {
1697 if (len
== 0) return ary_new(klass
, 0);
1699 rb_raise(rb_eArgError
, "slice step cannot be zero");
1701 return ary_make_partial(ary
, klass
, beg
, len
);
1703 return ary_make_partial_step(ary
, klass
, beg
, len
, step
);
1707 rb_ary_subseq(VALUE ary
, long beg
, long len
)
1709 return rb_ary_subseq_step(ary
, beg
, len
, 1);
1712 static VALUE
rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
);
1716 * array[index] -> object or nil
1717 * array[start, length] -> object or nil
1718 * array[range] -> object or nil
1719 * array[aseq] -> object or nil
1720 * array.slice(index) -> object or nil
1721 * array.slice(start, length) -> object or nil
1722 * array.slice(range) -> object or nil
1723 * array.slice(aseq) -> object or nil
1725 * Returns elements from +self+; does not modify +self+.
1727 * When a single \Integer argument +index+ is given, returns the element at offset +index+:
1728 * a = [:foo, 'bar', 2]
1731 * a # => [:foo, "bar", 2]
1733 * If +index+ is negative, counts relative to the end of +self+:
1734 * a = [:foo, 'bar', 2]
1738 * If +index+ is out of range, returns +nil+.
1740 * When two \Integer arguments +start+ and +length+ are given,
1741 * returns a new \Array of size +length+ containing successive elements beginning at offset +start+:
1742 * a = [:foo, 'bar', 2]
1743 * a[0, 2] # => [:foo, "bar"]
1744 * a[1, 2] # => ["bar", 2]
1746 * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
1747 * returns all elements from offset +start+ to the end:
1748 * a = [:foo, 'bar', 2]
1749 * a[0, 4] # => [:foo, "bar", 2]
1750 * a[1, 3] # => ["bar", 2]
1753 * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
1754 * returns a new empty \Array.
1756 * If +length+ is negative, returns +nil+.
1758 * When a single \Range argument +range+ is given,
1759 * treats <tt>range.min</tt> as +start+ above
1760 * and <tt>range.size</tt> as +length+ above:
1761 * a = [:foo, 'bar', 2]
1762 * a[0..1] # => [:foo, "bar"]
1763 * a[1..2] # => ["bar", 2]
1765 * Special case: If <tt>range.start == a.size</tt>, returns a new empty \Array.
1767 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1768 * a = [:foo, 'bar', 2]
1769 * a[0..-1] # => [:foo, "bar", 2]
1770 * a[0..-2] # => [:foo, "bar"]
1771 * a[0..-3] # => [:foo]
1773 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1774 * a = [:foo, 'bar', 2]
1776 * a[-2..2] # => ["bar", 2]
1777 * a[-3..2] # => [:foo, "bar", 2]
1779 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1780 * a = [:foo, 'bar', 2]
1785 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1786 * returns an Array of elements corresponding to the indexes produced by
1788 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1789 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1791 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1792 * is larger than array size, throws RangeError.
1793 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1794 * a[(1..11).step(2)]
1795 * # RangeError (((1..11).step(2)) out of range)
1797 * # RangeError (((7..).step(2)) out of range)
1799 * If given a single argument, and its type is not one of the listed, tries to
1800 * convert it to Integer, and raises if it is impossible:
1801 * a = [:foo, 'bar', 2]
1802 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1805 * Array#slice is an alias for Array#[].
1809 rb_ary_aref(int argc
, const VALUE
*argv
, VALUE ary
)
1811 rb_check_arity(argc
, 1, 2);
1813 return rb_ary_aref2(ary
, argv
[0], argv
[1]);
1815 return rb_ary_aref1(ary
, argv
[0]);
1819 rb_ary_aref2(VALUE ary
, VALUE b
, VALUE e
)
1821 long beg
= NUM2LONG(b
);
1822 long len
= NUM2LONG(e
);
1824 beg
+= RARRAY_LEN(ary
);
1826 return rb_ary_subseq(ary
, beg
, len
);
1829 MJIT_FUNC_EXPORTED VALUE
1830 rb_ary_aref1(VALUE ary
, VALUE arg
)
1832 long beg
, len
, step
;
1834 /* special case - speeding up */
1835 if (FIXNUM_P(arg
)) {
1836 return rb_ary_entry(ary
, FIX2LONG(arg
));
1838 /* check if idx is Range or ArithmeticSequence */
1839 switch (rb_arithmetic_sequence_beg_len_step(arg
, &beg
, &len
, &step
, RARRAY_LEN(ary
), 0)) {
1845 return rb_ary_subseq_step(ary
, beg
, len
, step
);
1848 return rb_ary_entry(ary
, NUM2LONG(arg
));
1853 * array.at(index) -> object
1855 * Returns the element at \Integer offset +index+; does not modify +self+.
1856 * a = [:foo, 'bar', 2]
1862 rb_ary_at(VALUE ary
, VALUE pos
)
1864 return rb_ary_entry(ary
, NUM2LONG(pos
));
1869 * array.first -> object or nil
1870 * array.first(n) -> new_array
1872 * Returns elements from +self+; does not modify +self+.
1874 * When no argument is given, returns the first element:
1875 * a = [:foo, 'bar', 2]
1877 * a # => [:foo, "bar", 2]
1879 * If +self+ is empty, returns +nil+.
1881 * When non-negative \Integer argument +n+ is given,
1882 * returns the first +n+ elements in a new \Array:
1883 * a = [:foo, 'bar', 2]
1884 * a.first(2) # => [:foo, "bar"]
1886 * If <tt>n >= array.size</tt>, returns all elements:
1887 * a = [:foo, 'bar', 2]
1888 * a.first(50) # => [:foo, "bar", 2]
1890 * If <tt>n == 0</tt> returns an new empty \Array:
1891 * a = [:foo, 'bar', 2]
1897 rb_ary_first(int argc
, VALUE
*argv
, VALUE ary
)
1900 if (RARRAY_LEN(ary
) == 0) return Qnil
;
1901 return RARRAY_AREF(ary
, 0);
1904 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_FIRST
);
1910 * array.last -> object or nil
1911 * array.last(n) -> new_array
1913 * Returns elements from +self+; +self+ is not modified.
1915 * When no argument is given, returns the last element:
1916 * a = [:foo, 'bar', 2]
1918 * a # => [:foo, "bar", 2]
1920 * If +self+ is empty, returns +nil+.
1922 * When non-negative \Innteger argument +n+ is given,
1923 * returns the last +n+ elements in a new \Array:
1924 * a = [:foo, 'bar', 2]
1925 * a.last(2) # => ["bar", 2]
1927 * If <tt>n >= array.size</tt>, returns all elements:
1928 * a = [:foo, 'bar', 2]
1929 * a.last(50) # => [:foo, "bar", 2]
1931 * If <tt>n == 0</tt>, returns an new empty \Array:
1932 * a = [:foo, 'bar', 2]
1939 rb_ary_last(int argc
, const VALUE
*argv
, VALUE ary
)
1942 long len
= RARRAY_LEN(ary
);
1943 if (len
== 0) return Qnil
;
1944 return RARRAY_AREF(ary
, len
-1);
1947 return ary_take_first_or_last(argc
, argv
, ary
, ARY_TAKE_LAST
);
1953 * array.fetch(index) -> element
1954 * array.fetch(index, default_value) -> element
1955 * array.fetch(index) {|index| ... } -> element
1957 * Returns the element at offset +index+.
1959 * With the single \Integer argument +index+,
1960 * returns the element at offset +index+:
1961 * a = [:foo, 'bar', 2]
1962 * a.fetch(1) # => "bar"
1964 * If +index+ is negative, counts from the end of the array:
1965 * a = [:foo, 'bar', 2]
1966 * a.fetch(-1) # => 2
1967 * a.fetch(-2) # => "bar"
1969 * With arguments +index+ and +default_value+,
1970 * returns the element at offset +index+ if index is in range,
1971 * otherwise returns +default_value+:
1972 * a = [:foo, 'bar', 2]
1973 * a.fetch(1, nil) # => "bar"
1975 * With argument +index+ and a block,
1976 * returns the element at offset +index+ if index is in range
1977 * (and the block is not called); otherwise calls the block with index and returns its return value:
1979 * a = [:foo, 'bar', 2]
1980 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
1981 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
1985 rb_ary_fetch(int argc
, VALUE
*argv
, VALUE ary
)
1991 rb_scan_args(argc
, argv
, "11", &pos
, &ifnone
);
1992 block_given
= rb_block_given_p();
1993 if (block_given
&& argc
== 2) {
1994 rb_warn("block supersedes default value argument");
1996 idx
= NUM2LONG(pos
);
1999 idx
+= RARRAY_LEN(ary
);
2001 if (idx
< 0 || RARRAY_LEN(ary
) <= idx
) {
2002 if (block_given
) return rb_yield(pos
);
2004 rb_raise(rb_eIndexError
, "index %ld outside of array bounds: %ld...%ld",
2005 idx
- (idx
< 0 ? RARRAY_LEN(ary
) : 0), -RARRAY_LEN(ary
), RARRAY_LEN(ary
));
2009 return RARRAY_AREF(ary
, idx
);
2014 * array.index(object) -> integer or nil
2015 * array.index {|element| ... } -> integer or nil
2016 * array.index -> new_enumerator
2018 * Returns the index of a specified element.
2020 * When argument +object+ is given but no block,
2021 * returns the index of the first element +element+
2022 * for which <tt>object == element</tt>:
2023 * a = [:foo, 'bar', 2, 'bar']
2024 * a.index('bar') # => 1
2026 * Returns +nil+ if no such element found.
2028 * When both argument +object+ and a block are given,
2029 * calls the block with each successive element;
2030 * returns the index of the first element for which the block returns a truthy value:
2031 * a = [:foo, 'bar', 2, 'bar']
2032 * a.index {|element| element == 'bar' } # => 1
2034 * Returns +nil+ if the block never returns a truthy value.
2036 * When neither an argument nor a block is given, returns a new Enumerator:
2037 * a = [:foo, 'bar', 2]
2039 * e # => #<Enumerator: [:foo, "bar", 2]:index>
2040 * e.each {|element| element == 'bar' } # => 1
2042 * Array#find_index is an alias for Array#index.
2048 rb_ary_index(int argc
, VALUE
*argv
, VALUE ary
)
2054 RETURN_ENUMERATOR(ary
, 0, 0);
2055 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2056 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
2062 rb_check_arity(argc
, 0, 1);
2064 if (rb_block_given_p())
2065 rb_warn("given block not used");
2066 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2067 VALUE e
= RARRAY_AREF(ary
, i
);
2068 if (rb_equal(e
, val
)) {
2077 * array.rindex(object) -> integer or nil
2078 * array.rindex {|element| ... } -> integer or nil
2079 * array.rindex -> new_enumerator
2081 * Returns the index of the last element for which <tt>object == element</tt>.
2083 * When argument +object+ is given but no block, returns the index of the last such element found:
2084 * a = [:foo, 'bar', 2, 'bar']
2085 * a.rindex('bar') # => 3
2087 * Returns +nil+ if no such object found.
2089 * When a block is given but no argument, calls the block with each successive element;
2090 * returns the index of the last element for which the block returns a truthy value:
2091 * a = [:foo, 'bar', 2, 'bar']
2092 * a.rindex {|element| element == 'bar' } # => 3
2094 * Returns +nil+ if the block never returns a truthy value.
2096 * When neither an argument nor a block is given, returns a new \Enumerator:
2098 * a = [:foo, 'bar', 2, 'bar']
2100 * e # => #<Enumerator: [:foo, "bar", 2, "bar"]:rindex>
2101 * e.each {|element| element == 'bar' } # => 3
2107 rb_ary_rindex(int argc
, VALUE
*argv
, VALUE ary
)
2110 long i
= RARRAY_LEN(ary
), len
;
2113 RETURN_ENUMERATOR(ary
, 0, 0);
2115 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
))))
2117 if (i
> (len
= RARRAY_LEN(ary
))) {
2123 rb_check_arity(argc
, 0, 1);
2125 if (rb_block_given_p())
2126 rb_warn("given block not used");
2128 VALUE e
= RARRAY_AREF(ary
, i
);
2129 if (rb_equal(e
, val
)) {
2132 if (i
> RARRAY_LEN(ary
)) {
2140 rb_ary_to_ary(VALUE obj
)
2142 VALUE tmp
= rb_check_array_type(obj
);
2144 if (!NIL_P(tmp
)) return tmp
;
2145 return rb_ary_new3(1, obj
);
2149 rb_ary_splice(VALUE ary
, long beg
, long len
, const VALUE
*rptr
, long rlen
)
2154 if (len
< 0) rb_raise(rb_eIndexError
, "negative length (%ld)", len
);
2155 olen
= RARRAY_LEN(ary
);
2159 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2163 if (olen
< len
|| olen
< beg
+ len
) {
2168 const VALUE
*optr
= RARRAY_CONST_PTR_TRANSIENT(ary
);
2169 rofs
= (rptr
>= optr
&& rptr
< optr
+ olen
) ? rptr
- optr
: -1;
2174 if (beg
> ARY_MAX_SIZE
- rlen
) {
2175 rb_raise(rb_eIndexError
, "index %ld too big", beg
);
2177 target_ary
= ary_ensure_room_for_push(ary
, rlen
-len
); /* len is 0 or negative */
2179 ary_mem_clear(ary
, olen
, beg
- olen
);
2181 if (rofs
!= -1) rptr
= RARRAY_CONST_PTR_TRANSIENT(ary
) + rofs
;
2182 ary_memcpy0(ary
, beg
, rlen
, rptr
, target_ary
);
2184 ARY_SET_LEN(ary
, len
);
2189 if (olen
- len
> ARY_MAX_SIZE
- rlen
) {
2190 rb_raise(rb_eIndexError
, "index %ld too big", olen
+ rlen
- len
);
2193 alen
= olen
+ rlen
- len
;
2194 if (alen
>= ARY_CAPA(ary
)) {
2195 ary_double_capa(ary
, alen
);
2199 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
,
2200 MEMMOVE(ptr
+ beg
+ rlen
, ptr
+ beg
+ len
,
2201 VALUE
, olen
- (beg
+ len
)));
2202 ARY_SET_LEN(ary
, alen
);
2205 if (rofs
!= -1) rptr
= RARRAY_CONST_PTR_TRANSIENT(ary
) + rofs
;
2206 /* give up wb-protected ary */
2207 RB_OBJ_WB_UNPROTECT_FOR(ARRAY
, ary
);
2209 /* do not use RARRAY_PTR() because it can causes GC.
2210 * ary can contain T_NONE object because it is not cleared.
2212 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
,
2213 MEMMOVE(ptr
+ beg
, rptr
, VALUE
, rlen
));
2219 rb_ary_set_len(VALUE ary
, long len
)
2223 rb_ary_modify_check(ary
);
2224 if (ARY_SHARED_P(ary
)) {
2225 rb_raise(rb_eRuntimeError
, "can't set length of shared ");
2227 if (len
> (capa
= (long)ARY_CAPA(ary
))) {
2228 rb_bug("probable buffer overflow: %ld for %ld", len
, capa
);
2230 ARY_SET_LEN(ary
, len
);
2234 rb_ary_resize(VALUE ary
, long len
)
2239 olen
= RARRAY_LEN(ary
);
2240 if (len
== olen
) return ary
;
2241 if (len
> ARY_MAX_SIZE
) {
2242 rb_raise(rb_eIndexError
, "index %ld too big", len
);
2245 if (len
>= ARY_CAPA(ary
)) {
2246 ary_double_capa(ary
, len
);
2248 ary_mem_clear(ary
, olen
, len
- olen
);
2249 ARY_SET_LEN(ary
, len
);
2251 else if (ARY_EMBED_P(ary
)) {
2252 ARY_SET_EMBED_LEN(ary
, len
);
2254 else if (len
<= RARRAY_EMBED_LEN_MAX
) {
2255 VALUE tmp
[RARRAY_EMBED_LEN_MAX
];
2256 MEMCPY(tmp
, ARY_HEAP_PTR(ary
), VALUE
, len
);
2258 MEMCPY((VALUE
*)ARY_EMBED_PTR(ary
), tmp
, VALUE
, len
); /* WB: no new reference */
2259 ARY_SET_EMBED_LEN(ary
, len
);
2262 if (olen
> len
+ ARY_DEFAULT_SIZE
) {
2263 size_t new_capa
= ary_heap_realloc(ary
, len
);
2264 ARY_SET_CAPA(ary
, new_capa
);
2266 ARY_SET_HEAP_LEN(ary
, len
);
2273 ary_aset_by_rb_ary_store(VALUE ary
, long key
, VALUE val
)
2275 rb_ary_store(ary
, key
, val
);
2280 ary_aset_by_rb_ary_splice(VALUE ary
, long beg
, long len
, VALUE val
)
2282 VALUE rpl
= rb_ary_to_ary(val
);
2283 rb_ary_splice(ary
, beg
, len
, RARRAY_CONST_PTR_TRANSIENT(rpl
), RARRAY_LEN(rpl
));
2290 * array[index] = object -> object
2291 * array[start, length] = object -> object
2292 * array[range] = object -> object
2294 * Assigns elements in +self+; returns the given +object+.
2296 * When \Integer argument +index+ is given, assigns +object+ to an element in +self+.
2298 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2299 * a = [:foo, 'bar', 2]
2300 * a[0] = 'foo' # => "foo"
2301 * a # => ["foo", "bar", 2]
2303 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2304 * a = [:foo, 'bar', 2]
2305 * a[7] = 'foo' # => "foo"
2306 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2308 * If +index+ is negative, counts backwards from the end of the array:
2309 * a = [:foo, 'bar', 2]
2310 * a[-1] = 'two' # => "two"
2311 * a # => [:foo, "bar", "two"]
2313 * When \Integer arguments +start+ and +length+ are given and +object+ is not an \Array,
2314 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2315 * and assigns +object+ at offset +start+:
2316 * a = [:foo, 'bar', 2]
2317 * a[0, 2] = 'foo' # => "foo"
2320 * If +start+ is negative, counts backwards from the end of the array:
2321 * a = [:foo, 'bar', 2]
2322 * a[-2, 2] = 'foo' # => "foo"
2323 * a # => [:foo, "foo"]
2325 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2326 * extends the array with +nil+, assigns +object+ at offset +start+,
2327 * and ignores +length+:
2328 * a = [:foo, 'bar', 2]
2329 * a[6, 50] = 'foo' # => "foo"
2330 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2332 * If +length+ is zero, shifts elements at and following offset +start+
2333 * and assigns +object+ at offset +start+:
2334 * a = [:foo, 'bar', 2]
2335 * a[1, 0] = 'foo' # => "foo"
2336 * a # => [:foo, "foo", "bar", 2]
2338 * If +length+ is too large for the existing array, does not extend the array:
2339 * a = [:foo, 'bar', 2]
2340 * a[1, 5] = 'foo' # => "foo"
2341 * a # => [:foo, "foo"]
2343 * When \Range argument +range+ is given and +object+ is an \Array,
2344 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2345 * and assigns +object+ at offset +start+:
2346 * a = [:foo, 'bar', 2]
2347 * a[0..1] = 'foo' # => "foo"
2350 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2351 * a = [:foo, 'bar', 2]
2352 * a[-2..2] = 'foo' # => "foo"
2353 * a # => [:foo, "foo"]
2355 * If the array length is less than <tt>range.begin</tt>,
2356 * assigns +object+ at offset <tt>range.begin</tt>, and ignores +length+:
2357 * a = [:foo, 'bar', 2]
2358 * a[6..50] = 'foo' # => "foo"
2359 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2361 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2362 * and assigns +object+ at offset +start+:
2363 * a = [:foo, 'bar', 2]
2364 * a[1..0] = 'foo' # => "foo"
2365 * a # => [:foo, "foo", "bar", 2]
2367 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2368 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2369 * a = [:foo, 'bar', 2]
2370 * a[1..-1] = 'foo' # => "foo"
2371 * a # => [:foo, "foo"]
2372 * a = [:foo, 'bar', 2]
2373 * a[1..-2] = 'foo' # => "foo"
2374 * a # => [:foo, "foo", 2]
2375 * a = [:foo, 'bar', 2]
2376 * a[1..-3] = 'foo' # => "foo"
2377 * a # => [:foo, "foo", "bar", 2]
2378 * a = [:foo, 'bar', 2]
2380 * If <tt>range.end</tt> is too large for the existing array,
2381 * replaces array elements, but does not extend the array with +nil+ values:
2382 * a = [:foo, 'bar', 2]
2383 * a[1..5] = 'foo' # => "foo"
2384 * a # => [:foo, "foo"]
2388 rb_ary_aset(int argc
, VALUE
*argv
, VALUE ary
)
2390 long offset
, beg
, len
;
2392 rb_check_arity(argc
, 2, 3);
2393 rb_ary_modify_check(ary
);
2395 beg
= NUM2LONG(argv
[0]);
2396 len
= NUM2LONG(argv
[1]);
2397 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[2]);
2399 if (FIXNUM_P(argv
[0])) {
2400 offset
= FIX2LONG(argv
[0]);
2401 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2403 if (rb_range_beg_len(argv
[0], &beg
, &len
, RARRAY_LEN(ary
), 1)) {
2404 /* check if idx is Range */
2405 return ary_aset_by_rb_ary_splice(ary
, beg
, len
, argv
[1]);
2408 offset
= NUM2LONG(argv
[0]);
2409 return ary_aset_by_rb_ary_store(ary
, offset
, argv
[1]);
2414 * array.insert(index, *objects) -> self
2416 * Inserts given +objects+ before or after the element at \Integer index +offset+;
2419 * When +index+ is non-negative, inserts all given +objects+
2420 * before the element at offset +index+:
2421 * a = [:foo, 'bar', 2]
2422 * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2]
2424 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2425 * a = [:foo, 'bar', 2]
2426 * a.insert(5, :bat, :bam)
2427 * a # => [:foo, "bar", 2, nil, nil, :bat, :bam]
2429 * Does nothing if no objects given:
2430 * a = [:foo, 'bar', 2]
2434 * a # => [:foo, "bar", 2]
2436 * When +index+ is negative, inserts all given +objects+
2437 * _after_ the element at offset <tt>index+self.size</tt>:
2438 * a = [:foo, 'bar', 2]
2439 * a.insert(-2, :bat, :bam)
2440 * a # => [:foo, "bar", :bat, :bam, 2]
2444 rb_ary_insert(int argc
, VALUE
*argv
, VALUE ary
)
2448 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
2449 rb_ary_modify_check(ary
);
2450 pos
= NUM2LONG(argv
[0]);
2451 if (argc
== 1) return ary
;
2453 pos
= RARRAY_LEN(ary
);
2456 long minpos
= -RARRAY_LEN(ary
) - 1;
2458 rb_raise(rb_eIndexError
, "index %ld too small for array; minimum: %ld",
2463 rb_ary_splice(ary
, pos
, 0, argv
+ 1, argc
- 1);
2468 rb_ary_length(VALUE ary
);
2471 ary_enum_length(VALUE ary
, VALUE args
, VALUE eobj
)
2473 return rb_ary_length(ary
);
2478 * array.each {|element| ... } -> self
2479 * array.each -> Enumerator
2481 * Iterates over array elements.
2483 * When a block given, passes each successive array element to the block;
2485 * a = [:foo, 'bar', 2]
2486 * a.each {|element| puts "#{element.class} #{element}" }
2493 * Allows the array to be modified during iteration:
2494 * a = [:foo, 'bar', 2]
2495 * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2501 * When no block given, returns a new \Enumerator:
2502 * a = [:foo, 'bar', 2]
2504 * e # => #<Enumerator: [:foo, "bar", 2]:each>
2505 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2512 * Related: #each_index, #reverse_each.
2516 rb_ary_each(VALUE ary
)
2520 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2521 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2522 rb_yield(RARRAY_AREF(ary
, i
));
2529 * array.each_index {|index| ... } -> self
2530 * array.each_index -> Enumerator
2532 * Iterates over array indexes.
2534 * When a block given, passes each successive array index to the block;
2536 * a = [:foo, 'bar', 2]
2537 * a.each_index {|index| puts "#{index} #{a[index]}" }
2544 * Allows the array to be modified during iteration:
2545 * a = [:foo, 'bar', 2]
2546 * a.each_index {|index| puts index; a.clear if index > 0 }
2552 * When no block given, returns a new \Enumerator:
2553 * a = [:foo, 'bar', 2]
2555 * e # => #<Enumerator: [:foo, "bar", 2]:each_index>
2556 * a1 = e.each {|index| puts "#{index} #{a[index]}"}
2563 * Related: #each, #reverse_each.
2567 rb_ary_each_index(VALUE ary
)
2570 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2572 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2573 rb_yield(LONG2NUM(i
));
2580 * array.reverse_each {|element| ... } -> self
2581 * array.reverse_each -> Enumerator
2583 * Iterates backwards over array elements.
2585 * When a block given, passes, in reverse order, each element to the block;
2587 * a = [:foo, 'bar', 2]
2588 * a.reverse_each {|element| puts "#{element.class} #{element}" }
2595 * Allows the array to be modified during iteration:
2596 * a = [:foo, 'bar', 2]
2597 * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2603 * When no block given, returns a new \Enumerator:
2604 * a = [:foo, 'bar', 2]
2605 * e = a.reverse_each
2606 * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
2607 * a1 = e.each {|element| puts "#{element.class} #{element}" }
2613 * Related: #each, #each_index.
2617 rb_ary_reverse_each(VALUE ary
)
2621 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
2622 len
= RARRAY_LEN(ary
);
2625 rb_yield(RARRAY_AREF(ary
, len
));
2626 nlen
= RARRAY_LEN(ary
);
2636 * array.length -> an_integer
2638 * Returns the count of elements in +self+.
2642 rb_ary_length(VALUE ary
)
2644 long len
= RARRAY_LEN(ary
);
2645 return LONG2NUM(len
);
2650 * array.empty? -> true or false
2652 * Returns +true+ if the count of elements in +self+ is zero,
2653 * +false+ otherwise.
2657 rb_ary_empty_p(VALUE ary
)
2659 return RBOOL(RARRAY_LEN(ary
) == 0);
2663 rb_ary_dup(VALUE ary
)
2665 long len
= RARRAY_LEN(ary
);
2666 VALUE dup
= rb_ary_new2(len
);
2667 ary_memcpy(dup
, 0, len
, RARRAY_CONST_PTR_TRANSIENT(ary
));
2668 ARY_SET_LEN(dup
, len
);
2676 rb_ary_resurrect(VALUE ary
)
2678 return ary_make_partial(ary
, rb_cArray
, 0, RARRAY_LEN(ary
));
2681 extern VALUE rb_output_fs
;
2683 static void ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
);
2686 recursive_join(VALUE obj
, VALUE argp
, int recur
)
2688 VALUE
*arg
= (VALUE
*)argp
;
2691 VALUE result
= arg
[2];
2692 int *first
= (int *)arg
[3];
2695 rb_raise(rb_eArgError
, "recursive array join");
2698 ary_join_1(obj
, ary
, sep
, 0, result
, first
);
2704 ary_join_0(VALUE ary
, VALUE sep
, long max
, VALUE result
)
2709 if (max
> 0) rb_enc_copy(result
, RARRAY_AREF(ary
, 0));
2710 for (i
=0; i
<max
; i
++) {
2711 val
= RARRAY_AREF(ary
, i
);
2712 if (!RB_TYPE_P(val
, T_STRING
)) break;
2713 if (i
> 0 && !NIL_P(sep
))
2714 rb_str_buf_append(result
, sep
);
2715 rb_str_buf_append(result
, val
);
2721 ary_join_1_str(VALUE dst
, VALUE src
, int *first
)
2723 rb_str_buf_append(dst
, src
);
2725 rb_enc_copy(dst
, src
);
2731 ary_join_1_ary(VALUE obj
, VALUE ary
, VALUE sep
, VALUE result
, VALUE val
, int *first
)
2734 rb_raise(rb_eArgError
, "recursive array join");
2743 args
[3] = (VALUE
)first
;
2744 rb_exec_recursive(recursive_join
, obj
, (VALUE
)args
);
2749 ary_join_1(VALUE obj
, VALUE ary
, VALUE sep
, long i
, VALUE result
, int *first
)
2753 for (; i
<RARRAY_LEN(ary
); i
++) {
2754 if (i
> 0 && !NIL_P(sep
))
2755 rb_str_buf_append(result
, sep
);
2757 val
= RARRAY_AREF(ary
, i
);
2758 if (RB_TYPE_P(val
, T_STRING
)) {
2759 ary_join_1_str(result
, val
, first
);
2761 else if (RB_TYPE_P(val
, T_ARRAY
)) {
2762 ary_join_1_ary(val
, ary
, sep
, result
, val
, first
);
2764 else if (!NIL_P(tmp
= rb_check_string_type(val
))) {
2765 ary_join_1_str(result
, tmp
, first
);
2767 else if (!NIL_P(tmp
= rb_check_array_type(val
))) {
2768 ary_join_1_ary(val
, ary
, sep
, result
, tmp
, first
);
2771 ary_join_1_str(result
, rb_obj_as_string(val
), first
);
2777 rb_ary_join(VALUE ary
, VALUE sep
)
2780 VALUE val
, tmp
, result
;
2782 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new(0, 0);
2786 len
+= RSTRING_LEN(sep
) * (RARRAY_LEN(ary
) - 1);
2788 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2789 val
= RARRAY_AREF(ary
, i
);
2790 tmp
= rb_check_string_type(val
);
2792 if (NIL_P(tmp
) || tmp
!= val
) {
2794 long n
= RARRAY_LEN(ary
);
2796 result
= rb_str_buf_new(len
+ (n
-i
)*10);
2797 rb_enc_associate(result
, rb_usascii_encoding());
2798 i
= ary_join_0(ary
, sep
, i
, result
);
2800 ary_join_1(ary
, ary
, sep
, i
, result
, &first
);
2804 len
+= RSTRING_LEN(tmp
);
2807 result
= rb_str_new(0, len
);
2808 rb_str_set_len(result
, 0);
2810 ary_join_0(ary
, sep
, RARRAY_LEN(ary
), result
);
2817 * array.join ->new_string
2818 * array.join(separator = $,) -> new_string
2820 * Returns the new \String formed by joining the array elements after conversion.
2821 * For each element +element+
2822 * - Uses <tt>element.to_s</tt> if +element+ is not a <tt>kind_of?(Array)</tt>.
2823 * - Uses recursive <tt>element.join(separator)</tt> if +element+ is a <tt>kind_of?(Array)</tt>.
2825 * With no argument, joins using the output field separator, <tt>$,</tt>:
2826 * a = [:foo, 'bar', 2]
2828 * a.join # => "foobar2"
2830 * With \string argument +separator+, joins using that separator:
2831 * a = [:foo, 'bar', 2]
2832 * a.join("\n") # => "foo\nbar\n2"
2834 * Joins recursively for nested Arrays:
2835 * a = [:foo, [:bar, [:baz, :bat]]]
2836 * a.join # => "foobarbazbat"
2839 rb_ary_join_m(int argc
, VALUE
*argv
, VALUE ary
)
2843 if (rb_check_arity(argc
, 0, 1) == 0 || NIL_P(sep
= argv
[0])) {
2846 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
2850 return rb_ary_join(ary
, sep
);
2854 inspect_ary(VALUE ary
, VALUE dummy
, int recur
)
2859 if (recur
) return rb_usascii_str_new_cstr("[...]");
2860 str
= rb_str_buf_new2("[");
2861 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2862 s
= rb_inspect(RARRAY_AREF(ary
, i
));
2863 if (i
> 0) rb_str_buf_cat2(str
, ", ");
2864 else rb_enc_copy(str
, s
);
2865 rb_str_buf_append(str
, s
);
2867 rb_str_buf_cat2(str
, "]");
2873 * array.inspect -> new_string
2875 * Returns the new \String formed by calling method <tt>#inspect</tt>
2876 * on each array element:
2877 * a = [:foo, 'bar', 2]
2878 * a.inspect # => "[:foo, \"bar\", 2]"
2880 * Array#to_s is an alias for Array#inspect.
2884 rb_ary_inspect(VALUE ary
)
2886 if (RARRAY_LEN(ary
) == 0) return rb_usascii_str_new2("[]");
2887 return rb_exec_recursive(inspect_ary
, ary
, 0);
2891 rb_ary_to_s(VALUE ary
)
2893 return rb_ary_inspect(ary
);
2898 * to_a -> self or new_array
2900 * When +self+ is an instance of \Array, returns +self+:
2901 * a = [:foo, 'bar', 2]
2902 * a.to_a # => [:foo, "bar", 2]
2904 * Otherwise, returns a new \Array containing the elements of +self+:
2905 * class MyArray < Array; end
2906 * a = MyArray.new(['foo', 'bar', 'two'])
2907 * a.instance_of?(Array) # => false
2908 * a.kind_of?(Array) # => true
2910 * a1 # => ["foo", "bar", "two"]
2911 * a1.class # => Array # Not MyArray
2915 rb_ary_to_a(VALUE ary
)
2917 if (rb_obj_class(ary
) != rb_cArray
) {
2918 VALUE dup
= rb_ary_new2(RARRAY_LEN(ary
));
2919 rb_ary_replace(dup
, ary
);
2927 * array.to_h -> new_hash
2928 * array.to_h {|item| ... } -> new_hash
2930 * Returns a new \Hash formed from +self+.
2932 * When a block is given, calls the block with each array element;
2933 * the block must return a 2-element \Array whose two elements
2934 * form a key-value pair in the returned \Hash:
2935 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
2936 * h = a.to_h {|item| [item, item] }
2937 * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
2939 * When no block is given, +self+ must be an \Array of 2-element sub-arrays,
2940 * each sub-array is formed into a key-value pair in the new \Hash:
2942 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
2944 * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
2948 rb_ary_to_h(VALUE ary
)
2951 VALUE hash
= rb_hash_new_with_size(RARRAY_LEN(ary
));
2952 int block_given
= rb_block_given_p();
2954 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
2955 const VALUE e
= rb_ary_elt(ary
, i
);
2956 const VALUE elt
= block_given
? rb_yield_force_blockarg(e
) : e
;
2957 const VALUE key_value_pair
= rb_check_array_type(elt
);
2958 if (NIL_P(key_value_pair
)) {
2959 rb_raise(rb_eTypeError
, "wrong element type %"PRIsVALUE
" at %ld (expected array)",
2960 rb_obj_class(elt
), i
);
2962 if (RARRAY_LEN(key_value_pair
) != 2) {
2963 rb_raise(rb_eArgError
, "wrong array length at %ld (expected 2, was %ld)",
2964 i
, RARRAY_LEN(key_value_pair
));
2966 rb_hash_aset(hash
, RARRAY_AREF(key_value_pair
, 0), RARRAY_AREF(key_value_pair
, 1));
2973 * array.to_ary -> self
2979 rb_ary_to_ary_m(VALUE ary
)
2985 ary_reverse(VALUE
*p1
, VALUE
*p2
)
2995 rb_ary_reverse(VALUE ary
)
2998 long len
= RARRAY_LEN(ary
);
3002 RARRAY_PTR_USE_TRANSIENT(ary
, p1
, {
3003 p2
= p1
+ len
- 1; /* points last item */
3004 ary_reverse(p1
, p2
);
3005 }); /* WB: no new reference */
3012 * array.reverse! -> self
3014 * Reverses +self+ in place:
3015 * a = ['foo', 'bar', 'two']
3016 * a.reverse! # => ["two", "bar", "foo"]
3020 rb_ary_reverse_bang(VALUE ary
)
3022 return rb_ary_reverse(ary
);
3027 * array.reverse -> new_array
3029 * Returns a new \Array with the elements of +self+ in reverse order.
3030 * a = ['foo', 'bar', 'two']
3032 * a1 # => ["two", "bar", "foo"]
3036 rb_ary_reverse_m(VALUE ary
)
3038 long len
= RARRAY_LEN(ary
);
3039 VALUE dup
= rb_ary_new2(len
);
3042 const VALUE
*p1
= RARRAY_CONST_PTR_TRANSIENT(ary
);
3043 VALUE
*p2
= (VALUE
*)RARRAY_CONST_PTR_TRANSIENT(dup
) + len
- 1;
3044 do *p2
-- = *p1
++; while (--len
> 0);
3046 ARY_SET_LEN(dup
, RARRAY_LEN(ary
));
3051 rotate_count(long cnt
, long len
)
3053 return (cnt
< 0) ? (len
- (~cnt
% len
) - 1) : (cnt
% len
);
3057 ary_rotate_ptr(VALUE
*ptr
, long len
, long cnt
)
3061 memmove(ptr
, ptr
+ 1, sizeof(VALUE
)*(len
- 1));
3062 *(ptr
+ len
- 1) = tmp
;
3064 else if (cnt
== len
- 1) {
3065 VALUE tmp
= *(ptr
+ len
- 1);
3066 memmove(ptr
+ 1, ptr
, sizeof(VALUE
)*(len
- 1));
3071 if (cnt
< len
) ary_reverse(ptr
+ cnt
, ptr
+ len
);
3072 if (--cnt
> 0) ary_reverse(ptr
, ptr
+ cnt
);
3073 if (len
> 0) ary_reverse(ptr
, ptr
+ len
);
3078 rb_ary_rotate(VALUE ary
, long cnt
)
3083 long len
= RARRAY_LEN(ary
);
3084 if (len
> 1 && (cnt
= rotate_count(cnt
, len
)) > 0) {
3085 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, ary_rotate_ptr(ptr
, len
, cnt
));
3094 * array.rotate! -> self
3095 * array.rotate!(count) -> self
3097 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3099 * When no argument given, rotates the first element to the last position:
3100 * a = [:foo, 'bar', 2, 'bar']
3101 * a.rotate! # => ["bar", 2, "bar", :foo]
3103 * When given a non-negative \Integer +count+,
3104 * rotates +count+ elements from the beginning to the end:
3105 * a = [:foo, 'bar', 2]
3107 * a # => [2, :foo, "bar"]
3109 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3110 * a = [:foo, 'bar', 2]
3112 * a # => [2, :foo, "bar"]
3114 * If +count+ is zero, returns +self+ unmodified:
3115 * a = [:foo, 'bar', 2]
3117 * a # => [:foo, "bar", 2]
3119 * When given a negative Integer +count+, rotates in the opposite direction,
3120 * from end to beginning:
3121 * a = [:foo, 'bar', 2]
3123 * a # => ["bar", 2, :foo]
3125 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3126 * a = [:foo, 'bar', 2]
3128 * a # => ["bar", 2, :foo]
3132 rb_ary_rotate_bang(int argc
, VALUE
*argv
, VALUE ary
)
3134 long n
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3135 rb_ary_rotate(ary
, n
);
3141 * array.rotate -> new_array
3142 * array.rotate(count) -> new_array
3144 * Returns a new \Array formed from +self+ with elements
3145 * rotated from one end to the other.
3147 * When no argument given, returns a new \Array that is like +self+,
3148 * except that the first element has been rotated to the last position:
3149 * a = [:foo, 'bar', 2, 'bar']
3151 * a1 # => ["bar", 2, "bar", :foo]
3153 * When given a non-negative \Integer +count+,
3154 * returns a new \Array with +count+ elements rotated from the beginning to the end:
3155 * a = [:foo, 'bar', 2]
3157 * a1 # => [2, :foo, "bar"]
3159 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3160 * a = [:foo, 'bar', 2]
3162 * a1 # => [2, :foo, "bar"]
3164 * If +count+ is zero, returns a copy of +self+, unmodified:
3165 * a = [:foo, 'bar', 2]
3167 * a1 # => [:foo, "bar", 2]
3169 * When given a negative \Integer +count+, rotates in the opposite direction,
3170 * from end to beginning:
3171 * a = [:foo, 'bar', 2]
3173 * a1 # => ["bar", 2, :foo]
3175 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3176 * a = [:foo, 'bar', 2]
3178 * a1 # => ["bar", 2, :foo]
3182 rb_ary_rotate_m(int argc
, VALUE
*argv
, VALUE ary
)
3187 long cnt
= (rb_check_arity(argc
, 0, 1) ? NUM2LONG(argv
[0]) : 1);
3189 len
= RARRAY_LEN(ary
);
3190 rotated
= rb_ary_new2(len
);
3192 cnt
= rotate_count(cnt
, len
);
3193 ptr
= RARRAY_CONST_PTR_TRANSIENT(ary
);
3195 ary_memcpy(rotated
, 0, len
, ptr
+ cnt
);
3196 ary_memcpy(rotated
, len
, cnt
, ptr
);
3198 ARY_SET_LEN(rotated
, RARRAY_LEN(ary
));
3202 struct ary_sort_data
{
3205 struct cmp_opt_data cmp_opt
;
3209 sort_reentered(VALUE ary
)
3211 if (RBASIC(ary
)->klass
) {
3212 rb_raise(rb_eRuntimeError
, "sort reentered");
3218 sort_returned(struct ary_sort_data
*data
)
3220 if (rb_obj_frozen_p(data
->receiver
)) {
3221 rb_raise(rb_eFrozenError
, "array frozen during sort");
3223 sort_reentered(data
->ary
);
3227 sort_1(const void *ap
, const void *bp
, void *dummy
)
3229 struct ary_sort_data
*data
= dummy
;
3230 VALUE retval
= sort_reentered(data
->ary
);
3231 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3237 retval
= rb_yield_values2(2, args
);
3238 n
= rb_cmpint(retval
, a
, b
);
3239 sort_returned(data
);
3244 sort_2(const void *ap
, const void *bp
, void *dummy
)
3246 struct ary_sort_data
*data
= dummy
;
3247 VALUE retval
= sort_reentered(data
->ary
);
3248 VALUE a
= *(const VALUE
*)ap
, b
= *(const VALUE
*)bp
;
3251 if (FIXNUM_P(a
) && FIXNUM_P(b
) && CMP_OPTIMIZABLE(data
->cmp_opt
, Integer
)) {
3252 if ((long)a
> (long)b
) return 1;
3253 if ((long)a
< (long)b
) return -1;
3256 if (STRING_P(a
) && STRING_P(b
) && CMP_OPTIMIZABLE(data
->cmp_opt
, String
)) {
3257 return rb_str_cmp(a
, b
);
3259 if (RB_FLOAT_TYPE_P(a
) && CMP_OPTIMIZABLE(data
->cmp_opt
, Float
)) {
3260 return rb_float_cmp(a
, b
);
3263 retval
= rb_funcallv(a
, id_cmp
, 1, &b
);
3264 n
= rb_cmpint(retval
, a
, b
);
3265 sort_returned(data
);
3272 * array.sort! -> self
3273 * array.sort! {|a, b| ... } -> self
3275 * Returns +self+ with its elements sorted in place.
3277 * With no block, compares elements using operator <tt><=></tt>
3279 * a = 'abcde'.split('').shuffle
3280 * a # => ["e", "b", "d", "a", "c"]
3282 * a # => ["a", "b", "c", "d", "e"]
3284 * With a block, calls the block with each element pair;
3285 * for each element pair +a+ and +b+, the block should return an integer:
3286 * - Negative when +b+ is to follow +a+.
3287 * - Zero when +a+ and +b+ are equivalent.
3288 * - Positive when +a+ is to follow +b+.
3291 * a = 'abcde'.split('').shuffle
3292 * a # => ["e", "b", "d", "a", "c"]
3293 * a.sort! {|a, b| a <=> b }
3294 * a # => ["a", "b", "c", "d", "e"]
3295 * a.sort! {|a, b| b <=> a }
3296 * a # => ["e", "d", "c", "b", "a"]
3298 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3299 * and may be unstable:
3300 * a = 'abcde'.split('').shuffle
3301 * a # => ["e", "b", "d", "a", "c"]
3302 * a.sort! {|a, b| 0 }
3303 * a # => ["d", "e", "c", "a", "b"]
3307 rb_ary_sort_bang(VALUE ary
)
3310 assert(!ARY_SHARED_P(ary
));
3311 if (RARRAY_LEN(ary
) > 1) {
3312 VALUE tmp
= ary_make_substitution(ary
); /* only ary refers tmp */
3313 struct ary_sort_data data
;
3314 long len
= RARRAY_LEN(ary
);
3315 RBASIC_CLEAR_CLASS(tmp
);
3317 data
.receiver
= ary
;
3318 data
.cmp_opt
.opt_methods
= 0;
3319 data
.cmp_opt
.opt_inited
= 0;
3320 RARRAY_PTR_USE(tmp
, ptr
, {
3321 ruby_qsort(ptr
, len
, sizeof(VALUE
),
3322 rb_block_given_p()?sort_1
:sort_2
, &data
);
3323 }); /* WB: no new reference */
3325 if (ARY_EMBED_P(tmp
)) {
3326 if (ARY_SHARED_P(ary
)) { /* ary might be destructively operated in the given block */
3327 rb_ary_unshare(ary
);
3330 ary_memcpy(ary
, 0, ARY_EMBED_LEN(tmp
), ARY_EMBED_PTR(tmp
));
3331 ARY_SET_LEN(ary
, ARY_EMBED_LEN(tmp
));
3334 if (!ARY_EMBED_P(ary
) && ARY_HEAP_PTR(ary
) == ARY_HEAP_PTR(tmp
)) {
3335 FL_UNSET_SHARED(ary
);
3336 ARY_SET_CAPA(ary
, RARRAY_LEN(tmp
));
3339 assert(!ARY_SHARED_P(tmp
));
3340 if (ARY_EMBED_P(ary
)) {
3341 FL_UNSET_EMBED(ary
);
3343 else if (ARY_SHARED_P(ary
)) {
3344 /* ary might be destructively operated in the given block */
3345 rb_ary_unshare(ary
);
3350 ARY_SET_PTR(ary
, ARY_HEAP_PTR(tmp
));
3351 ARY_SET_HEAP_LEN(ary
, len
);
3352 ARY_SET_CAPA(ary
, ARY_HEAP_LEN(tmp
));
3354 /* tmp was lost ownership for the ptr */
3355 FL_UNSET(tmp
, FL_FREEZE
);
3357 ARY_SET_EMBED_LEN(tmp
, 0);
3358 FL_SET(tmp
, FL_FREEZE
);
3360 /* tmp will be GC'ed. */
3361 RBASIC_SET_CLASS_RAW(tmp
, rb_cArray
); /* rb_cArray must be marked */
3369 * array.sort -> new_array
3370 * array.sort {|a, b| ... } -> new_array
3372 * Returns a new \Array whose elements are those from +self+, sorted.
3374 * With no block, compares elements using operator <tt><=></tt>
3376 * a = 'abcde'.split('').shuffle
3377 * a # => ["e", "b", "d", "a", "c"]
3379 * a1 # => ["a", "b", "c", "d", "e"]
3381 * With a block, calls the block with each element pair;
3382 * for each element pair +a+ and +b+, the block should return an integer:
3383 * - Negative when +b+ is to follow +a+.
3384 * - Zero when +a+ and +b+ are equivalent.
3385 * - Positive when +a+ is to follow +b+.
3388 * a = 'abcde'.split('').shuffle
3389 * a # => ["e", "b", "d", "a", "c"]
3390 * a1 = a.sort {|a, b| a <=> b }
3391 * a1 # => ["a", "b", "c", "d", "e"]
3392 * a2 = a.sort {|a, b| b <=> a }
3393 * a2 # => ["e", "d", "c", "b", "a"]
3395 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3396 * and may be unstable:
3397 * a = 'abcde'.split('').shuffle
3398 * a # => ["e", "b", "d", "a", "c"]
3399 * a1 = a.sort {|a, b| 0 }
3400 * a1 # => ["c", "e", "b", "d", "a"]
3402 * Related: Enumerable#sort_by.
3406 rb_ary_sort(VALUE ary
)
3408 ary
= rb_ary_dup(ary
);
3409 rb_ary_sort_bang(ary
);
3413 static VALUE
rb_ary_bsearch_index(VALUE ary
);
3417 * array.bsearch {|element| ... } -> object
3418 * array.bsearch -> new_enumerator
3420 * Returns an element from +self+ selected by a binary search.
3422 * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
3426 rb_ary_bsearch(VALUE ary
)
3428 VALUE index_result
= rb_ary_bsearch_index(ary
);
3430 if (FIXNUM_P(index_result
)) {
3431 return rb_ary_entry(ary
, FIX2LONG(index_result
));
3433 return index_result
;
3438 * array.bsearch_index {|element| ... } -> integer or nil
3439 * array.bsearch_index -> new_enumerator
3441 * Searches +self+ as described at method #bsearch,
3442 * but returns the _index_ of the found element instead of the element itself.
3446 rb_ary_bsearch_index(VALUE ary
)
3448 long low
= 0, high
= RARRAY_LEN(ary
), mid
;
3449 int smaller
= 0, satisfied
= 0;
3452 RETURN_ENUMERATOR(ary
, 0, 0);
3453 while (low
< high
) {
3454 mid
= low
+ ((high
- low
) / 2);
3455 val
= rb_ary_entry(ary
, mid
);
3458 if (v
== INT2FIX(0)) return INT2FIX(mid
);
3459 smaller
= (SIGNED_VALUE
)v
< 0; /* Fixnum preserves its sign-bit */
3461 else if (v
== Qtrue
) {
3465 else if (!RTEST(v
)) {
3468 else if (rb_obj_is_kind_of(v
, rb_cNumeric
)) {
3469 const VALUE zero
= INT2FIX(0);
3470 switch (rb_cmpint(rb_funcallv(v
, id_cmp
, 1, &zero
), v
, zero
)) {
3471 case 0: return INT2FIX(mid
);
3472 case 1: smaller
= 1; break;
3473 case -1: smaller
= 0;
3477 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
3478 " (must be numeric, true, false or nil)",
3488 if (!satisfied
) return Qnil
;
3489 return INT2FIX(low
);
3494 sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, dummy
))
3501 * array.sort_by! {|element| ... } -> self
3502 * array.sort_by! -> new_enumerator
3504 * Sorts the elements of +self+ in place,
3505 * using an ordering determined by the block; returns self.
3507 * Calls the block with each successive element;
3508 * sorts elements based on the values returned from the block.
3510 * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
3512 * This example sorts strings based on their sizes:
3513 * a = ['aaaa', 'bbb', 'cc', 'd']
3514 * a.sort_by! {|element| element.size }
3515 * a # => ["d", "cc", "bbb", "aaaa"]
3517 * Returns a new \Enumerator if no block given:
3519 * a = ['aaaa', 'bbb', 'cc', 'd']
3520 * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
3524 rb_ary_sort_by_bang(VALUE ary
)
3528 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3530 sorted
= rb_block_call(ary
, rb_intern("sort_by"), 0, 0, sort_by_i
, 0);
3531 rb_ary_replace(ary
, sorted
);
3538 * array.map {|element| ... } -> new_array
3539 * array.map -> new_enumerator
3541 * Calls the block, if given, with each element of +self+;
3542 * returns a new \Array whose elements are the return values from the block:
3543 * a = [:foo, 'bar', 2]
3544 * a1 = a.map {|element| element.class }
3545 * a1 # => [Symbol, String, Integer]
3547 * Returns a new \Enumerator if no block given:
3548 * a = [:foo, 'bar', 2]
3550 * a1 # => #<Enumerator: [:foo, "bar", 2]:map>
3552 * Array#collect is an alias for Array#map.
3556 rb_ary_collect(VALUE ary
)
3561 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3562 collect
= rb_ary_new2(RARRAY_LEN(ary
));
3563 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3564 rb_ary_push(collect
, rb_yield(RARRAY_AREF(ary
, i
)));
3572 * array.map! {|element| ... } -> self
3573 * array.map! -> new_enumerator
3575 * Calls the block, if given, with each element;
3576 * replaces the element with the block's return value:
3577 * a = [:foo, 'bar', 2]
3578 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3580 * Returns a new \Enumerator if no block given:
3581 * a = [:foo, 'bar', 2]
3583 * a1 # => #<Enumerator: [:foo, "bar", 2]:map!>
3585 * Array#collect! is an alias for Array#map!.
3589 rb_ary_collect_bang(VALUE ary
)
3593 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3595 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3596 rb_ary_store(ary
, i
, rb_yield(RARRAY_AREF(ary
, i
)));
3602 rb_get_values_at(VALUE obj
, long olen
, int argc
, const VALUE
*argv
, VALUE (*func
) (VALUE
, long))
3604 VALUE result
= rb_ary_new2(argc
);
3605 long beg
, len
, i
, j
;
3607 for (i
=0; i
<argc
; i
++) {
3608 if (FIXNUM_P(argv
[i
])) {
3609 rb_ary_push(result
, (*func
)(obj
, FIX2LONG(argv
[i
])));
3612 /* check if idx is Range */
3613 if (rb_range_beg_len(argv
[i
], &beg
, &len
, olen
, 1)) {
3614 long end
= olen
< beg
+len
? olen
: beg
+len
;
3615 for (j
= beg
; j
< end
; j
++) {
3616 rb_ary_push(result
, (*func
)(obj
, j
));
3619 rb_ary_resize(result
, RARRAY_LEN(result
) + (beg
+ len
) - j
);
3622 rb_ary_push(result
, (*func
)(obj
, NUM2LONG(argv
[i
])));
3628 append_values_at_single(VALUE result
, VALUE ary
, long olen
, VALUE idx
)
3631 if (FIXNUM_P(idx
)) {
3632 beg
= FIX2LONG(idx
);
3634 /* check if idx is Range */
3635 else if (rb_range_beg_len(idx
, &beg
, &len
, olen
, 1)) {
3637 const VALUE
*const src
= RARRAY_CONST_PTR_TRANSIENT(ary
);
3638 const long end
= beg
+ len
;
3639 const long prevlen
= RARRAY_LEN(result
);
3641 rb_ary_cat(result
, src
+ beg
, end
> olen
? olen
-beg
: len
);
3644 rb_ary_store(result
, prevlen
+ len
- 1, Qnil
);
3650 beg
= NUM2LONG(idx
);
3652 return rb_ary_push(result
, rb_ary_entry(ary
, beg
));
3657 * array.values_at(*indexes) -> new_array
3659 * Returns a new \Array whose elements are the elements
3660 * of +self+ at the given \Integer or \Range +indexes+.
3662 * For each positive +index+, returns the element at offset +index+:
3663 * a = [:foo, 'bar', 2]
3664 * a.values_at(0, 2) # => [:foo, 2]
3665 * a.values_at(0..1) # => [:foo, "bar"]
3667 * The given +indexes+ may be in any order, and may repeat:
3668 * a = [:foo, 'bar', 2]
3669 * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
3670 * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2]
3672 * Assigns +nil+ for an +index+ that is too large:
3673 * a = [:foo, 'bar', 2]
3674 * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
3676 * Returns a new empty \Array if no arguments given.
3678 * For each negative +index+, counts backward from the end of the array:
3679 * a = [:foo, 'bar', 2]
3680 * a.values_at(-1, -3) # => [2, :foo]
3682 * Assigns +nil+ for an +index+ that is too small:
3683 * a = [:foo, 'bar', 2]
3684 * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
3686 * The given +indexes+ may have a mixture of signs:
3687 * a = [:foo, 'bar', 2]
3688 * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
3692 rb_ary_values_at(int argc
, VALUE
*argv
, VALUE ary
)
3694 long i
, olen
= RARRAY_LEN(ary
);
3695 VALUE result
= rb_ary_new_capa(argc
);
3696 for (i
= 0; i
< argc
; ++i
) {
3697 append_values_at_single(result
, ary
, olen
, argv
[i
]);
3706 * array.select {|element| ... } -> new_array
3707 * array.select -> new_enumerator
3709 * Calls the block, if given, with each element of +self+;
3710 * returns a new \Array containing those elements of +self+
3711 * for which the block returns a truthy value:
3712 * a = [:foo, 'bar', 2, :bam]
3713 * a1 = a.select {|element| element.to_s.start_with?('b') }
3714 * a1 # => ["bar", :bam]
3716 * Returns a new \Enumerator if no block given:
3717 * a = [:foo, 'bar', 2, :bam]
3718 * a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
3720 * Array#filter is an alias for Array#select.
3724 rb_ary_select(VALUE ary
)
3729 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3730 result
= rb_ary_new2(RARRAY_LEN(ary
));
3731 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
3732 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
3733 rb_ary_push(result
, rb_ary_elt(ary
, i
));
3739 struct select_bang_arg
{
3745 select_bang_i(VALUE a
)
3747 volatile struct select_bang_arg
*arg
= (void *)a
;
3748 VALUE ary
= arg
->ary
;
3751 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
3752 VALUE v
= RARRAY_AREF(ary
, i1
);
3753 if (!RTEST(rb_yield(v
))) continue;
3755 rb_ary_store(ary
, i2
, v
);
3759 return (i1
== i2
) ? Qnil
: ary
;
3763 select_bang_ensure(VALUE a
)
3765 volatile struct select_bang_arg
*arg
= (void *)a
;
3766 VALUE ary
= arg
->ary
;
3767 long len
= RARRAY_LEN(ary
);
3768 long i1
= arg
->len
[0], i2
= arg
->len
[1];
3770 if (i2
< len
&& i2
< i1
) {
3775 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
3776 MEMMOVE(ptr
+ i2
, ptr
+ i1
, VALUE
, tail
);
3779 ARY_SET_LEN(ary
, i2
+ tail
);
3786 * array.select! {|element| ... } -> self or nil
3787 * array.select! -> new_enumerator
3789 * Calls the block, if given with each element of +self+;
3790 * removes from +self+ those elements for which the block returns +false+ or +nil+.
3792 * Returns +self+ if any elements were removed:
3793 * a = [:foo, 'bar', 2, :bam]
3794 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3796 * Returns +nil+ if no elements were removed.
3798 * Returns a new \Enumerator if no block given:
3799 * a = [:foo, 'bar', 2, :bam]
3800 * a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
3802 * Array#filter! is an alias for Array#select!.
3806 rb_ary_select_bang(VALUE ary
)
3808 struct select_bang_arg args
;
3810 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3814 args
.len
[0] = args
.len
[1] = 0;
3815 return rb_ensure(select_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
3820 * array.keep_if {|element| ... } -> self
3821 * array.keep_if -> new_enumeration
3823 * Retains those elements for which the block returns a truthy value;
3824 * deletes all other elements; returns +self+:
3825 * a = [:foo, 'bar', 2, :bam]
3826 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
3828 * Returns a new \Enumerator if no block given:
3829 * a = [:foo, 'bar', 2, :bam]
3830 * a.keep_if # => #<Enumerator: [:foo, "bar", 2, :bam]:keep_if>
3834 rb_ary_keep_if(VALUE ary
)
3836 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
3837 rb_ary_select_bang(ary
);
3842 ary_resize_smaller(VALUE ary
, long len
)
3845 if (RARRAY_LEN(ary
) > len
) {
3846 ARY_SET_LEN(ary
, len
);
3847 if (len
* 2 < ARY_CAPA(ary
) &&
3848 ARY_CAPA(ary
) > ARY_DEFAULT_SIZE
) {
3849 ary_resize_capa(ary
, len
* 2);
3856 * array.delete(obj) -> deleted_object
3857 * array.delete(obj) {|nosuch| ... } -> deleted_object or block_return
3859 * Removes zero or more elements from +self+; returns +self+.
3861 * When no block is given,
3862 * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>;
3863 * returns the last deleted element:
3864 * s1 = 'bar'; s2 = 'bar'
3865 * a = [:foo, s1, 2, s2]
3866 * a.delete('bar') # => "bar"
3869 * Returns +nil+ if no elements removed.
3871 * When a block is given,
3872 * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>.
3874 * If any such elements are found, ignores the block
3875 * and returns the last deleted element:
3876 * s1 = 'bar'; s2 = 'bar'
3877 * a = [:foo, s1, 2, s2]
3878 * deleted_obj = a.delete('bar') {|obj| fail 'Cannot happen' }
3881 * If no such elements are found, returns the block's return value:
3882 * a = [:foo, 'bar', 2]
3883 * a.delete(:nosuch) {|obj| "#{obj} not found" } # => "nosuch not found"
3887 rb_ary_delete(VALUE ary
, VALUE item
)
3892 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
3893 VALUE e
= RARRAY_AREF(ary
, i1
);
3895 if (rb_equal(e
, item
)) {
3900 rb_ary_store(ary
, i2
, e
);
3904 if (RARRAY_LEN(ary
) == i2
) {
3905 if (rb_block_given_p()) {
3906 return rb_yield(item
);
3911 ary_resize_smaller(ary
, i2
);
3918 rb_ary_delete_same(VALUE ary
, VALUE item
)
3922 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); i1
++) {
3923 VALUE e
= RARRAY_AREF(ary
, i1
);
3929 rb_ary_store(ary
, i2
, e
);
3933 if (RARRAY_LEN(ary
) == i2
) {
3937 ary_resize_smaller(ary
, i2
);
3941 rb_ary_delete_at(VALUE ary
, long pos
)
3943 long len
= RARRAY_LEN(ary
);
3946 if (pos
>= len
) return Qnil
;
3949 if (pos
< 0) return Qnil
;
3953 del
= RARRAY_AREF(ary
, pos
);
3954 RARRAY_PTR_USE_TRANSIENT(ary
, ptr
, {
3955 MEMMOVE(ptr
+pos
, ptr
+pos
+1, VALUE
, len
-pos
-1);
3957 ARY_INCREASE_LEN(ary
, -1);
3964 * array.delete_at(index) -> deleted_object or nil
3966 * Deletes an element from +self+, per the given \Integer +index+.
3968 * When +index+ is non-negative, deletes the element at offset +index+:
3969 * a = [:foo, 'bar', 2]
3970 * a.delete_at(1) # => "bar"
3973 * If index is too large, returns +nil+.
3975 * When +index+ is negative, counts backward from the end of the array:
3976 * a = [:foo, 'bar', 2]
3977 * a.delete_at(-2) # => "bar"
3980 * If +index+ is too small (far from zero), returns nil.
3984 rb_ary_delete_at_m(VALUE ary
, VALUE pos
)
3986 return rb_ary_delete_at(ary
, NUM2LONG(pos
));
3990 ary_slice_bang_by_rb_ary_splice(VALUE ary
, long pos
, long len
)
3992 const long orig_len
= RARRAY_LEN(ary
);
3997 else if (pos
< -orig_len
) {
4003 else if (orig_len
< pos
) {
4006 if (orig_len
< pos
+ len
) {
4007 len
= orig_len
- pos
;
4010 return rb_ary_new2(0);
4013 VALUE arg2
= rb_ary_new4(len
, RARRAY_CONST_PTR_TRANSIENT(ary
)+pos
);
4014 rb_ary_splice(ary
, pos
, len
, 0, 0);
4021 * array.slice!(n) -> object or nil
4022 * array.slice!(start, length) -> new_array or nil
4023 * array.slice!(range) -> new_array or nil
4025 * Removes and returns elements from +self+.
4027 * When the only argument is an \Integer +n+,
4028 * removes and returns the _nth_ element in +self+:
4029 * a = [:foo, 'bar', 2]
4030 * a.slice!(1) # => "bar"
4033 * If +n+ is negative, counts backwards from the end of +self+:
4034 * a = [:foo, 'bar', 2]
4035 * a.slice!(-1) # => 2
4036 * a # => [:foo, "bar"]
4038 * If +n+ is out of range, returns +nil+.
4040 * When the only arguments are Integers +start+ and +length+,
4041 * removes +length+ elements from +self+ beginning at offset +start+;
4042 * returns the deleted objects in a new Array:
4043 * a = [:foo, 'bar', 2]
4044 * a.slice!(0, 2) # => [:foo, "bar"]
4047 * If <tt>start + length</tt> exceeds the array size,
4048 * removes and returns all elements from offset +start+ to the end:
4049 * a = [:foo, 'bar', 2]
4050 * a.slice!(1, 50) # => ["bar", 2]
4053 * If <tt>start == a.size</tt> and +length+ is non-negative,
4054 * returns a new empty \Array.
4056 * If +length+ is negative, returns +nil+.
4058 * When the only argument is a \Range object +range+,
4059 * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
4060 * a = [:foo, 'bar', 2]
4061 * a.slice!(1..2) # => ["bar", 2]
4064 * If <tt>range.start == a.size</tt>, returns a new empty \Array.
4066 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
4068 * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
4069 * a = [:foo, 'bar', 2]
4070 * a.slice!(0..-2) # => [:foo, "bar"]
4073 * If <tt>range.start</tt> is negative,
4074 * calculates the start index backwards from the end of the array:
4075 * a = [:foo, 'bar', 2]
4076 * a.slice!(-2..2) # => ["bar", 2]
4081 rb_ary_slice_bang(int argc
, VALUE
*argv
, VALUE ary
)
4086 rb_ary_modify_check(ary
);
4087 rb_check_arity(argc
, 1, 2);
4091 pos
= NUM2LONG(argv
[0]);
4092 len
= NUM2LONG(argv
[1]);
4093 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4096 if (!FIXNUM_P(arg1
)) {
4097 switch (rb_range_beg_len(arg1
, &pos
, &len
, RARRAY_LEN(ary
), 0)) {
4100 return ary_slice_bang_by_rb_ary_splice(ary
, pos
, len
);
4110 return rb_ary_delete_at(ary
, NUM2LONG(arg1
));
4114 ary_reject(VALUE orig
, VALUE result
)
4118 for (i
= 0; i
< RARRAY_LEN(orig
); i
++) {
4119 VALUE v
= RARRAY_AREF(orig
, i
);
4121 if (!RTEST(rb_yield(v
))) {
4122 rb_ary_push(result
, v
);
4129 reject_bang_i(VALUE a
)
4131 volatile struct select_bang_arg
*arg
= (void *)a
;
4132 VALUE ary
= arg
->ary
;
4135 for (i1
= i2
= 0; i1
< RARRAY_LEN(ary
); arg
->len
[0] = ++i1
) {
4136 VALUE v
= RARRAY_AREF(ary
, i1
);
4137 if (RTEST(rb_yield(v
))) continue;
4139 rb_ary_store(ary
, i2
, v
);
4143 return (i1
== i2
) ? Qnil
: ary
;
4147 ary_reject_bang(VALUE ary
)
4149 struct select_bang_arg args
;
4150 rb_ary_modify_check(ary
);
4152 args
.len
[0] = args
.len
[1] = 0;
4153 return rb_ensure(reject_bang_i
, (VALUE
)&args
, select_bang_ensure
, (VALUE
)&args
);
4158 * array.reject! {|element| ... } -> self or nil
4159 * array.reject! -> new_enumerator
4161 * Removes each element for which the block returns a truthy value.
4163 * Returns +self+ if any elements removed:
4164 * a = [:foo, 'bar', 2, 'bat']
4165 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4167 * Returns +nil+ if no elements removed.
4169 * Returns a new \Enumerator if no block given:
4170 * a = [:foo, 'bar', 2]
4171 * a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
4175 rb_ary_reject_bang(VALUE ary
)
4177 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4179 return ary_reject_bang(ary
);
4184 * array.reject {|element| ... } -> new_array
4185 * array.reject -> new_enumerator
4187 * Returns a new \Array whose elements are all those from +self+
4188 * for which the block returns +false+ or +nil+:
4189 * a = [:foo, 'bar', 2, 'bat']
4190 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4193 * Returns a new \Enumerator if no block given:
4194 * a = [:foo, 'bar', 2]
4195 * a.reject # => #<Enumerator: [:foo, "bar", 2]:reject>
4199 rb_ary_reject(VALUE ary
)
4203 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4204 rejected_ary
= rb_ary_new();
4205 ary_reject(ary
, rejected_ary
);
4206 return rejected_ary
;
4211 * array.delete_if {|element| ... } -> self
4212 * array.delete_if -> Enumerator
4214 * Removes each element in +self+ for which the block returns a truthy value;
4216 * a = [:foo, 'bar', 2, 'bat']
4217 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4219 * Returns a new \Enumerator if no block given:
4220 * a = [:foo, 'bar', 2]
4221 * a.delete_if # => #<Enumerator: [:foo, "bar", 2]:delete_if>
4225 rb_ary_delete_if(VALUE ary
)
4228 RETURN_SIZED_ENUMERATOR(ary
, 0, 0, ary_enum_length
);
4229 ary_reject_bang(ary
);
4234 take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val
, cbarg
))
4236 VALUE
*args
= (VALUE
*)cbarg
;
4237 if (argc
> 1) val
= rb_ary_new4(argc
, argv
);
4238 rb_ary_push(args
[0], val
);
4239 if (--args
[1] == 0) rb_iter_break();
4244 take_items(VALUE obj
, long n
)
4246 VALUE result
= rb_check_array_type(obj
);
4249 if (n
== 0) return result
;
4250 if (!NIL_P(result
)) return rb_ary_subseq(result
, 0, n
);
4251 result
= rb_ary_new2(n
);
4252 args
[0] = result
; args
[1] = (VALUE
)n
;
4253 if (rb_check_block_call(obj
, idEach
, 0, 0, take_i
, (VALUE
)args
) == Qundef
)
4254 rb_raise(rb_eTypeError
, "wrong argument type %"PRIsVALUE
" (must respond to :each)",
4262 * array.zip(*other_arrays) -> new_array
4263 * array.zip(*other_arrays) {|other_array| ... } -> nil
4265 * When no block given, returns a new \Array +new_array+ of size <tt>self.size</tt>
4266 * whose elements are Arrays.
4268 * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
4270 * - The _nth_ element of +self+.
4271 * - The _nth_ element of each of the +other_arrays+.
4273 * If all +other_arrays+ and +self+ are the same size:
4274 * a = [:a0, :a1, :a2, :a3]
4275 * b = [:b0, :b1, :b2, :b3]
4276 * c = [:c0, :c1, :c2, :c3]
4278 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4280 * If any array in +other_arrays+ is smaller than +self+,
4281 * fills to <tt>self.size</tt> with +nil+:
4282 * a = [:a0, :a1, :a2, :a3]
4283 * b = [:b0, :b1, :b2]
4286 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
4288 * If any array in +other_arrays+ is larger than +self+,
4289 * its trailing elements are ignored:
4290 * a = [:a0, :a1, :a2, :a3]
4291 * b = [:b0, :b1, :b2, :b3, :b4]
4292 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4294 * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
4296 * When a block is given, calls the block with each of the sub-arrays (formed as above); returns nil
4297 * a = [:a0, :a1, :a2, :a3]
4298 * b = [:b0, :b1, :b2, :b3]
4299 * c = [:c0, :c1, :c2, :c3]
4300 * a.zip(b, c) {|sub_array| p sub_array} # => nil
4310 rb_ary_zip(int argc
, VALUE
*argv
, VALUE ary
)
4313 long len
= RARRAY_LEN(ary
);
4314 VALUE result
= Qnil
;
4316 for (i
=0; i
<argc
; i
++) {
4317 argv
[i
] = take_items(argv
[i
], len
);
4320 if (rb_block_given_p()) {
4321 int arity
= rb_block_arity();
4326 tmp
= ALLOCV_N(VALUE
, work
, argc
+1);
4328 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4329 tmp
[0] = RARRAY_AREF(ary
, i
);
4330 for (j
=0; j
<argc
; j
++) {
4331 tmp
[j
+1] = rb_ary_elt(argv
[j
], i
);
4333 rb_yield_values2(argc
+1, tmp
);
4336 if (work
) ALLOCV_END(work
);
4339 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
4340 VALUE tmp
= rb_ary_new2(argc
+1);
4342 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4343 for (j
=0; j
<argc
; j
++) {
4344 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4351 result
= rb_ary_new_capa(len
);
4353 for (i
=0; i
<len
; i
++) {
4354 VALUE tmp
= rb_ary_new_capa(argc
+1);
4356 rb_ary_push(tmp
, RARRAY_AREF(ary
, i
));
4357 for (j
=0; j
<argc
; j
++) {
4358 rb_ary_push(tmp
, rb_ary_elt(argv
[j
], i
));
4360 rb_ary_push(result
, tmp
);
4369 * array.transpose -> new_array
4371 * Transposes the rows and columns in an \Array of Arrays;
4372 * the nested Arrays must all be the same size:
4373 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4374 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4378 rb_ary_transpose(VALUE ary
)
4380 long elen
= -1, alen
, i
, j
;
4381 VALUE tmp
, result
= 0;
4383 alen
= RARRAY_LEN(ary
);
4384 if (alen
== 0) return rb_ary_dup(ary
);
4385 for (i
=0; i
<alen
; i
++) {
4386 tmp
= to_ary(rb_ary_elt(ary
, i
));
4387 if (elen
< 0) { /* first element */
4388 elen
= RARRAY_LEN(tmp
);
4389 result
= rb_ary_new2(elen
);
4390 for (j
=0; j
<elen
; j
++) {
4391 rb_ary_store(result
, j
, rb_ary_new2(alen
));
4394 else if (elen
!= RARRAY_LEN(tmp
)) {
4395 rb_raise(rb_eIndexError
, "element size differs (%ld should be %ld)",
4396 RARRAY_LEN(tmp
), elen
);
4398 for (j
=0; j
<elen
; j
++) {
4399 rb_ary_store(rb_ary_elt(result
, j
), i
, rb_ary_elt(tmp
, j
));
4407 * array.replace(other_array) -> self
4409 * Replaces the content of +self+ with the content of +other_array+; returns +self+:
4410 * a = [:foo, 'bar', 2]
4411 * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3]
4415 rb_ary_replace(VALUE copy
, VALUE orig
)
4417 rb_ary_modify_check(copy
);
4418 orig
= to_ary(orig
);
4419 if (copy
== orig
) return copy
;
4421 if (RARRAY_LEN(orig
) <= RARRAY_EMBED_LEN_MAX
) {
4422 VALUE shared_root
= 0;
4424 if (ARY_OWNS_HEAP_P(copy
)) {
4425 ary_heap_free(copy
);
4427 else if (ARY_SHARED_P(copy
)) {
4428 shared_root
= ARY_SHARED_ROOT(copy
);
4429 FL_UNSET_SHARED(copy
);
4432 ary_memcpy(copy
, 0, RARRAY_LEN(orig
), RARRAY_CONST_PTR_TRANSIENT(orig
));
4434 rb_ary_decrement_share(shared_root
);
4436 ARY_SET_LEN(copy
, RARRAY_LEN(orig
));
4439 VALUE shared_root
= ary_make_shared(orig
);
4440 if (ARY_OWNS_HEAP_P(copy
)) {
4441 ary_heap_free(copy
);
4444 rb_ary_unshare_safe(copy
);
4446 FL_UNSET_EMBED(copy
);
4447 ARY_SET_PTR(copy
, ARY_HEAP_PTR(orig
));
4448 ARY_SET_LEN(copy
, ARY_HEAP_LEN(orig
));
4449 rb_ary_set_shared(copy
, shared_root
);
4457 * array.clear -> self
4459 * Removes all elements from +self+:
4460 * a = [:foo, 'bar', 2]
4465 rb_ary_clear(VALUE ary
)
4467 rb_ary_modify_check(ary
);
4468 if (ARY_SHARED_P(ary
)) {
4469 if (!ARY_EMBED_P(ary
)) {
4470 rb_ary_unshare(ary
);
4472 ARY_SET_EMBED_LEN(ary
, 0);
4476 ARY_SET_LEN(ary
, 0);
4477 if (ARY_DEFAULT_SIZE
* 2 < ARY_CAPA(ary
)) {
4478 ary_resize_capa(ary
, ARY_DEFAULT_SIZE
* 2);
4487 * array.fill(obj) -> self
4488 * array.fill(obj, start) -> self
4489 * array.fill(obj, start, length) -> self
4490 * array.fill(obj, range) -> self
4491 * array.fill {|index| ... } -> self
4492 * array.fill(start) {|index| ... } -> self
4493 * array.fill(start, length) {|index| ... } -> self
4494 * array.fill(range) {|index| ... } -> self
4496 * Replaces specified elements in +self+ with specified objects; returns +self+.
4498 * With argument +obj+ and no block given, replaces all elements with that one object:
4499 * a = ['a', 'b', 'c', 'd']
4500 * a # => ["a", "b", "c", "d"]
4501 * a.fill(:X) # => [:X, :X, :X, :X]
4503 * With arguments +obj+ and \Integer +start+, and no block given,
4504 * replaces elements based on the given start.
4506 * If +start+ is in range (<tt>0 <= start < array.size</tt>),
4507 * replaces all elements from offset +start+ through the end:
4508 * a = ['a', 'b', 'c', 'd']
4509 * a.fill(:X, 2) # => ["a", "b", :X, :X]
4511 * If +start+ is too large (<tt>start >= array.size</tt>), does nothing:
4512 * a = ['a', 'b', 'c', 'd']
4513 * a.fill(:X, 4) # => ["a", "b", "c", "d"]
4514 * a = ['a', 'b', 'c', 'd']
4515 * a.fill(:X, 5) # => ["a", "b", "c", "d"]
4517 * If +start+ is negative, counts from the end (starting index is <tt>start + array.size</tt>):
4518 * a = ['a', 'b', 'c', 'd']
4519 * a.fill(:X, -2) # => ["a", "b", :X, :X]
4521 * If +start+ is too small (less than and far from zero), replaces all elements:
4522 * a = ['a', 'b', 'c', 'd']
4523 * a.fill(:X, -6) # => [:X, :X, :X, :X]
4524 * a = ['a', 'b', 'c', 'd']
4525 * a.fill(:X, -50) # => [:X, :X, :X, :X]
4527 * With arguments +obj+, \Integer +start+, and \Integer +length+, and no block given,
4528 * replaces elements based on the given +start+ and +length+.
4530 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4531 * a = ['a', 'b', 'c', 'd']
4532 * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"]
4534 * If +start+ is negative, counts from the end:
4535 * a = ['a', 'b', 'c', 'd']
4536 * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"]
4538 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4539 * a = ['a', 'b', 'c', 'd']
4540 * a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil]
4541 * a = ['a', 'b', 'c', 'd']
4542 * a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X]
4544 * If +length+ is zero or negative, replaces no elements:
4545 * a = ['a', 'b', 'c', 'd']
4546 * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"]
4547 * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"]
4549 * With arguments +obj+ and \Range +range+, and no block given,
4550 * replaces elements based on the given range.
4552 * If the range is positive and ascending (<tt>0 < range.begin <= range.end</tt>),
4553 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4554 * a = ['a', 'b', 'c', 'd']
4555 * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"]
4557 * If <tt>range.first</tt> is negative, replaces no elements:
4558 * a = ['a', 'b', 'c', 'd']
4559 * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"]
4561 * If <tt>range.last</tt> is negative, counts from the end:
4562 * a = ['a', 'b', 'c', 'd']
4563 * a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"]
4564 * a = ['a', 'b', 'c', 'd']
4565 * a.fill(:X, (1..-2)) # => ["a", :X, :X, "d"]
4567 * If <tt>range.last</tt> and <tt>range.last</tt> are both negative,
4568 * both count from the end of the array:
4569 * a = ['a', 'b', 'c', 'd']
4570 * a.fill(:X, (-1..-1)) # => ["a", "b", "c", :X]
4571 * a = ['a', 'b', 'c', 'd']
4572 * a.fill(:X, (-2..-2)) # => ["a", "b", :X, "d"]
4574 * With no arguments and a block given, calls the block with each index;
4575 * replaces the corresponding element with the block's return value:
4576 * a = ['a', 'b', 'c', 'd']
4577 * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4579 * With argument +start+ and a block given, calls the block with each index
4580 * from offset +start+ to the end; replaces the corresponding element
4581 * with the block's return value:
4583 * If start is in range (<tt>0 <= start < array.size</tt>),
4584 * replaces from offset +start+ to the end:
4585 * a = ['a', 'b', 'c', 'd']
4586 * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"]
4588 * If +start+ is too large(<tt>start >= array.size</tt>), does nothing:
4589 * a = ['a', 'b', 'c', 'd']
4590 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4591 * a = ['a', 'b', 'c', 'd']
4592 * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4594 * If +start+ is negative, counts from the end:
4595 * a = ['a', 'b', 'c', 'd']
4596 * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"]
4598 * If start is too small (<tt>start <= -array.size</tt>, replaces all elements:
4599 * a = ['a', 'b', 'c', 'd']
4600 * a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4601 * a = ['a', 'b', 'c', 'd']
4602 * a.fill(-50) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
4604 * With arguments +start+ and +length+, and a block given,
4605 * calls the block for each index specified by start length;
4606 * replaces the corresponding element with the block's return value.
4608 * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
4609 * a = ['a', 'b', 'c', 'd']
4610 * a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4612 * If start is negative, counts from the end:
4613 * a = ['a', 'b', 'c', 'd']
4614 * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4616 * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
4617 * a = ['a', 'b', 'c', 'd']
4618 * a.fill(5, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil]
4619 * a = ['a', 'b', 'c', 'd']
4620 * a.fill(5, 2) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil, "new_5", "new_6"]
4622 * If +length+ is zero or less, replaces no elements:
4623 * a = ['a', 'b', 'c', 'd']
4624 * a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4625 * a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
4627 * With arguments +obj+ and +range+, and a block given,
4628 * calls the block with each index in the given range;
4629 * replaces the corresponding element with the block's return value.
4631 * If the range is positive and ascending (<tt>range 0 < range.begin <= range.end</tt>,
4632 * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
4633 * a = ['a', 'b', 'c', 'd']
4634 * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
4636 * If +range.first+ is negative, does nothing:
4637 * a = ['a', 'b', 'c', 'd']
4638 * a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
4640 * If <tt>range.last</tt> is negative, counts from the end:
4641 * a = ['a', 'b', 'c', 'd']
4642 * a.fill(0..-2) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "d"]
4643 * a = ['a', 'b', 'c', 'd']
4644 * a.fill(1..-2) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "d"]
4646 * If <tt>range.first</tt> and <tt>range.last</tt> are both negative,
4647 * both count from the end:
4648 * a = ['a', 'b', 'c', 'd']
4649 * a.fill(-1..-1) { |index| "new_#{index}" } # => ["a", "b", "c", "new_3"]
4650 * a = ['a', 'b', 'c', 'd']
4651 * a.fill(-2..-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
4655 rb_ary_fill(int argc
, VALUE
*argv
, VALUE ary
)
4657 VALUE item
= Qundef
, arg1
, arg2
;
4658 long beg
= 0, end
= 0, len
= 0;
4660 if (rb_block_given_p()) {
4661 rb_scan_args(argc
, argv
, "02", &arg1
, &arg2
);
4662 argc
+= 1; /* hackish */
4665 rb_scan_args(argc
, argv
, "12", &item
, &arg1
, &arg2
);
4670 len
= RARRAY_LEN(ary
);
4673 if (rb_range_beg_len(arg1
, &beg
, &len
, RARRAY_LEN(ary
), 1)) {
4678 beg
= NIL_P(arg1
) ? 0 : NUM2LONG(arg1
);
4680 beg
= RARRAY_LEN(ary
) + beg
;
4681 if (beg
< 0) beg
= 0;
4683 len
= NIL_P(arg2
) ? RARRAY_LEN(ary
) - beg
: NUM2LONG(arg2
);
4690 if (beg
>= ARY_MAX_SIZE
|| len
> ARY_MAX_SIZE
- beg
) {
4691 rb_raise(rb_eArgError
, "argument too big");
4694 if (RARRAY_LEN(ary
) < end
) {
4695 if (end
>= ARY_CAPA(ary
)) {
4696 ary_resize_capa(ary
, end
);
4698 ary_mem_clear(ary
, RARRAY_LEN(ary
), end
- RARRAY_LEN(ary
));
4699 ARY_SET_LEN(ary
, end
);
4702 if (item
== Qundef
) {
4706 for (i
=beg
; i
<end
; i
++) {
4707 v
= rb_yield(LONG2NUM(i
));
4708 if (i
>=RARRAY_LEN(ary
)) break;
4713 ary_memfill(ary
, beg
, len
, item
);
4720 * array + other_array -> new_array
4722 * Returns a new \Array containing all elements of +array+
4723 * followed by all elements of +other_array+:
4724 * a = [0, 1] + [2, 3]
4725 * a # => [0, 1, 2, 3]
4731 rb_ary_plus(VALUE x
, VALUE y
)
4734 long len
, xlen
, ylen
;
4737 xlen
= RARRAY_LEN(x
);
4738 ylen
= RARRAY_LEN(y
);
4740 z
= rb_ary_new2(len
);
4742 ary_memcpy(z
, 0, xlen
, RARRAY_CONST_PTR_TRANSIENT(x
));
4743 ary_memcpy(z
, xlen
, ylen
, RARRAY_CONST_PTR_TRANSIENT(y
));
4744 ARY_SET_LEN(z
, len
);
4749 ary_append(VALUE x
, VALUE y
)
4751 long n
= RARRAY_LEN(y
);
4753 rb_ary_splice(x
, RARRAY_LEN(x
), 0, RARRAY_CONST_PTR_TRANSIENT(y
), n
);
4761 * array.concat(*other_arrays) -> self
4763 * Adds to +array+ all elements from each \Array in +other_arrays+; returns +self+:
4765 * a.concat([2, 3], [4, 5]) # => [0, 1, 2, 3, 4, 5]
4769 rb_ary_concat_multi(int argc
, VALUE
*argv
, VALUE ary
)
4771 rb_ary_modify_check(ary
);
4774 rb_ary_concat(ary
, argv
[0]);
4776 else if (argc
> 1) {
4778 VALUE args
= rb_ary_tmp_new(argc
);
4779 for (i
= 0; i
< argc
; i
++) {
4780 rb_ary_concat(args
, argv
[i
]);
4782 ary_append(ary
, args
);
4790 rb_ary_concat(VALUE x
, VALUE y
)
4792 return ary_append(x
, to_ary(y
));
4797 * array * n -> new_array
4798 * array * string_separator -> new_string
4800 * When non-negative argument \Integer +n+ is given,
4801 * returns a new \Array built by concatenating the +n+ copies of +self+:
4803 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
4805 * When \String argument +string_separator+ is given,
4806 * equivalent to <tt>array.join(string_separator)</tt>:
4807 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
4811 rb_ary_times(VALUE ary
, VALUE times
)
4817 tmp
= rb_check_string_type(times
);
4819 return rb_ary_join(ary
, tmp
);
4822 len
= NUM2LONG(times
);
4824 ary2
= ary_new(rb_cArray
, 0);
4828 rb_raise(rb_eArgError
, "negative argument");
4830 if (ARY_MAX_SIZE
/len
< RARRAY_LEN(ary
)) {
4831 rb_raise(rb_eArgError
, "argument too big");
4833 len
*= RARRAY_LEN(ary
);
4835 ary2
= ary_new(rb_cArray
, len
);
4836 ARY_SET_LEN(ary2
, len
);
4838 ptr
= RARRAY_CONST_PTR_TRANSIENT(ary
);
4839 t
= RARRAY_LEN(ary
);
4841 ary_memcpy(ary2
, 0, t
, ptr
);
4842 while (t
<= len
/2) {
4843 ary_memcpy(ary2
, t
, t
, RARRAY_CONST_PTR_TRANSIENT(ary2
));
4847 ary_memcpy(ary2
, t
, len
-t
, RARRAY_CONST_PTR_TRANSIENT(ary2
));
4856 * array.assoc(obj) -> found_array or nil
4858 * Returns the first element in +self+ that is an \Array
4859 * whose first element <tt>==</tt> +obj+:
4860 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
4861 * a.assoc(4) # => [4, 5, 6]
4863 * Returns +nil+ if no such element is found.
4869 rb_ary_assoc(VALUE ary
, VALUE key
)
4874 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
4875 v
= rb_check_array_type(RARRAY_AREF(ary
, i
));
4876 if (!NIL_P(v
) && RARRAY_LEN(v
) > 0 &&
4877 rb_equal(RARRAY_AREF(v
, 0), key
))
4885 * array.rassoc(obj) -> found_array or nil
4887 * Returns the first element in +self+ that is an \Array
4888 * whose second element <tt>==</tt> +obj+:
4889 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
4890 * a.rassoc(4) # => [2, 4]
4892 * Returns +nil+ if no such element is found.
4898 rb_ary_rassoc(VALUE ary
, VALUE value
)
4903 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
4904 v
= RARRAY_AREF(ary
, i
);
4905 if (RB_TYPE_P(v
, T_ARRAY
) &&
4906 RARRAY_LEN(v
) > 1 &&
4907 rb_equal(RARRAY_AREF(v
, 1), value
))
4914 recursive_equal(VALUE ary1
, VALUE ary2
, int recur
)
4917 const VALUE
*p1
, *p2
;
4919 if (recur
) return Qtrue
; /* Subtle! */
4921 /* rb_equal() can evacuate ptrs */
4922 p1
= RARRAY_CONST_PTR(ary1
);
4923 p2
= RARRAY_CONST_PTR(ary2
);
4924 len1
= RARRAY_LEN(ary1
);
4926 for (i
= 0; i
< len1
; i
++) {
4928 if (rb_equal(*p1
, *p2
)) {
4929 len1
= RARRAY_LEN(ary1
);
4930 if (len1
!= RARRAY_LEN(ary2
))
4934 p1
= RARRAY_CONST_PTR(ary1
) + i
;
4935 p2
= RARRAY_CONST_PTR(ary2
) + i
;
4949 * array == other_array -> true or false
4951 * Returns +true+ if both <tt>array.size == other_array.size</tt>
4952 * and for each index +i+ in +array+, <tt>array[i] == other_array[i]</tt>:
4953 * a0 = [:foo, 'bar', 2]
4954 * a1 = [:foo, 'bar', 2.0]
4955 * a1 == a0 # => true
4956 * [] == [] # => true
4958 * Otherwise, returns +false+.
4960 * This method is different from method Array#eql?,
4961 * which compares elements using <tt>Object#eql?</tt>.
4965 rb_ary_equal(VALUE ary1
, VALUE ary2
)
4967 if (ary1
== ary2
) return Qtrue
;
4968 if (!RB_TYPE_P(ary2
, T_ARRAY
)) {
4969 if (!rb_respond_to(ary2
, idTo_ary
)) {
4972 return rb_equal(ary2
, ary1
);
4974 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
4975 if (RARRAY_CONST_PTR_TRANSIENT(ary1
) == RARRAY_CONST_PTR_TRANSIENT(ary2
)) return Qtrue
;
4976 return rb_exec_recursive_paired(recursive_equal
, ary1
, ary2
, ary2
);
4980 recursive_eql(VALUE ary1
, VALUE ary2
, int recur
)
4984 if (recur
) return Qtrue
; /* Subtle! */
4985 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
4986 if (!rb_eql(rb_ary_elt(ary1
, i
), rb_ary_elt(ary2
, i
)))
4994 * array.eql? other_array -> true or false
4996 * Returns +true+ if +self+ and +other_array+ are the same size,
4997 * and if, for each index +i+ in +self+, <tt>self[i].eql? other_array[i]</tt>:
4998 * a0 = [:foo, 'bar', 2]
4999 * a1 = [:foo, 'bar', 2]
5000 * a1.eql?(a0) # => true
5002 * Otherwise, returns +false+.
5004 * This method is different from method {Array#==}[#method-i-3D-3D],
5005 * which compares using method <tt>Object#==</tt>.
5009 rb_ary_eql(VALUE ary1
, VALUE ary2
)
5011 if (ary1
== ary2
) return Qtrue
;
5012 if (!RB_TYPE_P(ary2
, T_ARRAY
)) return Qfalse
;
5013 if (RARRAY_LEN(ary1
) != RARRAY_LEN(ary2
)) return Qfalse
;
5014 if (RARRAY_CONST_PTR_TRANSIENT(ary1
) == RARRAY_CONST_PTR_TRANSIENT(ary2
)) return Qtrue
;
5015 return rb_exec_recursive_paired(recursive_eql
, ary1
, ary2
, ary2
);
5020 * array.hash -> integer
5022 * Returns the integer hash value for +self+.
5024 * Two arrays with the same content will have the same hash code (and will compare using eql?):
5025 * [0, 1, 2].hash == [0, 1, 2].hash # => true
5026 * [0, 1, 2].hash == [0, 1, 3].hash # => false
5030 rb_ary_hash(VALUE ary
)
5036 h
= rb_hash_start(RARRAY_LEN(ary
));
5037 h
= rb_hash_uint(h
, (st_index_t
)rb_ary_hash
);
5038 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5039 n
= rb_hash(RARRAY_AREF(ary
, i
));
5040 h
= rb_hash_uint(h
, NUM2LONG(n
));
5048 * array.include?(obj) -> true or false
5050 * Returns +true+ if for some index +i+ in +self+, <tt>obj == self[i]</tt>;
5051 * otherwise +false+:
5052 * [0, 1, 2].include?(2) # => true
5053 * [0, 1, 2].include?(3) # => false
5057 rb_ary_includes(VALUE ary
, VALUE item
)
5062 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5063 e
= RARRAY_AREF(ary
, i
);
5064 if (rb_equal(e
, item
)) {
5072 rb_ary_includes_by_eql(VALUE ary
, VALUE item
)
5077 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5078 e
= RARRAY_AREF(ary
, i
);
5079 if (rb_eql(item
, e
)) {
5087 recursive_cmp(VALUE ary1
, VALUE ary2
, int recur
)
5091 if (recur
) return Qundef
; /* Subtle! */
5092 len
= RARRAY_LEN(ary1
);
5093 if (len
> RARRAY_LEN(ary2
)) {
5094 len
= RARRAY_LEN(ary2
);
5096 for (i
=0; i
<len
; i
++) {
5097 VALUE e1
= rb_ary_elt(ary1
, i
), e2
= rb_ary_elt(ary2
, i
);
5098 VALUE v
= rb_funcallv(e1
, id_cmp
, 1, &e2
);
5099 if (v
!= INT2FIX(0)) {
5108 * array <=> other_array -> -1, 0, or 1
5110 * Returns -1, 0, or 1 as +self+ is less than, equal to, or greater than +other_array+.
5111 * For each index +i+ in +self+, evaluates <tt>result = self[i] <=> other_array[i]</tt>.
5113 * Returns -1 if any result is -1:
5114 * [0, 1, 2] <=> [0, 1, 3] # => -1
5116 * Returns 1 if any result is 1:
5117 * [0, 1, 2] <=> [0, 1, 1] # => 1
5119 * When all results are zero:
5120 * - Returns -1 if +array+ is smaller than +other_array+:
5121 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5122 * - Returns 1 if +array+ is larger than +other_array+:
5123 * [0, 1, 2] <=> [0, 1] # => 1
5124 * - Returns 0 if +array+ and +other_array+ are the same size:
5125 * [0, 1, 2] <=> [0, 1, 2] # => 0
5129 rb_ary_cmp(VALUE ary1
, VALUE ary2
)
5134 ary2
= rb_check_array_type(ary2
);
5135 if (NIL_P(ary2
)) return Qnil
;
5136 if (ary1
== ary2
) return INT2FIX(0);
5137 v
= rb_exec_recursive_paired(recursive_cmp
, ary1
, ary2
, ary2
);
5138 if (v
!= Qundef
) return v
;
5139 len
= RARRAY_LEN(ary1
) - RARRAY_LEN(ary2
);
5140 if (len
== 0) return INT2FIX(0);
5141 if (len
> 0) return INT2FIX(1);
5146 ary_add_hash(VALUE hash
, VALUE ary
)
5150 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
5151 VALUE elt
= RARRAY_AREF(ary
, i
);
5152 rb_hash_add_new_element(hash
, elt
, elt
);
5158 ary_tmp_hash_new(VALUE ary
)
5160 long size
= RARRAY_LEN(ary
);
5161 VALUE hash
= rb_hash_new_with_size(size
);
5163 RBASIC_CLEAR_CLASS(hash
);
5168 ary_make_hash(VALUE ary
)
5170 VALUE hash
= ary_tmp_hash_new(ary
);
5171 return ary_add_hash(hash
, ary
);
5175 ary_add_hash_by(VALUE hash
, VALUE ary
)
5179 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
5180 VALUE v
= rb_ary_elt(ary
, i
), k
= rb_yield(v
);
5181 rb_hash_add_new_element(hash
, k
, v
);
5187 ary_make_hash_by(VALUE ary
)
5189 VALUE hash
= ary_tmp_hash_new(ary
);
5190 return ary_add_hash_by(hash
, ary
);
5194 ary_recycle_hash(VALUE hash
)
5196 assert(RBASIC_CLASS(hash
) == 0);
5197 if (RHASH_ST_TABLE_P(hash
)) {
5198 st_table
*tbl
= RHASH_ST_TABLE(hash
);
5200 RHASH_ST_CLEAR(hash
);
5206 * array - other_array -> new_array
5208 * Returns a new \Array containing only those elements from +array+
5209 * that are not found in \Array +other_array+;
5210 * items are compared using <tt>eql?</tt>;
5211 * the order from +array+ is preserved:
5212 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5213 * [0, 1, 2, 3] - [3, 0] # => [1, 2]
5214 * [0, 1, 2] - [4] # => [0, 1, 2]
5216 * Related: Array#difference.
5220 rb_ary_diff(VALUE ary1
, VALUE ary2
)
5226 ary2
= to_ary(ary2
);
5227 if (RARRAY_LEN(ary2
) == 0) { return ary_make_shared_copy(ary1
); }
5228 ary3
= rb_ary_new();
5230 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
|| RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5231 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5232 VALUE elt
= rb_ary_elt(ary1
, i
);
5233 if (rb_ary_includes_by_eql(ary2
, elt
)) continue;
5234 rb_ary_push(ary3
, elt
);
5239 hash
= ary_make_hash(ary2
);
5240 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5241 if (rb_hash_stlike_lookup(hash
, RARRAY_AREF(ary1
, i
), NULL
)) continue;
5242 rb_ary_push(ary3
, rb_ary_elt(ary1
, i
));
5244 ary_recycle_hash(hash
);
5250 * array.difference(*other_arrays) -> new_array
5252 * Returns a new \Array containing only those elements from +self+
5253 * that are not found in any of the Arrays +other_arrays+;
5254 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5255 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5256 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5257 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5259 * Returns a copy of +self+ if no arguments given.
5265 rb_ary_difference_multi(int argc
, VALUE
*argv
, VALUE ary
)
5270 bool *is_hash
= ALLOCV_N(bool, t0
, argc
);
5271 ary_diff
= rb_ary_new();
5272 length
= RARRAY_LEN(ary
);
5274 for (i
= 0; i
< argc
; i
++) {
5275 argv
[i
] = to_ary(argv
[i
]);
5276 is_hash
[i
] = (length
> SMALL_ARRAY_LEN
&& RARRAY_LEN(argv
[i
]) > SMALL_ARRAY_LEN
);
5277 if (is_hash
[i
]) argv
[i
] = ary_make_hash(argv
[i
]);
5280 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5282 VALUE elt
= rb_ary_elt(ary
, i
);
5283 for (j
= 0; j
< argc
; j
++) {
5285 if (rb_hash_stlike_lookup(argv
[j
], RARRAY_AREF(ary
, i
), NULL
))
5289 if (rb_ary_includes_by_eql(argv
[j
], elt
)) break;
5292 if (j
== argc
) rb_ary_push(ary_diff
, elt
);
5303 * array & other_array -> new_array
5305 * Returns a new \Array containing each element found in both +array+ and \Array +other_array+;
5306 * duplicates are omitted; items are compared using <tt>eql?</tt>:
5307 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5308 * [0, 1, 0, 1] & [0, 1] # => [0, 1]
5310 * Preserves order from +array+:
5311 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5313 * Related: Array#intersection.
5318 rb_ary_and(VALUE ary1
, VALUE ary2
)
5320 VALUE hash
, ary3
, v
;
5324 ary2
= to_ary(ary2
);
5325 ary3
= rb_ary_new();
5326 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return ary3
;
5328 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5329 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5330 v
= RARRAY_AREF(ary1
, i
);
5331 if (!rb_ary_includes_by_eql(ary2
, v
)) continue;
5332 if (rb_ary_includes_by_eql(ary3
, v
)) continue;
5333 rb_ary_push(ary3
, v
);
5338 hash
= ary_make_hash(ary2
);
5340 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5341 v
= RARRAY_AREF(ary1
, i
);
5343 if (rb_hash_stlike_delete(hash
, &vv
, 0)) {
5344 rb_ary_push(ary3
, v
);
5347 ary_recycle_hash(hash
);
5354 * array.intersection(*other_arrays) -> new_array
5356 * Returns a new \Array containing each element found both in +self+
5357 * and in all of the given Arrays +other_arrays+;
5358 * duplicates are omitted; items are compared using <tt>eql?</tt>:
5359 * [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5360 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5362 * Preserves order from +self+:
5363 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5365 * Returns a copy of +self+ if no arguments given.
5371 rb_ary_intersection_multi(int argc
, VALUE
*argv
, VALUE ary
)
5373 VALUE result
= rb_ary_dup(ary
);
5376 for (i
= 0; i
< argc
; i
++) {
5377 result
= rb_ary_and(result
, argv
[i
]);
5384 ary_hash_orset(st_data_t
*key
, st_data_t
*value
, st_data_t arg
, int existing
)
5386 if (existing
) return ST_STOP
;
5387 *key
= *value
= (VALUE
)arg
;
5392 rb_ary_union(VALUE ary_union
, VALUE ary
)
5395 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5396 VALUE elt
= rb_ary_elt(ary
, i
);
5397 if (rb_ary_includes_by_eql(ary_union
, elt
)) continue;
5398 rb_ary_push(ary_union
, elt
);
5403 rb_ary_union_hash(VALUE hash
, VALUE ary2
)
5406 for (i
= 0; i
< RARRAY_LEN(ary2
); i
++) {
5407 VALUE elt
= RARRAY_AREF(ary2
, i
);
5408 if (!rb_hash_stlike_update(hash
, (st_data_t
)elt
, ary_hash_orset
, (st_data_t
)elt
)) {
5409 RB_OBJ_WRITTEN(hash
, Qundef
, elt
);
5416 * array | other_array -> new_array
5418 * Returns the union of +array+ and \Array +other_array+;
5419 * duplicates are removed; order is preserved;
5420 * items are compared using <tt>eql?</tt>:
5421 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5422 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5423 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5425 * Related: Array#union.
5429 rb_ary_or(VALUE ary1
, VALUE ary2
)
5433 ary2
= to_ary(ary2
);
5434 if (RARRAY_LEN(ary1
) + RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5435 ary3
= rb_ary_new();
5436 rb_ary_union(ary3
, ary1
);
5437 rb_ary_union(ary3
, ary2
);
5441 hash
= ary_make_hash(ary1
);
5442 rb_ary_union_hash(hash
, ary2
);
5444 ary3
= rb_hash_values(hash
);
5445 ary_recycle_hash(hash
);
5451 * array.union(*other_arrays) -> new_array
5453 * Returns a new \Array that is the union of +self+ and all given Arrays +other_arrays+;
5454 * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
5455 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
5456 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
5457 * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
5459 * Returns a copy of +self+ if no arguments given.
5465 rb_ary_union_multi(int argc
, VALUE
*argv
, VALUE ary
)
5469 VALUE hash
, ary_union
;
5471 sum
= RARRAY_LEN(ary
);
5472 for (i
= 0; i
< argc
; i
++) {
5473 argv
[i
] = to_ary(argv
[i
]);
5474 sum
+= RARRAY_LEN(argv
[i
]);
5477 if (sum
<= SMALL_ARRAY_LEN
) {
5478 ary_union
= rb_ary_new();
5480 rb_ary_union(ary_union
, ary
);
5481 for (i
= 0; i
< argc
; i
++) rb_ary_union(ary_union
, argv
[i
]);
5486 hash
= ary_make_hash(ary
);
5487 for (i
= 0; i
< argc
; i
++) rb_ary_union_hash(hash
, argv
[i
]);
5489 ary_union
= rb_hash_values(hash
);
5490 ary_recycle_hash(hash
);
5496 * ary.intersect?(other_ary) -> true or false
5498 * Returns +true+ if the array and +other_ary+ have at least one element in
5499 * common, otherwise returns +false+.
5504 * a.intersect?(b) #=> true
5505 * a.intersect?(c) #=> false
5509 rb_ary_intersect_p(VALUE ary1
, VALUE ary2
)
5511 VALUE hash
, v
, result
, shorter
, longer
;
5515 ary2
= to_ary(ary2
);
5516 if (RARRAY_LEN(ary1
) == 0 || RARRAY_LEN(ary2
) == 0) return Qfalse
;
5518 if (RARRAY_LEN(ary1
) <= SMALL_ARRAY_LEN
&& RARRAY_LEN(ary2
) <= SMALL_ARRAY_LEN
) {
5519 for (i
=0; i
<RARRAY_LEN(ary1
); i
++) {
5520 v
= RARRAY_AREF(ary1
, i
);
5521 if (rb_ary_includes_by_eql(ary2
, v
)) return Qtrue
;
5528 if (RARRAY_LEN(ary1
) > RARRAY_LEN(ary2
)) {
5533 hash
= ary_make_hash(shorter
);
5536 for (i
=0; i
<RARRAY_LEN(longer
); i
++) {
5537 v
= RARRAY_AREF(longer
, i
);
5539 if (rb_hash_stlike_lookup(hash
, vv
, 0)) {
5544 ary_recycle_hash(hash
);
5550 ary_max_generic(VALUE ary
, long i
, VALUE vmax
)
5552 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5555 for (; i
< RARRAY_LEN(ary
); ++i
) {
5556 v
= RARRAY_AREF(ary
, i
);
5558 if (rb_cmpint(rb_funcallv(vmax
, id_cmp
, 1, &v
), vmax
, v
) < 0) {
5567 ary_max_opt_fixnum(VALUE ary
, long i
, VALUE vmax
)
5569 const long n
= RARRAY_LEN(ary
);
5570 RUBY_ASSERT(i
> 0 && i
< n
);
5571 RUBY_ASSERT(FIXNUM_P(vmax
));
5574 for (; i
< n
; ++i
) {
5575 v
= RARRAY_AREF(ary
, i
);
5578 if ((long)vmax
< (long)v
) {
5583 return ary_max_generic(ary
, i
, vmax
);
5591 ary_max_opt_float(VALUE ary
, long i
, VALUE vmax
)
5593 const long n
= RARRAY_LEN(ary
);
5594 RUBY_ASSERT(i
> 0 && i
< n
);
5595 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax
));
5598 for (; i
< n
; ++i
) {
5599 v
= RARRAY_AREF(ary
, i
);
5601 if (RB_FLOAT_TYPE_P(v
)) {
5602 if (rb_float_cmp(vmax
, v
) < 0) {
5607 return ary_max_generic(ary
, i
, vmax
);
5615 ary_max_opt_string(VALUE ary
, long i
, VALUE vmax
)
5617 const long n
= RARRAY_LEN(ary
);
5618 RUBY_ASSERT(i
> 0 && i
< n
);
5619 RUBY_ASSERT(STRING_P(vmax
));
5622 for (; i
< n
; ++i
) {
5623 v
= RARRAY_AREF(ary
, i
);
5626 if (rb_str_cmp(vmax
, v
) < 0) {
5631 return ary_max_generic(ary
, i
, vmax
);
5640 * array.max -> element
5641 * array.max {|a, b| ... } -> element
5642 * array.max(n) -> new_array
5643 * array.max(n) {|a, b| ... } -> new_array
5645 * Returns one of the following:
5646 * - The maximum-valued element from +self+.
5647 * - A new \Array of maximum-valued elements selected from +self+.
5649 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5652 * With no argument and no block, returns the element in +self+
5653 * having the maximum value per method <tt><=></tt>:
5654 * [0, 1, 2].max # => 2
5656 * With an argument \Integer +n+ and no block, returns a new \Array with at most +n+ elements,
5657 * in descending order per method <tt><=></tt>:
5658 * [0, 1, 2, 3].max(3) # => [3, 2, 1]
5659 * [0, 1, 2, 3].max(6) # => [3, 2, 1, 0]
5661 * When a block is given, the block must return an \Integer.
5663 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
5664 * returns the element having the maximum value per the block:
5665 * ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000"
5667 * With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
5668 * in descending order per the block:
5669 * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
5672 rb_ary_max(int argc
, VALUE
*argv
, VALUE ary
)
5674 struct cmp_opt_data cmp_opt
= { 0, 0 };
5675 VALUE result
= Qundef
, v
;
5679 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
5680 return rb_nmin_run(ary
, num
, 0, 1, 1);
5682 const long n
= RARRAY_LEN(ary
);
5683 if (rb_block_given_p()) {
5684 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5685 v
= RARRAY_AREF(ary
, i
);
5686 if (result
== Qundef
|| rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) > 0) {
5692 result
= RARRAY_AREF(ary
, 0);
5694 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(cmp_opt
, Integer
)) {
5695 return ary_max_opt_fixnum(ary
, 1, result
);
5697 else if (STRING_P(result
) && CMP_OPTIMIZABLE(cmp_opt
, String
)) {
5698 return ary_max_opt_string(ary
, 1, result
);
5700 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(cmp_opt
, Float
)) {
5701 return ary_max_opt_float(ary
, 1, result
);
5704 return ary_max_generic(ary
, 1, result
);
5708 if (result
== Qundef
) return Qnil
;
5713 ary_min_generic(VALUE ary
, long i
, VALUE vmin
)
5715 RUBY_ASSERT(i
> 0 && i
< RARRAY_LEN(ary
));
5718 for (; i
< RARRAY_LEN(ary
); ++i
) {
5719 v
= RARRAY_AREF(ary
, i
);
5721 if (rb_cmpint(rb_funcallv(vmin
, id_cmp
, 1, &v
), vmin
, v
) > 0) {
5730 ary_min_opt_fixnum(VALUE ary
, long i
, VALUE vmin
)
5732 const long n
= RARRAY_LEN(ary
);
5733 RUBY_ASSERT(i
> 0 && i
< n
);
5734 RUBY_ASSERT(FIXNUM_P(vmin
));
5737 for (; i
< n
; ++i
) {
5738 a
= RARRAY_AREF(ary
, i
);
5741 if ((long)vmin
> (long)a
) {
5746 return ary_min_generic(ary
, i
, vmin
);
5754 ary_min_opt_float(VALUE ary
, long i
, VALUE vmin
)
5756 const long n
= RARRAY_LEN(ary
);
5757 RUBY_ASSERT(i
> 0 && i
< n
);
5758 RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin
));
5761 for (; i
< n
; ++i
) {
5762 a
= RARRAY_AREF(ary
, i
);
5764 if (RB_FLOAT_TYPE_P(a
)) {
5765 if (rb_float_cmp(vmin
, a
) > 0) {
5770 return ary_min_generic(ary
, i
, vmin
);
5778 ary_min_opt_string(VALUE ary
, long i
, VALUE vmin
)
5780 const long n
= RARRAY_LEN(ary
);
5781 RUBY_ASSERT(i
> 0 && i
< n
);
5782 RUBY_ASSERT(STRING_P(vmin
));
5785 for (; i
< n
; ++i
) {
5786 a
= RARRAY_AREF(ary
, i
);
5789 if (rb_str_cmp(vmin
, a
) > 0) {
5794 return ary_min_generic(ary
, i
, vmin
);
5803 * array.min -> element
5804 * array.min { |a, b| ... } -> element
5805 * array.min(n) -> new_array
5806 * array.min(n) { |a, b| ... } -> new_array
5808 * Returns one of the following:
5809 * - The minimum-valued element from +self+.
5810 * - A new \Array of minimum-valued elements selected from +self+.
5812 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5815 * With no argument and no block, returns the element in +self+
5816 * having the minimum value per method <tt><=></tt>:
5817 * [0, 1, 2].min # => 0
5819 * With \Integer argument +n+ and no block, returns a new \Array with at most +n+ elements,
5820 * in ascending order per method <tt><=></tt>:
5821 * [0, 1, 2, 3].min(3) # => [0, 1, 2]
5822 * [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
5824 * When a block is given, the block must return an Integer.
5826 * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
5827 * returns the element having the minimum value per the block:
5828 * ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0"
5830 * With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
5831 * in ascending order per the block:
5832 * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
5835 rb_ary_min(int argc
, VALUE
*argv
, VALUE ary
)
5837 struct cmp_opt_data cmp_opt
= { 0, 0 };
5838 VALUE result
= Qundef
, v
;
5842 if (rb_check_arity(argc
, 0, 1) && !NIL_P(num
= argv
[0]))
5843 return rb_nmin_run(ary
, num
, 0, 0, 1);
5845 const long n
= RARRAY_LEN(ary
);
5846 if (rb_block_given_p()) {
5847 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
5848 v
= RARRAY_AREF(ary
, i
);
5849 if (result
== Qundef
|| rb_cmpint(rb_yield_values(2, v
, result
), v
, result
) < 0) {
5855 result
= RARRAY_AREF(ary
, 0);
5857 if (FIXNUM_P(result
) && CMP_OPTIMIZABLE(cmp_opt
, Integer
)) {
5858 return ary_min_opt_fixnum(ary
, 1, result
);
5860 else if (STRING_P(result
) && CMP_OPTIMIZABLE(cmp_opt
, String
)) {
5861 return ary_min_opt_string(ary
, 1, result
);
5863 else if (RB_FLOAT_TYPE_P(result
) && CMP_OPTIMIZABLE(cmp_opt
, Float
)) {
5864 return ary_min_opt_float(ary
, 1, result
);
5867 return ary_min_generic(ary
, 1, result
);
5871 if (result
== Qundef
) return Qnil
;
5877 * array.minmax -> [min_val, max_val]
5878 * array.minmax {|a, b| ... } -> [min_val, max_val]
5880 * Returns a new 2-element \Array containing the minimum and maximum values
5881 * from +self+, either per method <tt><=></tt> or per a given block:.
5883 * When no block is given, each element in +self+ must respond to method <tt><=></tt>
5885 * returns a new 2-element \Array containing the minimum and maximum values
5886 * from +self+, per method <tt><=></tt>:
5887 * [0, 1, 2].minmax # => [0, 2]
5889 * When a block is given, the block must return an \Integer;
5890 * the block is called <tt>self.size-1</tt> times to compare elements;
5891 * returns a new 2-element \Array containing the minimum and maximum values
5892 * from +self+, per the block:
5893 * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
5896 rb_ary_minmax(VALUE ary
)
5898 if (rb_block_given_p()) {
5899 return rb_call_super(0, NULL
);
5901 return rb_assoc_new(rb_ary_min(0, 0, ary
), rb_ary_max(0, 0, ary
));
5905 push_value(st_data_t key
, st_data_t val
, st_data_t ary
)
5907 rb_ary_push((VALUE
)ary
, (VALUE
)val
);
5913 * array.uniq! -> self or nil
5914 * array.uniq! {|element| ... } -> self or nil
5916 * Removes duplicate elements from +self+, the first occurrence always being retained;
5917 * returns +self+ if any elements removed, +nil+ otherwise.
5919 * With no block given, identifies and removes elements using method <tt>eql?</tt>
5922 * Returns +self+ if any elements removed:
5923 * a = [0, 0, 1, 1, 2, 2]
5924 * a.uniq! # => [0, 1, 2]
5926 * Returns +nil+ if no elements removed.
5928 * With a block given, calls the block for each element;
5929 * identifies (using method <tt>eql?</tt>) and removes
5930 * elements for which the block returns duplicate values.
5932 * Returns +self+ if any elements removed:
5933 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
5934 * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
5936 * Returns +nil+ if no elements removed.
5939 rb_ary_uniq_bang(VALUE ary
)
5944 rb_ary_modify_check(ary
);
5945 if (RARRAY_LEN(ary
) <= 1)
5947 if (rb_block_given_p())
5948 hash
= ary_make_hash_by(ary
);
5950 hash
= ary_make_hash(ary
);
5952 hash_size
= RHASH_SIZE(hash
);
5953 if (RARRAY_LEN(ary
) == hash_size
) {
5956 rb_ary_modify_check(ary
);
5957 ARY_SET_LEN(ary
, 0);
5958 if (ARY_SHARED_P(ary
) && !ARY_EMBED_P(ary
)) {
5959 rb_ary_unshare(ary
);
5962 ary_resize_capa(ary
, hash_size
);
5963 rb_hash_foreach(hash
, push_value
, ary
);
5964 ary_recycle_hash(hash
);
5971 * array.uniq -> new_array
5972 * array.uniq {|element| ... } -> new_array
5974 * Returns a new \Array containing those elements from +self+ that are not duplicates,
5975 * the first occurrence always being retained.
5977 * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
5979 * a = [0, 0, 1, 1, 2, 2]
5980 * a.uniq # => [0, 1, 2]
5982 * With a block given, calls the block for each element;
5983 * identifies (using method <tt>eql?</tt>) and omits duplicate values,
5984 * that is, those elements for which the block returns the same value:
5985 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
5986 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
5990 rb_ary_uniq(VALUE ary
)
5994 if (RARRAY_LEN(ary
) <= 1) {
5996 uniq
= rb_ary_dup(ary
);
5998 else if (rb_block_given_p()) {
5999 hash
= ary_make_hash_by(ary
);
6000 uniq
= rb_hash_values(hash
);
6003 hash
= ary_make_hash(ary
);
6004 uniq
= rb_hash_values(hash
);
6007 ary_recycle_hash(hash
);
6015 * array.compact! -> self or nil
6017 * Removes all +nil+ elements from +self+.
6019 * Returns +self+ if any elements removed, otherwise +nil+.
6023 rb_ary_compact_bang(VALUE ary
)
6029 p
= t
= (VALUE
*)RARRAY_CONST_PTR_TRANSIENT(ary
); /* WB: no new reference */
6030 end
= p
+ RARRAY_LEN(ary
);
6036 n
= p
- RARRAY_CONST_PTR_TRANSIENT(ary
);
6037 if (RARRAY_LEN(ary
) == n
) {
6040 ary_resize_smaller(ary
, n
);
6047 * array.compact -> new_array
6049 * Returns a new \Array containing all non-+nil+ elements from +self+:
6050 * a = [nil, 0, nil, 1, nil, 2, nil]
6051 * a.compact # => [0, 1, 2]
6055 rb_ary_compact(VALUE ary
)
6057 ary
= rb_ary_dup(ary
);
6058 rb_ary_compact_bang(ary
);
6064 * array.count -> an_integer
6065 * array.count(obj) -> an_integer
6066 * array.count {|element| ... } -> an_integer
6068 * Returns a count of specified elements.
6070 * With no argument and no block, returns the count of all elements:
6071 * [0, 1, 2].count # => 3
6074 * With argument +obj+, returns the count of elements <tt>==</tt> to +obj+:
6075 * [0, 1, 2, 0.0].count(0) # => 2
6076 * [0, 1, 2].count(3) # => 0
6078 * With no argument and a block given, calls the block with each element;
6079 * returns the count of elements for which the block returns a truthy value:
6080 * [0, 1, 2, 3].count {|element| element > 1} # => 2
6082 * With argument +obj+ and a block given, issues a warning, ignores the block,
6083 * and returns the count of elements <tt>==</tt> to +obj+:
6087 rb_ary_count(int argc
, VALUE
*argv
, VALUE ary
)
6091 if (rb_check_arity(argc
, 0, 1) == 0) {
6094 if (!rb_block_given_p())
6095 return LONG2NUM(RARRAY_LEN(ary
));
6097 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6098 v
= RARRAY_AREF(ary
, i
);
6099 if (RTEST(rb_yield(v
))) n
++;
6103 VALUE obj
= argv
[0];
6105 if (rb_block_given_p()) {
6106 rb_warn("given block not used");
6108 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6109 if (rb_equal(RARRAY_AREF(ary
, i
), obj
)) n
++;
6117 flatten(VALUE ary
, int level
)
6120 VALUE stack
, result
, tmp
= 0, elt
, vmemo
;
6124 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6125 elt
= RARRAY_AREF(ary
, i
);
6126 tmp
= rb_check_array_type(elt
);
6131 if (i
== RARRAY_LEN(ary
)) {
6135 result
= ary_new(0, RARRAY_LEN(ary
));
6136 ary_memcpy(result
, 0, i
, RARRAY_CONST_PTR_TRANSIENT(ary
));
6137 ARY_SET_LEN(result
, i
);
6139 stack
= ary_new(0, ARY_DEFAULT_SIZE
);
6140 rb_ary_push(stack
, ary
);
6141 rb_ary_push(stack
, LONG2NUM(i
+ 1));
6144 vmemo
= rb_hash_new();
6145 RBASIC_CLEAR_CLASS(vmemo
);
6146 memo
= st_init_numtable();
6147 rb_hash_st_table_set(vmemo
, memo
);
6148 st_insert(memo
, (st_data_t
)ary
, (st_data_t
)Qtrue
);
6149 st_insert(memo
, (st_data_t
)tmp
, (st_data_t
)Qtrue
);
6156 while (i
< RARRAY_LEN(ary
)) {
6157 elt
= RARRAY_AREF(ary
, i
++);
6158 if (level
>= 0 && RARRAY_LEN(stack
) / 2 >= level
) {
6159 rb_ary_push(result
, elt
);
6162 tmp
= rb_check_array_type(elt
);
6163 if (RBASIC(result
)->klass
) {
6168 rb_raise(rb_eRuntimeError
, "flatten reentered");
6171 rb_ary_push(result
, elt
);
6175 id
= (st_data_t
)tmp
;
6176 if (st_is_member(memo
, id
)) {
6178 rb_raise(rb_eArgError
, "tried to flatten recursive array");
6180 st_insert(memo
, id
, (st_data_t
)Qtrue
);
6182 rb_ary_push(stack
, ary
);
6183 rb_ary_push(stack
, LONG2NUM(i
));
6188 if (RARRAY_LEN(stack
) == 0) {
6192 id
= (st_data_t
)ary
;
6193 st_delete(memo
, &id
, 0);
6195 tmp
= rb_ary_pop(stack
);
6197 ary
= rb_ary_pop(stack
);
6204 RBASIC_SET_CLASS(result
, rb_cArray
);
6210 * array.flatten! -> self or nil
6211 * array.flatten!(level) -> self or nil
6213 * Replaces each nested \Array in +self+ with the elements from that \Array;
6214 * returns +self+ if any changes, +nil+ otherwise.
6216 * With non-negative \Integer argument +level+, flattens recursively through +level+ levels:
6217 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6218 * a.flatten!(1) # => [0, 1, [2, 3], 4, 5]
6219 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6220 * a.flatten!(2) # => [0, 1, 2, 3, 4, 5]
6221 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6222 * a.flatten!(3) # => [0, 1, 2, 3, 4, 5]
6223 * [0, 1, 2].flatten!(1) # => nil
6225 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6226 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6227 * a.flatten! # => [0, 1, 2, 3, 4, 5]
6228 * [0, 1, 2].flatten! # => nil
6229 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6230 * a.flatten!(-1) # => [0, 1, 2, 3, 4, 5]
6231 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6232 * a.flatten!(-2) # => [0, 1, 2, 3, 4, 5]
6233 * [0, 1, 2].flatten!(-1) # => nil
6237 rb_ary_flatten_bang(int argc
, VALUE
*argv
, VALUE ary
)
6239 int mod
= 0, level
= -1;
6242 lv
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : Qnil
);
6243 rb_ary_modify_check(ary
);
6244 if (!NIL_P(lv
)) level
= NUM2INT(lv
);
6245 if (level
== 0) return Qnil
;
6247 result
= flatten(ary
, level
);
6248 if (result
== ary
) {
6251 if (!(mod
= ARY_EMBED_P(result
))) rb_obj_freeze(result
);
6252 rb_ary_replace(ary
, result
);
6253 if (mod
) ARY_SET_EMBED_LEN(result
, 0);
6260 * array.flatten -> new_array
6261 * array.flatten(level) -> new_array
6263 * Returns a new \Array that is a recursive flattening of +self+:
6264 * - Each non-Array element is unchanged.
6265 * - Each \Array is replaced by its individual elements.
6267 * With non-negative \Integer argument +level+, flattens recursively through +level+ levels:
6268 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6269 * a.flatten(0) # => [0, [1, [2, 3], 4], 5]
6270 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6271 * a.flatten(1) # => [0, 1, [2, 3], 4, 5]
6272 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6273 * a.flatten(2) # => [0, 1, 2, 3, 4, 5]
6274 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6275 * a.flatten(3) # => [0, 1, 2, 3, 4, 5]
6277 * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
6278 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6279 * a.flatten # => [0, 1, 2, 3, 4, 5]
6280 * [0, 1, 2].flatten # => [0, 1, 2]
6281 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6282 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5]
6283 * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
6284 * a.flatten(-2) # => [0, 1, 2, 3, 4, 5]
6285 * [0, 1, 2].flatten(-1) # => [0, 1, 2]
6289 rb_ary_flatten(int argc
, VALUE
*argv
, VALUE ary
)
6294 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0])) {
6295 level
= NUM2INT(argv
[0]);
6296 if (level
== 0) return ary_make_shared_copy(ary
);
6299 result
= flatten(ary
, level
);
6300 if (result
== ary
) {
6301 result
= ary_make_shared_copy(ary
);
6307 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6310 rb_ary_shuffle_bang(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6315 i
= len
= RARRAY_LEN(ary
);
6316 RARRAY_PTR_USE(ary
, ptr
, {
6318 long j
= RAND_UPTO(i
);
6320 if (len
!= RARRAY_LEN(ary
) || ptr
!= RARRAY_CONST_PTR_TRANSIENT(ary
)) {
6321 rb_raise(rb_eRuntimeError
, "modified during shuffle");
6327 }); /* WB: no new reference */
6332 rb_ary_shuffle(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
)
6334 ary
= rb_ary_dup(ary
);
6335 rb_ary_shuffle_bang(ec
, ary
, randgen
);
6340 ary_sample(rb_execution_context_t
*ec
, VALUE ary
, VALUE randgen
, VALUE nv
, VALUE to_array
)
6343 long n
, len
, i
, j
, k
, idx
[10];
6344 long rnds
[numberof(idx
)];
6345 long memo_threshold
;
6347 len
= RARRAY_LEN(ary
);
6354 return rb_ary_elt(ary
, i
);
6357 if (n
< 0) rb_raise(rb_eArgError
, "negative sample number");
6358 if (n
> len
) n
= len
;
6359 if (n
<= numberof(idx
)) {
6360 for (i
= 0; i
< n
; ++i
) {
6361 rnds
[i
] = RAND_UPTO(len
- i
);
6365 len
= RARRAY_LEN(ary
);
6366 if (len
< k
&& n
<= numberof(idx
)) {
6367 for (i
= 0; i
< n
; ++i
) {
6368 if (rnds
[i
] >= len
) return rb_ary_new_capa(0);
6371 if (n
> len
) n
= len
;
6374 return rb_ary_new_capa(0);
6377 return rb_ary_new_from_args(1, RARRAY_AREF(ary
, i
));
6382 return rb_ary_new_from_args(2, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
));
6389 if (j
>= i
) l
= i
, g
= ++j
;
6390 if (k
>= l
&& (++k
>= g
)) ++k
;
6392 return rb_ary_new_from_args(3, RARRAY_AREF(ary
, i
), RARRAY_AREF(ary
, j
), RARRAY_AREF(ary
, k
));
6395 len
< 2560 ? len
/ 128 :
6396 len
< 5120 ? len
/ 64 :
6397 len
< 10240 ? len
/ 32 :
6399 if (n
<= numberof(idx
)) {
6400 long sorted
[numberof(idx
)];
6401 sorted
[0] = idx
[0] = rnds
[0];
6402 for (i
=1; i
<n
; i
++) {
6404 for (j
= 0; j
< i
; ++j
) {
6405 if (k
< sorted
[j
]) break;
6408 memmove(&sorted
[j
+1], &sorted
[j
], sizeof(sorted
[0])*(i
-j
));
6409 sorted
[j
] = idx
[i
] = k
;
6411 result
= rb_ary_new_capa(n
);
6412 RARRAY_PTR_USE_TRANSIENT(result
, ptr_result
, {
6413 for (i
=0; i
<n
; i
++) {
6414 ptr_result
[i
] = RARRAY_AREF(ary
, idx
[i
]);
6418 else if (n
<= memo_threshold
/ 2) {
6420 #undef RUBY_UNTYPED_DATA_WARNING
6421 #define RUBY_UNTYPED_DATA_WARNING 0
6422 VALUE vmemo
= Data_Wrap_Struct(0, 0, st_free_table
, 0);
6423 st_table
*memo
= st_init_numtable_with_size(n
);
6424 DATA_PTR(vmemo
) = memo
;
6425 result
= rb_ary_new_capa(n
);
6426 RARRAY_PTR_USE(result
, ptr_result
, {
6427 for (i
=0; i
<n
; i
++) {
6428 long r
= RAND_UPTO(len
-i
) + i
;
6430 if (r
> max_idx
) max_idx
= r
;
6432 len
= RARRAY_LEN(ary
);
6433 if (len
<= max_idx
) n
= 0;
6434 else if (n
> len
) n
= len
;
6435 RARRAY_PTR_USE_TRANSIENT(ary
, ptr_ary
, {
6436 for (i
=0; i
<n
; i
++) {
6437 long j2
= j
= ptr_result
[i
];
6440 if (st_lookup(memo
, (st_data_t
)i
, &value
)) i2
= (long)value
;
6441 if (st_lookup(memo
, (st_data_t
)j
, &value
)) j2
= (long)value
;
6442 st_insert(memo
, (st_data_t
)j
, (st_data_t
)i2
);
6443 ptr_result
[i
] = ptr_ary
[j2
];
6447 DATA_PTR(vmemo
) = 0;
6448 st_free_table(memo
);
6451 result
= rb_ary_dup(ary
);
6452 RBASIC_CLEAR_CLASS(result
);
6454 RARRAY_PTR_USE(result
, ptr_result
, {
6455 for (i
=0; i
<n
; i
++) {
6456 j
= RAND_UPTO(len
-i
) + i
;
6458 ptr_result
[j
] = ptr_result
[i
];
6462 RBASIC_SET_CLASS_RAW(result
, rb_cArray
);
6464 ARY_SET_LEN(result
, n
);
6470 ary_sample0(rb_execution_context_t
*ec
, VALUE ary
)
6472 return ary_sample(ec
, ary
, rb_cRandom
, Qfalse
, Qfalse
);
6476 rb_ary_cycle_size(VALUE self
, VALUE args
, VALUE eobj
)
6480 if (args
&& (RARRAY_LEN(args
) > 0)) {
6481 n
= RARRAY_AREF(args
, 0);
6483 if (RARRAY_LEN(self
) == 0) return INT2FIX(0);
6484 if (NIL_P(n
)) return DBL2NUM(HUGE_VAL
);
6486 if (mul
<= 0) return INT2FIX(0);
6488 return rb_fix_mul_fix(rb_ary_length(self
), n
);
6493 * array.cycle {|element| ... } -> nil
6494 * array.cycle(count) {|element| ... } -> nil
6495 * array.cycle -> new_enumerator
6496 * array.cycle(count) -> new_enumerator
6498 * When called with positive \Integer argument +count+ and a block,
6499 * calls the block with each element, then does so again,
6500 * until it has done so +count+ times; returns +nil+:
6502 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
6503 * output # => [0, 1, 0, 1]
6505 * If +count+ is zero or negative, does not call the block:
6506 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
6507 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
6509 * When a block is given, and argument is omitted or +nil+, cycles forever:
6510 * # Prints 0 and 1 forever.
6511 * [0, 1].cycle {|element| puts element }
6512 * [0, 1].cycle(nil) {|element| puts element }
6514 * When no block is given, returns a new \Enumerator:
6516 * [0, 1].cycle(2) # => #<Enumerator: [0, 1]:cycle(2)>
6517 * [0, 1].cycle # => # => #<Enumerator: [0, 1]:cycle>
6518 * [0, 1].cycle.first(5) # => [0, 1, 0, 1, 0]
6521 rb_ary_cycle(int argc
, VALUE
*argv
, VALUE ary
)
6525 rb_check_arity(argc
, 0, 1);
6527 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_cycle_size
);
6528 if (argc
== 0 || NIL_P(argv
[0])) {
6532 n
= NUM2LONG(argv
[0]);
6533 if (n
<= 0) return Qnil
;
6536 while (RARRAY_LEN(ary
) > 0 && (n
< 0 || 0 < n
--)) {
6537 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
6538 rb_yield(RARRAY_AREF(ary
, i
));
6544 #define tmpary(n) rb_ary_tmp_new(n)
6545 #define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
6548 * Build a ruby array of the corresponding values and yield it to the
6550 * Return the class of +values+ for reentry check.
6553 yield_indexed_values(const VALUE values
, const long r
, const long *const p
)
6555 const VALUE result
= rb_ary_new2(r
);
6558 for (i
= 0; i
< r
; i
++) ARY_SET(result
, i
, RARRAY_AREF(values
, p
[i
]));
6559 ARY_SET_LEN(result
, r
);
6561 return !RBASIC(values
)->klass
;
6565 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
6567 * When we have a complete permutation of array indices, copy the values
6568 * at those indices into a new array and yield that array.
6570 * n: the size of the set
6571 * r: the number of elements in each permutation
6572 * p: the array (of size r) that we're filling in
6573 * used: an array of booleans: whether a given index is already used
6574 * values: the Ruby array that holds the actual values to permute
6577 permute0(const long n
, const long r
, long *const p
, char *const used
, const VALUE values
)
6579 long i
= 0, index
= 0;
6582 const char *const unused
= memchr(&used
[i
], 0, n
-i
);
6585 i
= p
[--index
]; /* pop index */
6586 used
[i
++] = 0; /* index unused */
6591 used
[i
] = 1; /* mark index used */
6593 if (index
< r
-1) { /* if not done yet */
6597 for (i
= 0; i
< n
; ++i
) {
6598 if (used
[i
]) continue;
6600 if (!yield_indexed_values(values
, r
, p
)) {
6601 rb_raise(rb_eRuntimeError
, "permute reentered");
6604 i
= p
[--index
]; /* pop index */
6605 used
[i
] = 0; /* index unused */
6612 * Returns the product of from, from-1, ..., from - how_many + 1.
6613 * https://en.wikipedia.org/wiki/Pochhammer_symbol
6616 descending_factorial(long from
, long how_many
)
6620 cnt
= LONG2FIX(from
);
6621 while (--how_many
> 0) {
6623 cnt
= rb_int_mul(cnt
, LONG2FIX(v
));
6627 cnt
= LONG2FIX(how_many
== 0);
6633 binomial_coefficient(long comb
, long size
)
6637 if (comb
> size
-comb
) {
6643 else if (comb
== 0) {
6647 for (i
= 1; i
< comb
; ++i
) {
6648 r
= rb_int_mul(r
, LONG2FIX(size
- i
));
6649 r
= rb_int_idiv(r
, LONG2FIX(i
+ 1));
6655 rb_ary_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
6657 long n
= RARRAY_LEN(ary
);
6658 long k
= (args
&& (RARRAY_LEN(args
) > 0)) ? NUM2LONG(RARRAY_AREF(args
, 0)) : n
;
6660 return descending_factorial(n
, k
);
6665 * array.permutation {|element| ... } -> self
6666 * array.permutation(n) {|element| ... } -> self
6667 * array.permutation -> new_enumerator
6668 * array.permutation(n) -> new_enumerator
6670 * When invoked with a block, yield all permutations of elements of +self+; returns +self+.
6671 * The order of permutations is indeterminate.
6673 * When a block and an in-range positive \Integer argument +n+ (<tt>0 < n <= self.size</tt>)
6674 * are given, calls the block with all +n+-tuple permutations of +self+.
6678 * a.permutation(2) {|permutation| p permutation }
6688 * a.permutation(3) {|permutation| p permutation }
6697 * When +n+ is zero, calls the block once with a new empty \Array:
6699 * a.permutation(0) {|permutation| p permutation }
6703 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
6704 * does not call the block:
6706 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
6707 * a.permutation(4) {|permutation| fail 'Cannot happen' }
6709 * When a block given but no argument,
6710 * behaves the same as <tt>a.permutation(a.size)</tt>:
6712 * a.permutation {|permutation| p permutation }
6721 * Returns a new \Enumerator if no block given:
6723 * a.permutation # => #<Enumerator: [0, 1, 2]:permutation>
6724 * a.permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
6728 rb_ary_permutation(int argc
, VALUE
*argv
, VALUE ary
)
6732 n
= RARRAY_LEN(ary
); /* Array length */
6733 RETURN_SIZED_ENUMERATOR(ary
, argc
, argv
, rb_ary_permutation_size
); /* Return enumerator if no block */
6735 if (rb_check_arity(argc
, 0, 1) && !NIL_P(argv
[0]))
6736 r
= NUM2LONG(argv
[0]); /* Permutation size from argument */
6738 if (r
< 0 || n
< r
) {
6739 /* no permutations: yield nothing */
6741 else if (r
== 0) { /* exactly one permutation: the zero-length array */
6742 rb_yield(rb_ary_new2(0));
6744 else if (r
== 1) { /* this is a special, easy case */
6745 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6746 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
6749 else { /* this is the general case */
6751 long *p
= ALLOCV_N(long, t0
, r
+roomof(n
, sizeof(long)));
6752 char *used
= (char*)(p
+ r
);
6753 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
6754 RBASIC_CLEAR_CLASS(ary0
);
6756 MEMZERO(used
, char, n
); /* initialize array */
6758 permute0(n
, r
, p
, used
, ary0
); /* compute and yield permutations */
6760 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
6766 combinate0(const long len
, const long n
, long *const stack
, const VALUE values
)
6770 MEMZERO(stack
+1, long, n
);
6773 for (lev
++; lev
< n
; lev
++) {
6774 stack
[lev
+1] = stack
[lev
]+1;
6776 if (!yield_indexed_values(values
, n
, stack
+1)) {
6777 rb_raise(rb_eRuntimeError
, "combination reentered");
6780 if (lev
== 0) return;
6782 } while (stack
[lev
+1]+n
== len
+lev
+1);
6787 rb_ary_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
6789 long n
= RARRAY_LEN(ary
);
6790 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
6792 return binomial_coefficient(k
, n
);
6797 * array.combination(n) {|element| ... } -> self
6798 * array.combination(n) -> new_enumerator
6800 * Calls the block, if given, with combinations of elements of +self+;
6801 * returns +self+. The order of combinations is indeterminate.
6803 * When a block and an in-range positive \Integer argument +n+ (<tt>0 < n <= self.size</tt>)
6804 * are given, calls the block with all +n+-tuple combinations of +self+.
6808 * a.combination(2) {|combination| p combination }
6816 * a.combination(3) {|combination| p combination }
6820 * When +n+ is zero, calls the block once with a new empty \Array:
6822 * a1 = a.combination(0) {|combination| p combination }
6826 * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
6827 * does not call the block:
6829 * a.combination(-1) {|combination| fail 'Cannot happen' }
6830 * a.combination(4) {|combination| fail 'Cannot happen' }
6832 * Returns a new \Enumerator if no block given:
6834 * a.combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
6838 rb_ary_combination(VALUE ary
, VALUE num
)
6843 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_combination_size
);
6844 len
= RARRAY_LEN(ary
);
6845 if (n
< 0 || len
< n
) {
6849 rb_yield(rb_ary_new2(0));
6852 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6853 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
6857 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
6859 long *stack
= ALLOCV_N(long, t0
, n
+1);
6861 RBASIC_CLEAR_CLASS(ary0
);
6862 combinate0(len
, n
, stack
, ary0
);
6864 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
6870 * Compute repeated permutations of +r+ elements of the set
6871 * <code>[0..n-1]</code>.
6873 * When we have a complete repeated permutation of array indices, copy the
6874 * values at those indices into a new array and yield that array.
6876 * n: the size of the set
6877 * r: the number of elements in each permutation
6878 * p: the array (of size r) that we're filling in
6879 * values: the Ruby array that holds the actual values to permute
6882 rpermute0(const long n
, const long r
, long *const p
, const VALUE values
)
6884 long i
= 0, index
= 0;
6888 if (++index
< r
-1) {
6892 for (i
= 0; i
< n
; ++i
) {
6894 if (!yield_indexed_values(values
, r
, p
)) {
6895 rb_raise(rb_eRuntimeError
, "repeated permute reentered");
6899 if (index
<= 0) return;
6900 } while ((i
= ++p
[--index
]) >= n
);
6905 rb_ary_repeated_permutation_size(VALUE ary
, VALUE args
, VALUE eobj
)
6907 long n
= RARRAY_LEN(ary
);
6908 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
6914 return LONG2FIX(!k
);
6916 return rb_int_positive_pow(n
, (unsigned long)k
);
6921 * array.repeated_permutation(n) {|permutation| ... } -> self
6922 * array.repeated_permutation(n) -> new_enumerator
6924 * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
6925 * each permutation is an \Array;
6926 * returns +self+. The order of the permutations is indeterminate.
6928 * When a block and a positive \Integer argument +n+ are given, calls the block with each
6929 * +n+-tuple repeated permutation of the elements of +self+.
6930 * The number of permutations is <tt>self.size**n</tt>.
6934 * a.repeated_permutation(1) {|permutation| p permutation }
6941 * a.repeated_permutation(2) {|permutation| p permutation }
6953 * If +n+ is zero, calls the block once with an empty \Array.
6955 * If +n+ is negative, does not call the block:
6956 * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
6958 * Returns a new \Enumerator if no block given:
6960 * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
6962 * Using Enumerators, it's convenient to show the permutations and counts
6963 * for some values of +n+:
6964 * e = a.repeated_permutation(0)
6967 * e = a.repeated_permutation(1)
6969 * e.to_a # => [[0], [1], [2]]
6970 * e = a.repeated_permutation(2)
6972 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
6975 rb_ary_repeated_permutation(VALUE ary
, VALUE num
)
6979 n
= RARRAY_LEN(ary
); /* Array length */
6980 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_permutation_size
); /* Return Enumerator if no block */
6981 r
= NUM2LONG(num
); /* Permutation size from argument */
6984 /* no permutations: yield nothing */
6986 else if (r
== 0) { /* exactly one permutation: the zero-length array */
6987 rb_yield(rb_ary_new2(0));
6989 else if (r
== 1) { /* this is a special, easy case */
6990 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
6991 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
6994 else { /* this is the general case */
6996 long *p
= ALLOCV_N(long, t0
, r
);
6997 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
6998 RBASIC_CLEAR_CLASS(ary0
);
7000 rpermute0(n
, r
, p
, ary0
); /* compute and yield repeated permutations */
7002 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7008 rcombinate0(const long n
, const long r
, long *const p
, const long rest
, const VALUE values
)
7010 long i
= 0, index
= 0;
7014 if (++index
< r
-1) {
7018 for (; i
< n
; ++i
) {
7020 if (!yield_indexed_values(values
, r
, p
)) {
7021 rb_raise(rb_eRuntimeError
, "repeated combination reentered");
7025 if (index
<= 0) return;
7026 } while ((i
= ++p
[--index
]) >= n
);
7031 rb_ary_repeated_combination_size(VALUE ary
, VALUE args
, VALUE eobj
)
7033 long n
= RARRAY_LEN(ary
);
7034 long k
= NUM2LONG(RARRAY_AREF(args
, 0));
7038 return binomial_coefficient(k
, n
+ k
- 1);
7043 * array.repeated_combination(n) {|combination| ... } -> self
7044 * array.repeated_combination(n) -> new_enumerator
7046 * Calls the block with each repeated combination of length +n+ of the elements of +self+;
7047 * each combination is an \Array;
7048 * returns +self+. The order of the combinations is indeterminate.
7050 * When a block and a positive \Integer argument +n+ are given, calls the block with each
7051 * +n+-tuple repeated combination of the elements of +self+.
7052 * The number of combinations is <tt>(n+1)(n+2)/2</tt>.
7056 * a.repeated_combination(1) {|combination| p combination }
7063 * a.repeated_combination(2) {|combination| p combination }
7072 * If +n+ is zero, calls the block once with an empty \Array.
7074 * If +n+ is negative, does not call the block:
7075 * a.repeated_combination(-1) {|combination| fail 'Cannot happen' }
7077 * Returns a new \Enumerator if no block given:
7079 * a.repeated_combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
7081 * Using Enumerators, it's convenient to show the combinations and counts
7082 * for some values of +n+:
7083 * e = a.repeated_combination(0)
7086 * e = a.repeated_combination(1)
7088 * e.to_a # => [[0], [1], [2]]
7089 * e = a.repeated_combination(2)
7091 * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7095 rb_ary_repeated_combination(VALUE ary
, VALUE num
)
7099 n
= NUM2LONG(num
); /* Combination size from argument */
7100 RETURN_SIZED_ENUMERATOR(ary
, 1, &num
, rb_ary_repeated_combination_size
); /* Return enumerator if no block */
7101 len
= RARRAY_LEN(ary
);
7106 rb_yield(rb_ary_new2(0));
7109 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7110 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary
, i
)));
7113 else if (len
== 0) {
7118 long *p
= ALLOCV_N(long, t0
, n
);
7119 VALUE ary0
= ary_make_shared_copy(ary
); /* private defensive copy of ary */
7120 RBASIC_CLEAR_CLASS(ary0
);
7122 rcombinate0(len
, n
, p
, n
, ary0
); /* compute and yield repeated combinations */
7124 RBASIC_SET_CLASS_RAW(ary0
, rb_cArray
);
7131 * array.product(*other_arrays) -> new_array
7132 * array.product(*other_arrays) {|combination| ... } -> self
7134 * Computes and returns or yields all combinations of elements from all the Arrays,
7135 * including both +self+ and +other_arrays+.
7136 * - The number of combinations is the product of the sizes of all the arrays,
7137 * including both +self+ and +other_arrays+.
7138 * - The order of the returned combinations is indeterminate.
7140 * When no block is given, returns the combinations as an \Array of Arrays:
7145 * p.size # => 6 # a.size * a1.size
7146 * p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]]
7147 * p = a.product(a1, a2)
7148 * p.size # => 12 # a.size * a1.size * a2.size
7149 * p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
7151 * If any argument is an empty \Array, returns an empty \Array.
7153 * If no argument is given, returns an \Array of 1-element Arrays,
7154 * each containing an element of +self+:
7155 * a.product # => [[0], [1], [2]]
7157 * When a block is given, yields each combination as an \Array; returns +self+:
7158 * a.product(a1) {|combination| p combination }
7167 * If any argument is an empty \Array, does not call the block:
7168 * a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
7170 * If no argument is given, yields each element of +self+ as a 1-element \Array:
7171 * a.product {|combination| p combination }
7179 rb_ary_product(int argc
, VALUE
*argv
, VALUE ary
)
7181 int n
= argc
+1; /* How many arrays we're operating on */
7182 volatile VALUE t0
= tmpary(n
);
7183 volatile VALUE t1
= Qundef
;
7184 VALUE
*arrays
= RARRAY_PTR(t0
); /* The arrays we're computing the product of */
7185 int *counters
= ALLOCV_N(int, t1
, n
); /* The current position in each one */
7186 VALUE result
= Qnil
; /* The array we'll be returning, when no block given */
7190 RBASIC_CLEAR_CLASS(t0
);
7192 /* initialize the arrays of arrays */
7195 for (i
= 1; i
< n
; i
++) arrays
[i
] = Qnil
;
7196 for (i
= 1; i
< n
; i
++) arrays
[i
] = to_ary(argv
[i
-1]);
7198 /* initialize the counters for the arrays */
7199 for (i
= 0; i
< n
; i
++) counters
[i
] = 0;
7201 /* Otherwise, allocate and fill in an array of results */
7202 if (rb_block_given_p()) {
7203 /* Make defensive copies of arrays; exit if any is empty */
7204 for (i
= 0; i
< n
; i
++) {
7205 if (RARRAY_LEN(arrays
[i
]) == 0) goto done
;
7206 arrays
[i
] = ary_make_shared_copy(arrays
[i
]);
7210 /* Compute the length of the result array; return [] if any is empty */
7211 for (i
= 0; i
< n
; i
++) {
7212 long k
= RARRAY_LEN(arrays
[i
]);
7214 result
= rb_ary_new2(0);
7217 if (MUL_OVERFLOW_LONG_P(resultlen
, k
))
7218 rb_raise(rb_eRangeError
, "too big to product");
7221 result
= rb_ary_new2(resultlen
);
7225 /* fill in one subarray */
7226 VALUE subarray
= rb_ary_new2(n
);
7227 for (j
= 0; j
< n
; j
++) {
7228 rb_ary_push(subarray
, rb_ary_entry(arrays
[j
], counters
[j
]));
7231 /* put it on the result array */
7232 if (NIL_P(result
)) {
7233 FL_SET(t0
, FL_USER5
);
7235 if (! FL_TEST(t0
, FL_USER5
)) {
7236 rb_raise(rb_eRuntimeError
, "product reentered");
7239 FL_UNSET(t0
, FL_USER5
);
7243 rb_ary_push(result
, subarray
);
7247 * Increment the last counter. If it overflows, reset to 0
7248 * and increment the one before it.
7252 while (counters
[m
] == RARRAY_LEN(arrays
[m
])) {
7254 /* If the first counter overflows, we are done */
7255 if (--m
< 0) goto done
;
7263 return NIL_P(result
) ? ary
: result
;
7268 * array.take(n) -> new_array
7270 * Returns a new \Array containing the first +n+ element of +self+,
7271 * where +n+ is a non-negative \Integer;
7272 * does not modify +self+.
7275 * a = [0, 1, 2, 3, 4, 5]
7276 * a.take(1) # => [0]
7277 * a.take(2) # => [0, 1]
7278 * a.take(50) # => [0, 1, 2, 3, 4, 5]
7279 * a # => [0, 1, 2, 3, 4, 5]
7283 rb_ary_take(VALUE obj
, VALUE n
)
7285 long len
= NUM2LONG(n
);
7287 rb_raise(rb_eArgError
, "attempt to take negative size");
7289 return rb_ary_subseq(obj
, 0, len
);
7294 * array.take_while {|element| ... } -> new_array
7295 * array.take_while -> new_enumerator
7297 * Returns a new \Array containing zero or more leading elements of +self+;
7298 * does not modify +self+.
7300 * With a block given, calls the block with each successive element of +self+;
7301 * stops if the block returns +false+ or +nil+;
7302 * returns a new Array containing those elements for which the block returned a truthy value:
7303 * a = [0, 1, 2, 3, 4, 5]
7304 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7305 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7306 * a # => [0, 1, 2, 3, 4, 5]
7308 * With no block given, returns a new \Enumerator:
7309 * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
7313 rb_ary_take_while(VALUE ary
)
7317 RETURN_ENUMERATOR(ary
, 0, 0);
7318 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7319 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7321 return rb_ary_take(ary
, LONG2FIX(i
));
7326 * array.drop(n) -> new_array
7328 * Returns a new \Array containing all but the first +n+ element of +self+,
7329 * where +n+ is a non-negative \Integer;
7330 * does not modify +self+.
7333 * a = [0, 1, 2, 3, 4, 5]
7334 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7335 * a.drop(1) # => [1, 2, 3, 4, 5]
7336 * a.drop(2) # => [2, 3, 4, 5]
7340 rb_ary_drop(VALUE ary
, VALUE n
)
7343 long pos
= NUM2LONG(n
);
7345 rb_raise(rb_eArgError
, "attempt to drop negative size");
7348 result
= rb_ary_subseq(ary
, pos
, RARRAY_LEN(ary
));
7349 if (NIL_P(result
)) result
= rb_ary_new();
7355 * array.drop_while {|element| ... } -> new_array
7356 * array.drop_while -> new_enumerator
7358 * Returns a new \Array containing zero or more trailing elements of +self+;
7359 * does not modify +self+.
7361 * With a block given, calls the block with each successive element of +self+;
7362 * stops if the block returns +false+ or +nil+;
7363 * returns a new Array _omitting_ those elements for which the block returned a truthy value:
7364 * a = [0, 1, 2, 3, 4, 5]
7365 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7367 * With no block given, returns a new \Enumerator:
7368 * [0, 1].drop_while # => # => #<Enumerator: [0, 1]:drop_while>
7372 rb_ary_drop_while(VALUE ary
)
7376 RETURN_ENUMERATOR(ary
, 0, 0);
7377 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7378 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) break;
7380 return rb_ary_drop(ary
, LONG2FIX(i
));
7385 * array.any? -> true or false
7386 * array.any? {|element| ... } -> true or false
7387 * array.any?(obj) -> true or false
7389 * Returns +true+ if any element of +self+ meets a given criterion.
7391 * With no block given and no argument, returns +true+ if +self+ has any truthy element,
7392 * +false+ otherwise:
7393 * [nil, 0, false].any? # => true
7394 * [nil, false].any? # => false
7395 * [].any? # => false
7397 * With a block given and no argument, calls the block with each element in +self+;
7398 * returns +true+ if the block returns any truthy value, +false+ otherwise:
7399 * [0, 1, 2].any? {|element| element > 1 } # => true
7400 * [0, 1, 2].any? {|element| element > 2 } # => false
7402 * If argument +obj+ is given, returns +true+ if +obj+.<tt>===</tt> any element,
7403 * +false+ otherwise:
7404 * ['food', 'drink'].any?(/foo/) # => true
7405 * ['food', 'drink'].any?(/bar/) # => false
7406 * [].any?(/foo/) # => false
7407 * [0, 1, 2].any?(1) # => true
7408 * [0, 1, 2].any?(3) # => false
7410 * Related: Enumerable#any?
7414 rb_ary_any_p(int argc
, VALUE
*argv
, VALUE ary
)
7416 long i
, len
= RARRAY_LEN(ary
);
7418 rb_check_arity(argc
, 0, 1);
7419 if (!len
) return Qfalse
;
7421 if (rb_block_given_p()) {
7422 rb_warn("given block not used");
7424 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7425 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qtrue
;
7428 else if (!rb_block_given_p()) {
7429 for (i
= 0; i
< len
; ++i
) {
7430 if (RTEST(RARRAY_AREF(ary
, i
))) return Qtrue
;
7434 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7435 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qtrue
;
7443 * array.all? -> true or false
7444 * array.all? {|element| ... } -> true or false
7445 * array.all?(obj) -> true or false
7447 * Returns +true+ if all elements of +self+ meet a given criterion.
7449 * With no block given and no argument, returns +true+ if +self+ contains only truthy elements,
7450 * +false+ otherwise:
7451 * [0, 1, :foo].all? # => true
7452 * [0, nil, 2].all? # => false
7455 * With a block given and no argument, calls the block with each element in +self+;
7456 * returns +true+ if the block returns only truthy values, +false+ otherwise:
7457 * [0, 1, 2].all? { |element| element < 3 } # => true
7458 * [0, 1, 2].all? { |element| element < 2 } # => false
7460 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> every element, +false+ otherwise:
7461 * ['food', 'fool', 'foot'].all?(/foo/) # => true
7462 * ['food', 'drink'].all?(/bar/) # => false
7463 * [].all?(/foo/) # => true
7464 * [0, 0, 0].all?(0) # => true
7465 * [0, 1, 2].all?(1) # => false
7467 * Related: Enumerable#all?
7471 rb_ary_all_p(int argc
, VALUE
*argv
, VALUE ary
)
7473 long i
, len
= RARRAY_LEN(ary
);
7475 rb_check_arity(argc
, 0, 1);
7476 if (!len
) return Qtrue
;
7478 if (rb_block_given_p()) {
7479 rb_warn("given block not used");
7481 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7482 if (!RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7485 else if (!rb_block_given_p()) {
7486 for (i
= 0; i
< len
; ++i
) {
7487 if (!RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7491 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7492 if (!RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7500 * array.none? -> true or false
7501 * array.none? {|element| ... } -> true or false
7502 * array.none?(obj) -> true or false
7504 * Returns +true+ if no element of +self+ meet a given criterion.
7506 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
7507 * +false+ otherwise:
7508 * [nil, false].none? # => true
7509 * [nil, 0, false].none? # => false
7510 * [].none? # => true
7512 * With a block given and no argument, calls the block with each element in +self+;
7513 * returns +true+ if the block returns no truthy value, +false+ otherwise:
7514 * [0, 1, 2].none? {|element| element > 3 } # => true
7515 * [0, 1, 2].none? {|element| element > 1 } # => false
7517 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> no element, +false+ otherwise:
7518 * ['food', 'drink'].none?(/bar/) # => true
7519 * ['food', 'drink'].none?(/foo/) # => false
7520 * [].none?(/foo/) # => true
7521 * [0, 1, 2].none?(3) # => true
7522 * [0, 1, 2].none?(1) # => false
7524 * Related: Enumerable#none?
7528 rb_ary_none_p(int argc
, VALUE
*argv
, VALUE ary
)
7530 long i
, len
= RARRAY_LEN(ary
);
7532 rb_check_arity(argc
, 0, 1);
7533 if (!len
) return Qtrue
;
7535 if (rb_block_given_p()) {
7536 rb_warn("given block not used");
7538 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7539 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) return Qfalse
;
7542 else if (!rb_block_given_p()) {
7543 for (i
= 0; i
< len
; ++i
) {
7544 if (RTEST(RARRAY_AREF(ary
, i
))) return Qfalse
;
7548 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7549 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) return Qfalse
;
7557 * array.one? -> true or false
7558 * array.one? {|element| ... } -> true or false
7559 * array.one?(obj) -> true or false
7561 * Returns +true+ if exactly one element of +self+ meets a given criterion.
7563 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
7564 * +false+ otherwise:
7565 * [nil, 0].one? # => true
7566 * [0, 0].one? # => false
7567 * [nil, nil].one? # => false
7568 * [].one? # => false
7570 * With a block given and no argument, calls the block with each element in +self+;
7571 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
7572 * [0, 1, 2].one? {|element| element > 0 } # => false
7573 * [0, 1, 2].one? {|element| element > 1 } # => true
7574 * [0, 1, 2].one? {|element| element > 2 } # => false
7576 * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> exactly one element,
7577 * +false+ otherwise:
7578 * [0, 1, 2].one?(0) # => true
7579 * [0, 0, 1].one?(0) # => false
7580 * [1, 1, 2].one?(0) # => false
7581 * ['food', 'drink'].one?(/bar/) # => false
7582 * ['food', 'drink'].one?(/foo/) # => true
7583 * [].one?(/foo/) # => false
7585 * Related: Enumerable#one?
7589 rb_ary_one_p(int argc
, VALUE
*argv
, VALUE ary
)
7591 long i
, len
= RARRAY_LEN(ary
);
7592 VALUE result
= Qfalse
;
7594 rb_check_arity(argc
, 0, 1);
7595 if (!len
) return Qfalse
;
7597 if (rb_block_given_p()) {
7598 rb_warn("given block not used");
7600 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7601 if (RTEST(rb_funcall(argv
[0], idEqq
, 1, RARRAY_AREF(ary
, i
)))) {
7602 if (result
) return Qfalse
;
7607 else if (!rb_block_given_p()) {
7608 for (i
= 0; i
< len
; ++i
) {
7609 if (RTEST(RARRAY_AREF(ary
, i
))) {
7610 if (result
) return Qfalse
;
7616 for (i
= 0; i
< RARRAY_LEN(ary
); ++i
) {
7617 if (RTEST(rb_yield(RARRAY_AREF(ary
, i
)))) {
7618 if (result
) return Qfalse
;
7628 * array.dig(index, *identifiers) -> object
7630 * Finds and returns the object in nested objects
7631 * that is specified by +index+ and +identifiers+.
7632 * The nested objects may be instances of various classes.
7633 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
7636 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
7637 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
7638 * a.dig(1, 2) # => [:bat, :bam]
7639 * a.dig(1, 2, 0) # => :bat
7640 * a.dig(1, 2, 3) # => nil
7644 rb_ary_dig(int argc
, VALUE
*argv
, VALUE self
)
7646 rb_check_arity(argc
, 1, UNLIMITED_ARGUMENTS
);
7647 self
= rb_ary_at(self
, *argv
);
7648 if (!--argc
) return self
;
7650 return rb_obj_dig(argc
, argv
, self
, Qnil
);
7654 finish_exact_sum(long n
, VALUE r
, VALUE v
, int z
)
7657 v
= rb_fix_plus(LONG2FIX(n
), v
);
7659 v
= rb_rational_plus(r
, v
);
7662 v
= rb_fix_plus(LONG2FIX(0), v
);
7669 * array.sum(init = 0) -> object
7670 * array.sum(init = 0) {|element| ... } -> object
7672 * When no block is given, returns the object equivalent to:
7674 * array.each {|element| sum += element }
7676 * For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
7681 * a.sum(100) # => 106
7683 * The elements need not be numeric, but must be <tt>+</tt>-compatible
7684 * with each other and with +init+:
7685 * a = ['abc', 'def', 'ghi']
7686 * a.sum('jkl') # => "jklabcdefghi"
7688 * When a block is given, it is called with each element
7689 * and the block's return value (instead of the element itself) is used as the addend:
7690 * a = ['zero', 1, :two]
7691 * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
7692 * s # => "Coerced and concatenated: zero1two"
7695 * - Array#join and Array#flatten may be faster than Array#sum
7696 * for an \Array of Strings or an \Array of Arrays.
7697 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
7701 rb_ary_sum(int argc
, VALUE
*argv
, VALUE ary
)
7707 v
= (rb_check_arity(argc
, 0, 1) ? argv
[0] : LONG2FIX(0));
7709 block_given
= rb_block_given_p();
7711 if (RARRAY_LEN(ary
) == 0)
7716 for (i
= 0; i
< RARRAY_LEN(ary
); i
++) {
7717 e
= RARRAY_AREF(ary
, i
);
7721 n
+= FIX2LONG(e
); /* should not overflow long type */
7723 v
= rb_big_plus(LONG2NUM(n
), v
);
7727 else if (RB_BIGNUM_TYPE_P(e
))
7728 v
= rb_big_plus(e
, v
);
7729 else if (RB_TYPE_P(e
, T_RATIONAL
)) {
7733 r
= rb_rational_plus(r
, e
);
7738 v
= finish_exact_sum(n
, r
, v
, argc
!=0);
7742 v
= finish_exact_sum(n
, r
, v
, i
!=0);
7744 if (RB_FLOAT_TYPE_P(e
)) {
7746 * Kahan-Babuska balancing compensated summation algorithm
7747 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
7754 goto has_float_value
;
7755 for (; i
< RARRAY_LEN(ary
); i
++) {
7756 e
= RARRAY_AREF(ary
, i
);
7759 if (RB_FLOAT_TYPE_P(e
))
7761 x
= RFLOAT_VALUE(e
);
7762 else if (FIXNUM_P(e
))
7764 else if (RB_BIGNUM_TYPE_P(e
))
7766 else if (RB_TYPE_P(e
, T_RATIONAL
))
7771 if (isnan(f
)) continue;
7777 if (isinf(f
) && signbit(x
) != signbit(f
))
7783 if (isinf(f
)) continue;
7786 if (fabs(f
) >= fabs(x
))
7799 goto has_some_value
;
7800 for (; i
< RARRAY_LEN(ary
); i
++) {
7801 e
= RARRAY_AREF(ary
, i
);
7805 v
= rb_funcall(v
, idPLUS
, 1, e
);
7811 rb_ary_deconstruct(VALUE ary
)
7817 * An \Array is an ordered, integer-indexed collection of objects,
7818 * called _elements_. Any object may be an \Array element.
7822 * \Array indexing starts at 0, as in C or Java.
7824 * A positive index is an offset from the first element:
7825 * - Index 0 indicates the first element.
7826 * - Index 1 indicates the second element.
7829 * A negative index is an offset, backwards, from the end of the array:
7830 * - Index -1 indicates the last element.
7831 * - Index -2 indicates the next-to-last element.
7834 * A non-negative index is <i>in range</i> if it is smaller than
7835 * the size of the array. For a 3-element array:
7836 * - Indexes 0 through 2 are in range.
7837 * - Index 3 is out of range.
7839 * A negative index is <i>in range</i> if its absolute value is
7840 * not larger than the size of the array. For a 3-element array:
7841 * - Indexes -1 through -3 are in range.
7842 * - Index -4 is out of range.
7844 * == Creating Arrays
7846 * You can create an \Array object explicitly with:
7848 * - An {array literal}[doc/syntax/literals_rdoc.html#label-Array+Literals].
7850 * You can convert certain objects to Arrays with:
7852 * - \Method {Array}[Kernel.html#method-i-Array].
7854 * An \Array can contain different types of objects. For
7855 * example, the array below contains an Integer, a String and a Float:
7857 * ary = [1, "two", 3.0] #=> [1, "two", 3.0]
7859 * An array can also be created by calling Array.new with zero, one
7860 * (the initial size of the Array) or two arguments (the initial size and a
7863 * ary = Array.new #=> []
7864 * Array.new(3) #=> [nil, nil, nil]
7865 * Array.new(3, true) #=> [true, true, true]
7867 * Note that the second argument populates the array with references to the
7868 * same object. Therefore, it is only recommended in cases when you need to
7869 * instantiate arrays with natively immutable objects such as Symbols,
7870 * numbers, true or false.
7872 * To create an array with separate objects a block can be passed instead.
7873 * This method is safe to use with mutable objects such as hashes, strings or
7876 * Array.new(4) {Hash.new} #=> [{}, {}, {}, {}]
7877 * Array.new(4) {|i| i.to_s } #=> ["0", "1", "2", "3"]
7879 * This is also a quick way to build up multi-dimensional arrays:
7881 * empty_table = Array.new(3) {Array.new(3)}
7882 * #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
7884 * An array can also be created by using the Array() method, provided by
7885 * Kernel, which tries to call #to_ary, then #to_a on its argument.
7887 * Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
7891 * In addition to the methods it mixes in through the Enumerable module, the
7892 * Array class has proprietary methods for accessing, searching and otherwise
7893 * manipulating arrays.
7895 * Some of the more common ones are illustrated below.
7897 * == Accessing Elements
7899 * Elements in an array can be retrieved using the Array#[] method. It can
7900 * take a single integer argument (a numeric index), a pair of arguments
7901 * (start and length) or a range. Negative indices start counting from the end,
7902 * with -1 being the last element.
7904 * arr = [1, 2, 3, 4, 5, 6]
7908 * arr[2, 3] #=> [3, 4, 5]
7909 * arr[1..4] #=> [2, 3, 4, 5]
7910 * arr[1..-3] #=> [2, 3, 4]
7912 * Another way to access a particular array element is by using the #at method
7916 * The #slice method works in an identical manner to Array#[].
7918 * To raise an error for indices outside of the array bounds or else to
7919 * provide a default value when that happens, you can use #fetch.
7921 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
7922 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
7923 * arr.fetch(100, "oops") #=> "oops"
7925 * The special methods #first and #last will return the first and last
7926 * elements of an array, respectively.
7931 * To return the first +n+ elements of an array, use #take
7933 * arr.take(3) #=> [1, 2, 3]
7935 * #drop does the opposite of #take, by returning the elements after +n+
7936 * elements have been dropped:
7938 * arr.drop(3) #=> [4, 5, 6]
7940 * == Obtaining Information about an Array
7942 * Arrays keep track of their own length at all times. To query an array
7943 * about the number of elements it contains, use #length, #count or #size.
7945 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
7946 * browsers.length #=> 5
7947 * browsers.count #=> 5
7949 * To check whether an array contains any elements at all
7951 * browsers.empty? #=> false
7953 * To check whether a particular item is included in the array
7955 * browsers.include?('Konqueror') #=> false
7957 * == Adding Items to Arrays
7959 * Items can be added to the end of an array by using either #push or #<<
7961 * arr = [1, 2, 3, 4]
7962 * arr.push(5) #=> [1, 2, 3, 4, 5]
7963 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
7965 * #unshift will add a new item to the beginning of an array.
7967 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
7969 * With #insert you can add a new element to an array at any position.
7971 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
7973 * Using the #insert method, you can also insert multiple values at once:
7975 * arr.insert(3, 'orange', 'pear', 'grapefruit')
7976 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
7978 * == Removing Items from an Array
7980 * The method #pop removes the last element in an array and returns it:
7982 * arr = [1, 2, 3, 4, 5, 6]
7984 * arr #=> [1, 2, 3, 4, 5]
7986 * To retrieve and at the same time remove the first item, use #shift:
7989 * arr #=> [2, 3, 4, 5]
7991 * To delete an element at a particular index:
7993 * arr.delete_at(2) #=> 4
7996 * To delete a particular element anywhere in an array, use #delete:
7998 * arr = [1, 2, 2, 3]
7999 * arr.delete(2) #=> 2
8002 * A useful method if you need to remove +nil+ values from an array is
8005 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8006 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8007 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8008 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8009 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8011 * Another common need is to remove duplicate elements from an array.
8013 * It has the non-destructive #uniq, and destructive method #uniq!
8015 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8016 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8018 * == Iterating over Arrays
8020 * Like all classes that include the Enumerable module, Array has an each
8021 * method, which defines what elements should be iterated over and how. In
8022 * case of Array's #each, all elements in the Array instance are yielded to
8023 * the supplied block in sequence.
8025 * Note that this operation leaves the array unchanged.
8027 * arr = [1, 2, 3, 4, 5]
8028 * arr.each {|a| print a -= 10, " "}
8029 * # prints: -9 -8 -7 -6 -5
8030 * #=> [1, 2, 3, 4, 5]
8032 * Another sometimes useful iterator is #reverse_each which will iterate over
8033 * the elements in the array in reverse order.
8035 * words = %w[first second third fourth fifth sixth]
8037 * words.reverse_each {|word| str += "#{word} "}
8038 * p str #=> "sixth fifth fourth third second first "
8040 * The #map method can be used to create a new array based on the original
8041 * array, but with the values modified by the supplied block:
8043 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8044 * arr #=> [1, 2, 3, 4, 5]
8045 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8046 * arr #=> [1, 4, 9, 16, 25]
8048 * == Selecting Items from an Array
8050 * Elements can be selected from an array according to criteria defined in a
8051 * block. The selection can happen in a destructive or a non-destructive
8052 * manner. While the destructive operations will modify the array they were
8053 * called on, the non-destructive methods usually return a new array with the
8054 * selected elements, but leave the original array unchanged.
8056 * === Non-destructive Selection
8058 * arr = [1, 2, 3, 4, 5, 6]
8059 * arr.select {|a| a > 3} #=> [4, 5, 6]
8060 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8061 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8062 * arr #=> [1, 2, 3, 4, 5, 6]
8064 * === Destructive Selection
8066 * #select! and #reject! are the corresponding destructive methods to #select
8069 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8070 * opposite result when supplied with the same block:
8072 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8075 * arr = [1, 2, 3, 4, 5, 6]
8076 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8081 * First, what's elsewhere. \Class \Array:
8083 * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
8084 * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here],
8085 * which provides dozens of additional methods.
8087 * Here, class \Array provides methods that are useful for:
8089 * - {Creating an Array}[#class-Array-label-Methods+for+Creating+an+Array]
8090 * - {Querying}[#class-Array-label-Methods+for+Querying]
8091 * - {Comparing}[#class-Array-label-Methods+for+Comparing]
8092 * - {Fetching}[#class-Array-label-Methods+for+Fetching]
8093 * - {Assigning}[#class-Array-label-Methods+for+Assigning]
8094 * - {Deleting}[#class-Array-label-Methods+for+Deleting]
8095 * - {Combining}[#class-Array-label-Methods+for+Combining]
8096 * - {Iterating}[#class-Array-label-Methods+for+Iterating]
8097 * - {Converting}[#class-Array-label-Methods+for+Converting]
8098 * - {And more....}[#class-Array-label-Other+Methods]
8100 * === Methods for Creating an Array
8102 * ::[]:: Returns a new array populated with given objects.
8103 * ::new:: Returns a new array.
8104 * ::try_convert:: Returns a new array created from a given object.
8106 * === Methods for Querying
8108 * #length, #size:: Returns the count of elements.
8109 * #include?:: Returns whether any element <tt>==</tt> a given object.
8110 * #empty?:: Returns whether there are no elements.
8111 * #all?:: Returns whether all elements meet a given criterion.
8112 * #any?:: Returns whether any element meets a given criterion.
8113 * #none?:: Returns whether no element <tt>==</tt> a given object.
8114 * #one?:: Returns whether exactly one element <tt>==</tt> a given object.
8115 * #count:: Returns the count of elements that meet a given criterion.
8116 * #find_index, #index:: Returns the index of the first element that meets a given criterion.
8117 * #rindex:: Returns the index of the last element that meets a given criterion.
8118 * #hash:: Returns the integer hash code.
8120 * === Methods for Comparing
8121 * {#<=>}[#method-i-3C-3D-3E]:: Returns -1, 0, or 1
8122 * as +self+ is less than, equal to, or greater than a given object.
8123 * {#==}[#method-i-3D-3D]:: Returns whether each element in +self+ is <tt>==</tt> to the
8124 * corresponding element in a given object.
8125 * #eql?:: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
8126 * element in a given object.
8128 * === Methods for Fetching
8130 * These methods do not modify +self+.
8132 * #[]:: Returns one or more elements.
8133 * #fetch:: Returns the element at a given offset.
8134 * #first:: Returns one or more leading elements.
8135 * #last:: Returns one or more trailing elements.
8136 * #max:: Returns one or more maximum-valued elements,
8137 * as determined by <tt><=></tt> or a given block.
8138 * #max:: Returns one or more minimum-valued elements,
8139 * as determined by <tt><=></tt> or a given block.
8140 * #minmax:: Returns the minimum-valued and maximum-valued elements,
8141 * as determined by <tt><=></tt> or a given block.
8142 * #assoc:: Returns the first element that is an array
8143 * whose first element <tt>==</tt> a given object.
8144 * #rassoc:: Returns the first element that is an array
8145 * whose second element <tt>==</tt> a given object.
8146 * #at:: Returns the element at a given offset.
8147 * #values_at:: Returns the elements at given offsets.
8148 * #dig:: Returns the object in nested objects
8149 * that is specified by a given index and additional arguments.
8150 * #drop:: Returns trailing elements as determined by a given index.
8151 * #take:: Returns leading elements as determined by a given index.
8152 * #drop_while:: Returns trailing elements as determined by a given block.
8153 * #take_while:: Returns leading elements as determined by a given block.
8154 * #slice:: Returns consecutive elements as determined by a given argument.
8155 * #sort:: Returns all elements in an order determined by <tt><=></tt> or a given block.
8156 * #reverse:: Returns all elements in reverse order.
8157 * #compact:: Returns an array containing all non-+nil+ elements.
8158 * #select, #filter:: Returns an array containing elements selected by a given block.
8159 * #uniq:: Returns an array containing non-duplicate elements.
8160 * #rotate:: Returns all elements with some rotated from one end to the other.
8161 * #bsearch:: Returns an element selected via a binary search
8162 * as determined by a given block.
8163 * #bsearch_index:: Returns the index of an element selected via a binary search
8164 * as determined by a given block.
8165 * #sample:: Returns one or more random elements.
8166 * #shuffle:: Returns elements in a random order.
8168 * === Methods for Assigning
8170 * These methods add, replace, or reorder elements in +self+.
8172 * #[]=:: Assigns specified elements with a given object.
8173 * #push, #append, #<<:: Appends trailing elements.
8174 * #unshift, #prepend:: Prepends leading elements.
8175 * #insert:: Inserts given objects at a given offset; does not replace elements.
8176 * #concat:: Appends all elements from given arrays.
8177 * #fill:: Replaces specified elements with specified objects.
8178 * #replace:: Replaces the content of +self+ with the content of a given array.
8179 * #reverse!:: Replaces +self+ with its elements reversed.
8180 * #rotate!:: Replaces +self+ with its elements rotated.
8181 * #shuffle!:: Replaces +self+ with its elements in random order.
8182 * #sort!:: Replaces +self+ with its elements sorted,
8183 * as determined by <tt><=></tt> or a given block.
8184 * #sort_by!:: Replaces +self+ with its elements sorted, as determined by a given block.
8186 * === Methods for Deleting
8188 * Each of these methods removes elements from +self+:
8190 * #pop:: Removes and returns the last element.
8191 * #shift:: Removes and returns the first element.
8192 * #compact!:: Removes all non-+nil+ elements.
8193 * #delete:: Removes elements equal to a given object.
8194 * #delete_at:: Removes the element at a given offset.
8195 * #delete_if:: Removes elements specified by a given block.
8196 * #keep_if:: Removes elements not specified by a given block.
8197 * #reject!:: Removes elements specified by a given block.
8198 * #select!, #filter!:: Removes elements not specified by a given block.
8199 * #slice!:: Removes and returns a sequence of elements.
8200 * #uniq!:: Removes duplicates.
8202 * === Methods for Combining
8204 * {#&}[#method-i-26]:: Returns an array containing elements found both in +self+ and a given array.
8205 * #intersection:: Returns an array containing elements found both in +self+
8206 * and in each given array.
8207 * #+:: Returns an array containing all elements of +self+ followed by all elements of a given array.
8208 * #-:: Returns an array containiing all elements of +self+ that are not found in a given array.
8209 * {#|}[#method-i-7C]:: Returns an array containing all elements of +self+ and all elements of a given array,
8210 * duplicates removed.
8211 * #union:: Returns an array containing all elements of +self+ and all elements of given arrays,
8212 * duplicates removed.
8213 * #difference:: Returns an array containing all elements of +self+ that are not found
8214 * in any of the given arrays..
8215 * #product:: Returns or yields all combinations of elements from +self+ and given arrays.
8217 * === Methods for Iterating
8219 * #each:: Passes each element to a given block.
8220 * #reverse_each:: Passes each element, in reverse order, to a given block.
8221 * #each_index:: Passes each element index to a given block.
8222 * #cycle:: Calls a given block with each element, then does so again,
8223 * for a specified number of times, or forever.
8224 * #combination:: Calls a given block with combinations of elements of +self+;
8225 * a combination does not use the same element more than once.
8226 * #permutation:: Calls a given block with permutations of elements of +self+;
8227 * a permutation does not use the same element more than once.
8228 * #repeated_combination:: Calls a given block with combinations of elements of +self+;
8229 * a combination may use the same element more than once.
8230 * #repeated_permutation:: Calls a given block with permutations of elements of +self+;
8231 * a permutation may use the same element more than once.
8233 * === Methods for Converting
8235 * #map, #collect:: Returns an array containing the block return-value for each element.
8236 * #map!, #collect!:: Replaces each element with a block return-value.
8237 * #flatten:: Returns an array that is a recursive flattening of +self+.
8238 * #flatten!:: Replaces each nested array in +self+ with the elements from that array.
8239 * #inspect, #to_s:: Returns a new String containing the elements.
8240 * #join:: Returns a newsString containing the elements joined by the field separator.
8241 * #to_a:: Returns +self+ or a new array containing all elements.
8242 * #to_ary:: Returns +self+.
8243 * #to_h:: Returns a new hash formed from the elements.
8244 * #transpose:: Transposes +self+, which must be an array of arrays.
8245 * #zip:: Returns a new array of arrays containing +self+ and given arrays;
8246 * follow the link for details.
8250 * #*:: Returns one of the following:
8251 * - With integer argument +n+, a new array that is the concatenation
8252 * of +n+ copies of +self+.
8253 * - With string argument +field_separator+, a new string that is equivalent to
8254 * <tt>join(field_separator)</tt>.
8255 * #abbrev:: Returns a hash of unambiguous abbreviations for elements.
8256 * #pack:: Packs the elements into a binary sequence.
8257 * #sum:: Returns a sum of elements according to either <tt>+</tt> or a given block.
8263 rb_cArray
= rb_define_class("Array", rb_cObject
);
8264 rb_include_module(rb_cArray
, rb_mEnumerable
);
8266 rb_define_alloc_func(rb_cArray
, empty_ary_alloc
);
8267 rb_define_singleton_method(rb_cArray
, "[]", rb_ary_s_create
, -1);
8268 rb_define_singleton_method(rb_cArray
, "try_convert", rb_ary_s_try_convert
, 1);
8269 rb_define_method(rb_cArray
, "initialize", rb_ary_initialize
, -1);
8270 rb_define_method(rb_cArray
, "initialize_copy", rb_ary_replace
, 1);
8272 rb_define_method(rb_cArray
, "inspect", rb_ary_inspect
, 0);
8273 rb_define_alias(rb_cArray
, "to_s", "inspect");
8274 rb_define_method(rb_cArray
, "to_a", rb_ary_to_a
, 0);
8275 rb_define_method(rb_cArray
, "to_h", rb_ary_to_h
, 0);
8276 rb_define_method(rb_cArray
, "to_ary", rb_ary_to_ary_m
, 0);
8278 rb_define_method(rb_cArray
, "==", rb_ary_equal
, 1);
8279 rb_define_method(rb_cArray
, "eql?", rb_ary_eql
, 1);
8280 rb_define_method(rb_cArray
, "hash", rb_ary_hash
, 0);
8282 rb_define_method(rb_cArray
, "[]", rb_ary_aref
, -1);
8283 rb_define_method(rb_cArray
, "[]=", rb_ary_aset
, -1);
8284 rb_define_method(rb_cArray
, "at", rb_ary_at
, 1);
8285 rb_define_method(rb_cArray
, "fetch", rb_ary_fetch
, -1);
8286 rb_define_method(rb_cArray
, "first", rb_ary_first
, -1);
8287 rb_define_method(rb_cArray
, "last", rb_ary_last
, -1);
8288 rb_define_method(rb_cArray
, "concat", rb_ary_concat_multi
, -1);
8289 rb_define_method(rb_cArray
, "union", rb_ary_union_multi
, -1);
8290 rb_define_method(rb_cArray
, "difference", rb_ary_difference_multi
, -1);
8291 rb_define_method(rb_cArray
, "intersection", rb_ary_intersection_multi
, -1);
8292 rb_define_method(rb_cArray
, "intersect?", rb_ary_intersect_p
, 1);
8293 rb_define_method(rb_cArray
, "<<", rb_ary_push
, 1);
8294 rb_define_method(rb_cArray
, "push", rb_ary_push_m
, -1);
8295 rb_define_alias(rb_cArray
, "append", "push");
8296 rb_define_method(rb_cArray
, "pop", rb_ary_pop_m
, -1);
8297 rb_define_method(rb_cArray
, "shift", rb_ary_shift_m
, -1);
8298 rb_define_method(rb_cArray
, "unshift", rb_ary_unshift_m
, -1);
8299 rb_define_alias(rb_cArray
, "prepend", "unshift");
8300 rb_define_method(rb_cArray
, "insert", rb_ary_insert
, -1);
8301 rb_define_method(rb_cArray
, "each", rb_ary_each
, 0);
8302 rb_define_method(rb_cArray
, "each_index", rb_ary_each_index
, 0);
8303 rb_define_method(rb_cArray
, "reverse_each", rb_ary_reverse_each
, 0);
8304 rb_define_method(rb_cArray
, "length", rb_ary_length
, 0);
8305 rb_define_method(rb_cArray
, "size", rb_ary_length
, 0);
8306 rb_define_method(rb_cArray
, "empty?", rb_ary_empty_p
, 0);
8307 rb_define_method(rb_cArray
, "find_index", rb_ary_index
, -1);
8308 rb_define_method(rb_cArray
, "index", rb_ary_index
, -1);
8309 rb_define_method(rb_cArray
, "rindex", rb_ary_rindex
, -1);
8310 rb_define_method(rb_cArray
, "join", rb_ary_join_m
, -1);
8311 rb_define_method(rb_cArray
, "reverse", rb_ary_reverse_m
, 0);
8312 rb_define_method(rb_cArray
, "reverse!", rb_ary_reverse_bang
, 0);
8313 rb_define_method(rb_cArray
, "rotate", rb_ary_rotate_m
, -1);
8314 rb_define_method(rb_cArray
, "rotate!", rb_ary_rotate_bang
, -1);
8315 rb_define_method(rb_cArray
, "sort", rb_ary_sort
, 0);
8316 rb_define_method(rb_cArray
, "sort!", rb_ary_sort_bang
, 0);
8317 rb_define_method(rb_cArray
, "sort_by!", rb_ary_sort_by_bang
, 0);
8318 rb_define_method(rb_cArray
, "collect", rb_ary_collect
, 0);
8319 rb_define_method(rb_cArray
, "collect!", rb_ary_collect_bang
, 0);
8320 rb_define_method(rb_cArray
, "map", rb_ary_collect
, 0);
8321 rb_define_method(rb_cArray
, "map!", rb_ary_collect_bang
, 0);
8322 rb_define_method(rb_cArray
, "select", rb_ary_select
, 0);
8323 rb_define_method(rb_cArray
, "select!", rb_ary_select_bang
, 0);
8324 rb_define_method(rb_cArray
, "filter", rb_ary_select
, 0);
8325 rb_define_method(rb_cArray
, "filter!", rb_ary_select_bang
, 0);
8326 rb_define_method(rb_cArray
, "keep_if", rb_ary_keep_if
, 0);
8327 rb_define_method(rb_cArray
, "values_at", rb_ary_values_at
, -1);
8328 rb_define_method(rb_cArray
, "delete", rb_ary_delete
, 1);
8329 rb_define_method(rb_cArray
, "delete_at", rb_ary_delete_at_m
, 1);
8330 rb_define_method(rb_cArray
, "delete_if", rb_ary_delete_if
, 0);
8331 rb_define_method(rb_cArray
, "reject", rb_ary_reject
, 0);
8332 rb_define_method(rb_cArray
, "reject!", rb_ary_reject_bang
, 0);
8333 rb_define_method(rb_cArray
, "zip", rb_ary_zip
, -1);
8334 rb_define_method(rb_cArray
, "transpose", rb_ary_transpose
, 0);
8335 rb_define_method(rb_cArray
, "replace", rb_ary_replace
, 1);
8336 rb_define_method(rb_cArray
, "clear", rb_ary_clear
, 0);
8337 rb_define_method(rb_cArray
, "fill", rb_ary_fill
, -1);
8338 rb_define_method(rb_cArray
, "include?", rb_ary_includes
, 1);
8339 rb_define_method(rb_cArray
, "<=>", rb_ary_cmp
, 1);
8341 rb_define_method(rb_cArray
, "slice", rb_ary_aref
, -1);
8342 rb_define_method(rb_cArray
, "slice!", rb_ary_slice_bang
, -1);
8344 rb_define_method(rb_cArray
, "assoc", rb_ary_assoc
, 1);
8345 rb_define_method(rb_cArray
, "rassoc", rb_ary_rassoc
, 1);
8347 rb_define_method(rb_cArray
, "+", rb_ary_plus
, 1);
8348 rb_define_method(rb_cArray
, "*", rb_ary_times
, 1);
8350 rb_define_method(rb_cArray
, "-", rb_ary_diff
, 1);
8351 rb_define_method(rb_cArray
, "&", rb_ary_and
, 1);
8352 rb_define_method(rb_cArray
, "|", rb_ary_or
, 1);
8354 rb_define_method(rb_cArray
, "max", rb_ary_max
, -1);
8355 rb_define_method(rb_cArray
, "min", rb_ary_min
, -1);
8356 rb_define_method(rb_cArray
, "minmax", rb_ary_minmax
, 0);
8358 rb_define_method(rb_cArray
, "uniq", rb_ary_uniq
, 0);
8359 rb_define_method(rb_cArray
, "uniq!", rb_ary_uniq_bang
, 0);
8360 rb_define_method(rb_cArray
, "compact", rb_ary_compact
, 0);
8361 rb_define_method(rb_cArray
, "compact!", rb_ary_compact_bang
, 0);
8362 rb_define_method(rb_cArray
, "flatten", rb_ary_flatten
, -1);
8363 rb_define_method(rb_cArray
, "flatten!", rb_ary_flatten_bang
, -1);
8364 rb_define_method(rb_cArray
, "count", rb_ary_count
, -1);
8365 rb_define_method(rb_cArray
, "cycle", rb_ary_cycle
, -1);
8366 rb_define_method(rb_cArray
, "permutation", rb_ary_permutation
, -1);
8367 rb_define_method(rb_cArray
, "combination", rb_ary_combination
, 1);
8368 rb_define_method(rb_cArray
, "repeated_permutation", rb_ary_repeated_permutation
, 1);
8369 rb_define_method(rb_cArray
, "repeated_combination", rb_ary_repeated_combination
, 1);
8370 rb_define_method(rb_cArray
, "product", rb_ary_product
, -1);
8372 rb_define_method(rb_cArray
, "take", rb_ary_take
, 1);
8373 rb_define_method(rb_cArray
, "take_while", rb_ary_take_while
, 0);
8374 rb_define_method(rb_cArray
, "drop", rb_ary_drop
, 1);
8375 rb_define_method(rb_cArray
, "drop_while", rb_ary_drop_while
, 0);
8376 rb_define_method(rb_cArray
, "bsearch", rb_ary_bsearch
, 0);
8377 rb_define_method(rb_cArray
, "bsearch_index", rb_ary_bsearch_index
, 0);
8378 rb_define_method(rb_cArray
, "any?", rb_ary_any_p
, -1);
8379 rb_define_method(rb_cArray
, "all?", rb_ary_all_p
, -1);
8380 rb_define_method(rb_cArray
, "none?", rb_ary_none_p
, -1);
8381 rb_define_method(rb_cArray
, "one?", rb_ary_one_p
, -1);
8382 rb_define_method(rb_cArray
, "dig", rb_ary_dig
, -1);
8383 rb_define_method(rb_cArray
, "sum", rb_ary_sum
, -1);
8385 rb_define_method(rb_cArray
, "deconstruct", rb_ary_deconstruct
, 0);
8388 #include "array.rbinc"