Ruby 4.1.0dev (2026-10-04 revision 76aa225e9af575a320135123891fe5b5919411a1)
array.c (76aa225e9af575a320135123891fe5b5919411a1)
1/**********************************************************************
2
3 array.c -
4
5 $Author$
6 created at: Fri Aug 6 09:46:12 JST 1993
7
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
11
12**********************************************************************/
13
14#include "debug_counter.h"
15#include "id.h"
16#include "internal.h"
17#include "internal/array.h"
18#include "internal/compar.h"
19#include "internal/enum.h"
20#include "internal/gc.h"
21#include "internal/hash.h"
22#include "internal/numeric.h"
23#include "internal/object.h"
24#include "internal/proc.h"
25#include "internal/rational.h"
26#include "internal/set.h"
27#include "internal/string.h"
28#include "internal/vm.h"
29#include "probes.h"
30#include "ruby/encoding.h"
31#include "ruby/st.h"
32#include "ruby/thread.h"
33#include "ruby/util.h"
34#include "ruby/ractor.h"
35#include "shape.h"
36#include "vm_core.h"
37#include "builtin.h"
38#include "zjit.h"
39
40#if !ARRAY_DEBUG
41# undef NDEBUG
42# define NDEBUG
43#endif
44#include "ruby_assert.h"
45
47VALUE rb_cArray_empty_frozen;
48
49/* Flags of RArray
50 *
51 * 0: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
52 * The array is shared. The buffer this array points to is owned by
53 * another array (the shared root).
54 * 1: RARRAY_EMBED_FLAG
55 * The array is embedded (its contents follow the header, rather than
56 * being on a separately allocated buffer).
57 * 3-9: RARRAY_EMBED_LEN
58 * The length of the array when RARRAY_EMBED_FLAG is set.
59 * 12: RARRAY_SHARED_ROOT_FLAG
60 * The array is a shared root that does reference counting. The buffer
61 * this array points to is owned by this array but may be pointed to
62 * by other arrays.
63 * Note: Frozen arrays may be a shared root without this flag being
64 * set. Frozen arrays do not have reference counting because
65 * they cannot be modified. Not updating the reference count
66 * improves copy-on-write performance. Their reference count is
67 * assumed to be infinity.
68 * 14: RARRAY_PTR_IN_USE_FLAG
69 * The buffer of the array is in use. This is only used during
70 * debugging.
71 * 19: RARRAY_FAKEARY
72 * The array is not allocated or managed by the garbage collector.
73 * Typically, the array object header (struct RString) is temporarily
74 * allocated on C stack.
75 */
76
77/* for OPTIMIZED_CMP: */
78#define id_cmp idCmp
79
80#define ARY_DEFAULT_SIZE 16
81#define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
82#define SMALL_ARRAY_LEN 16
83
85static int
86should_be_T_ARRAY(VALUE ary)
87{
88 return RB_TYPE_P(ary, T_ARRAY);
89}
90
91#define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
92#define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
93#define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \
94 RARRAY(a)->as.heap.aux.capa)
95
96#define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
97#define ARY_EMBED_LEN(a) \
98 (RUBY_ASSERT(ARY_EMBED_P(a)), \
99 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
100 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
101#define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
102
103#define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \
104 !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG))
105
106#define FL_SET_EMBED(a) do { \
107 RUBY_ASSERT(!ARY_SHARED_P(a)); \
108 FL_SET((a), RARRAY_EMBED_FLAG); \
109 ary_verify(a); \
110} while (0)
111
112#define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
113#define FL_SET_SHARED(ary) do { \
114 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
115 FL_SET((ary), RARRAY_SHARED_FLAG); \
116} while (0)
117#define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
118
119#define ARY_SET_PTR_FORCE(ary, p) \
120 (RARRAY(ary)->as.heap.ptr = (p))
121#define ARY_SET_PTR(ary, p) do { \
122 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
123 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
124 ARY_SET_PTR_FORCE(ary, p); \
125} while (0)
126#define ARY_SET_EMBED_LEN(ary, n) do { \
127 long tmp_n = (n); \
128 RUBY_ASSERT(ARY_EMBED_P(ary)); \
129 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
130 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
131} while (0)
132#define ARY_SET_HEAP_LEN(ary, n) do { \
133 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
134 RARRAY(ary)->as.heap.len = (n); \
135} while (0)
136#define ARY_SET_LEN(ary, n) do { \
137 if (ARY_EMBED_P(ary)) { \
138 ARY_SET_EMBED_LEN((ary), (n)); \
139 } \
140 else { \
141 ARY_SET_HEAP_LEN((ary), (n)); \
142 } \
143 RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \
144} while (0)
145#define ARY_INCREASE_PTR(ary, n) do { \
146 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
147 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
148 RARRAY(ary)->as.heap.ptr += (n); \
149} while (0)
150#define ARY_INCREASE_LEN(ary, n) do { \
151 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
152 if (ARY_EMBED_P(ary)) { \
153 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
154 } \
155 else { \
156 RARRAY(ary)->as.heap.len += (n); \
157 } \
158} while (0)
159
160#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
161 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
162#define ARY_SET_CAPA_FORCE(ary, n) \
163 RARRAY(ary)->as.heap.aux.capa = (n);
164#define ARY_SET_CAPA(ary, n) do { \
165 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
166 RUBY_ASSERT(!ARY_SHARED_P(ary)); \
167 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
168 ARY_SET_CAPA_FORCE(ary, n); \
169} while (0)
170
171#define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
172#define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
173 RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \
174 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
175 RUBY_ASSERT((value) >= 0); \
176 RARRAY(ary)->as.heap.aux.capa = (value); \
177} while (0)
178#define FL_SET_SHARED_ROOT(ary) do { \
179 RUBY_ASSERT(!OBJ_FROZEN(ary)); \
180 RUBY_ASSERT(!ARY_EMBED_P(ary)); \
181 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
182} while (0)
183
184static inline void
185ARY_SET(VALUE a, long i, VALUE v)
186{
187 RUBY_ASSERT(!ARY_SHARED_P(a));
189
190 RARRAY_ASET(a, i, v);
191}
192#undef RARRAY_ASET
193
194static long
195ary_embed_capa(VALUE ary)
196{
197 size_t size = rb_obj_shape_slot_size(ary) - offsetof(struct RArray, as.ary);
198 RUBY_ASSERT(size % sizeof(VALUE) == 0);
199 return size / sizeof(VALUE);
200}
201
202static size_t
203ary_embed_size(long capa)
204{
205 size_t size = offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
206 if (size < sizeof(struct RArray)) size = sizeof(struct RArray);
207 return size;
208}
209
210static bool
211ary_embeddable_p(long capa)
212{
213 const long embed_len_max = RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT;
214
215 return capa <= embed_len_max && rb_gc_size_allocatable_p(ary_embed_size(capa));
216}
217
218bool
219rb_ary_embeddable_p(VALUE ary)
220{
221 RUBY_ASSERT(!ARY_EMBED_P(ary));
222 /* An array cannot be turned embeddable when the array is:
223 * - Shared root: other objects may point to the buffer of this array
224 * so we cannot make it embedded.
225 * - Frozen: this array may also be a shared root without the shared root
226 * flag.
227 * - Shared: we don't want to re-embed an array that points to a shared
228 * root (to save memory).
229 */
230 if (ARY_SHARED_ROOT_P(ary) || OBJ_FROZEN(ary) || ARY_SHARED_P(ary)) return false;
231
232 const long embed_len_max = RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT;
233 return ARY_HEAP_CAPA(ary) <= embed_len_max;
234}
235
236/* True when other arrays may read this array's elements out of its own slot, so the
237 * slot contents must stay valid for as long as the object does. A frozen array is
238 * handed out as a shared root as it is, without the shared root flag. */
239bool
240rb_ary_embedded_shared_root_p(VALUE ary)
241{
242 return ARY_EMBED_P(ary) && OBJ_FROZEN(ary);
243}
244
245size_t
246rb_ary_size_as_embedded(VALUE ary)
247{
248 size_t real_size;
249
250 if (ARY_EMBED_P(ary)) {
251 real_size = ary_embed_size(ARY_EMBED_LEN(ary));
252 }
253 else if (rb_ary_embeddable_p(ary)) {
254 real_size = ary_embed_size(ARY_HEAP_CAPA(ary));
255 }
256 else {
257 real_size = sizeof(struct RArray);
258 }
259 return real_size;
260}
261
262
263#if ARRAY_DEBUG
264#define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
265
266static VALUE
267ary_verify_(VALUE ary, const char *file, int line)
268{
270
271 if (ARY_SHARED_P(ary)) {
272 VALUE root = ARY_SHARED_ROOT(ary);
273 const VALUE *ptr = ARY_HEAP_PTR(ary);
274 const VALUE *root_ptr = RARRAY_CONST_PTR(root);
275 long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
276 RUBY_ASSERT(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root));
277 RUBY_ASSERT(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
278 ary_verify(root);
279 }
280 else if (ARY_EMBED_P(ary)) {
281 RUBY_ASSERT(!ARY_SHARED_P(ary));
282 RUBY_ASSERT(RARRAY_LEN(ary) <= ary_embed_capa(ary));
283 }
284 else {
285 const VALUE *ptr = RARRAY_CONST_PTR(ary);
286 long i, len = RARRAY_LEN(ary);
287 volatile VALUE v;
288 if (len > 1) len = 1; /* check only HEAD */
289 for (i=0; i<len; i++) {
290 v = ptr[i]; /* access check */
291 }
292 v = v;
293 }
294
295 return ary;
296}
297#else
298#define ary_verify(ary) ((void)0)
299#endif
300
301VALUE *
302rb_ary_ptr_use_start(VALUE ary)
303{
304#if ARRAY_DEBUG
305 FL_SET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
306#endif
307 return (VALUE *)RARRAY_CONST_PTR(ary);
308}
309
310void
311rb_ary_ptr_use_end(VALUE ary)
312{
313#if ARRAY_DEBUG
314 FL_UNSET_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
315#endif
316}
317
318void
319rb_mem_clear(VALUE *mem, long size)
320{
321 while (size--) {
322 *mem++ = Qnil;
323 }
324}
325
326static void
327ary_mem_clear(VALUE ary, long beg, long size)
328{
330 rb_mem_clear(ptr + beg, size);
331 });
332}
333
334static inline void
335memfill(register VALUE *mem, register long size, register VALUE val)
336{
337 while (size--) {
338 *mem++ = val;
339 }
340}
341
342static void
343ary_memfill(VALUE ary, long beg, long size, VALUE val)
344{
346 memfill(ptr + beg, size, val);
348 });
349}
350
351static void
352ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
353{
354 RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary));
355
356 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
357 rb_gc_writebarrier_remember(buff_owner_ary);
359 MEMCPY(ptr+beg, argv, VALUE, argc);
360 });
361 }
362 else {
363 int i;
365 for (i=0; i<argc; i++) {
366 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
367 }
368 });
369 }
370}
371
372static void
373ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
374{
375 ary_memcpy0(ary, beg, argc, argv, ary);
376}
377
378static VALUE *
379ary_heap_alloc_buffer(size_t capa)
380{
381 return ALLOC_N(VALUE, capa);
382}
383
384static void
385ary_heap_free_ptr(VALUE ary, const VALUE *ptr, long size)
386{
387 ruby_xfree_sized((void *)ptr, size);
388}
389
390static void
391ary_heap_free(VALUE ary)
392{
393 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
394}
395
396static size_t
397ary_heap_realloc(VALUE ary, size_t new_capa)
398{
400 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, ARY_HEAP_CAPA(ary));
401 ary_verify(ary);
402
403 return new_capa;
404}
405
406void
407rb_ary_make_embedded(VALUE ary)
408{
409 RUBY_ASSERT(rb_ary_embeddable_p(ary));
410 if (!ARY_EMBED_P(ary)) {
411 const VALUE *buf = ARY_HEAP_PTR(ary);
412 long len = ARY_HEAP_LEN(ary);
413 long capa = ARY_HEAP_CAPA(ary);
414
415 FL_SET_EMBED(ary);
416 ARY_SET_EMBED_LEN(ary, len);
417
418 MEMCPY((void *)ARY_EMBED_PTR(ary), (void *)buf, VALUE, len);
419
420 ary_heap_free_ptr(ary, buf, capa * sizeof(VALUE));
421 }
422}
423
424static void
425ary_resize_capa(VALUE ary, long capacity)
426{
427 RUBY_ASSERT(RARRAY_LEN(ary) <= capacity);
429 RUBY_ASSERT(!ARY_SHARED_P(ary));
430
431 if (capacity > ary_embed_capa(ary)) {
432 size_t new_capa = capacity;
433 if (ARY_EMBED_P(ary)) {
434 long len = ARY_EMBED_LEN(ary);
435 VALUE *ptr = ary_heap_alloc_buffer(capacity);
436
437 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
438 FL_UNSET_EMBED(ary);
439 ARY_SET_PTR(ary, ptr);
440 ARY_SET_HEAP_LEN(ary, len);
441 }
442 else {
443 new_capa = ary_heap_realloc(ary, capacity);
444 }
445 ARY_SET_CAPA(ary, new_capa);
446 }
447 else {
448 if (!ARY_EMBED_P(ary)) {
449 long len = ARY_HEAP_LEN(ary);
450 long old_capa = ARY_HEAP_CAPA(ary);
451 const VALUE *ptr = ARY_HEAP_PTR(ary);
452
453 if (len > capacity) len = capacity;
454 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
455 ary_heap_free_ptr(ary, ptr, old_capa * sizeof(VALUE));
456
457 FL_SET_EMBED(ary);
458 ARY_SET_LEN(ary, len);
459 }
460 }
461
462 ary_verify(ary);
463}
464
465static inline void
466ary_shrink_capa(VALUE ary)
467{
468 long capacity = ARY_HEAP_LEN(ary);
469 long old_capa = ARY_HEAP_CAPA(ary);
470 RUBY_ASSERT(!ARY_SHARED_P(ary));
471 RUBY_ASSERT(old_capa >= capacity);
472 if (old_capa > capacity) {
473 size_t new_capa = ary_heap_realloc(ary, capacity);
474 ARY_SET_CAPA(ary, new_capa);
475 }
476
477 ary_verify(ary);
478}
479
480static void
481ary_double_capa(VALUE ary, long min)
482{
483 long new_capa = ARY_CAPA(ary) / 2;
484
485 if (new_capa < ARY_DEFAULT_SIZE) {
486 new_capa = ARY_DEFAULT_SIZE;
487 }
488 if (new_capa >= ARY_MAX_SIZE - min) {
489 new_capa = (ARY_MAX_SIZE - min) / 2;
490 }
491 new_capa += min;
492 ary_resize_capa(ary, new_capa);
493
494 ary_verify(ary);
495}
496
497static void
498rb_ary_decrement_share(VALUE shared_root)
499{
500 if (!OBJ_FROZEN(shared_root)) {
501 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
502 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
503 }
504}
505
506static void
507rb_ary_unshare(VALUE ary)
508{
509 VALUE shared_root = ARY_SHARED_ROOT(ary);
510 rb_ary_decrement_share(shared_root);
511 FL_UNSET_SHARED(ary);
512}
513
514static void
515rb_ary_reset(VALUE ary)
516{
517 if (ARY_OWNS_HEAP_P(ary)) {
518 ary_heap_free(ary);
519 }
520 else if (ARY_SHARED_P(ary)) {
521 rb_ary_unshare(ary);
522 }
523
524 FL_SET_EMBED(ary);
525 ARY_SET_EMBED_LEN(ary, 0);
526}
527
528static VALUE
529rb_ary_increment_share(VALUE shared_root)
530{
531 if (!OBJ_FROZEN(shared_root)) {
532 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
533 RUBY_ASSERT(num >= 0);
534 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
535 }
536 return shared_root;
537}
538
539static void
540rb_ary_set_shared(VALUE ary, VALUE shared_root)
541{
542 RUBY_ASSERT(!ARY_EMBED_P(ary));
544 RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root));
545
546 rb_ary_increment_share(shared_root);
547 FL_SET_SHARED(ary);
548 RB_OBJ_WRITE(ary, &RARRAY(ary)->as.heap.aux.shared_root, shared_root);
549
550 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
551}
552
553static inline void
554rb_ary_modify_check(VALUE ary)
555{
556 RUBY_ASSERT(ruby_thread_has_gvl_p());
557
558 rb_check_frozen(ary);
559 ary_verify(ary);
560}
561
562void
563rb_ary_cancel_sharing(VALUE ary)
564{
565 if (ARY_SHARED_P(ary)) {
566 long shared_len, len = RARRAY_LEN(ary);
567 VALUE shared_root = ARY_SHARED_ROOT(ary);
568
569 ary_verify(shared_root);
570
571 if (len <= ary_embed_capa(ary)) {
572 const VALUE *ptr = ARY_HEAP_PTR(ary);
573 FL_UNSET_SHARED(ary);
574 FL_SET_EMBED(ary);
575 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
576 rb_ary_decrement_share(shared_root);
577 ARY_SET_EMBED_LEN(ary, len);
578 }
579 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
581 FL_UNSET_SHARED(ary);
582 ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared_root));
583 ARY_SET_CAPA(ary, shared_len);
585 MEMMOVE(ptr, ptr+shift, VALUE, len);
586 });
587 FL_SET_EMBED(shared_root);
588 rb_ary_decrement_share(shared_root);
589 }
590 else {
591 VALUE *ptr = ary_heap_alloc_buffer(len);
592 MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
593 rb_ary_unshare(ary);
594 ARY_SET_CAPA_FORCE(ary, len);
595 ARY_SET_PTR_FORCE(ary, ptr);
596 }
597
598 rb_gc_writebarrier_remember(ary);
599 }
600 ary_verify(ary);
601}
602
603void
605{
606 rb_ary_modify_check(ary);
607 rb_ary_cancel_sharing(ary);
608}
609
610static VALUE
611ary_ensure_room_for_push(VALUE ary, long add_len)
612{
613 long old_len = RARRAY_LEN(ary);
614 long new_len = old_len + add_len;
615 long capa;
616
617 if (old_len > ARY_MAX_SIZE - add_len) {
618 rb_raise(rb_eIndexError, "index %ld too big", new_len);
619 }
620 if (ARY_SHARED_P(ary)) {
621 if (new_len > ary_embed_capa(ary)) {
622 VALUE shared_root = ARY_SHARED_ROOT(ary);
623 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
624 if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
625 rb_ary_modify_check(ary);
626
627 ary_verify(ary);
628 ary_verify(shared_root);
629 return shared_root;
630 }
631 else {
632 /* if array is shared, then it is likely it participate in push/shift pattern */
634 capa = ARY_CAPA(ary);
635 if (new_len > capa - (capa >> 6)) {
636 ary_double_capa(ary, new_len);
637 }
638 ary_verify(ary);
639 return ary;
640 }
641 }
642 }
643 ary_verify(ary);
645 }
646 else {
647 rb_ary_modify_check(ary);
648 }
649 capa = ARY_CAPA(ary);
650 if (new_len > capa) {
651 ary_double_capa(ary, new_len);
652 }
653
654 ary_verify(ary);
655 return ary;
656}
657
658/*
659 * call-seq:
660 * freeze -> self
661 *
662 * Freezes +self+, preventing further modifications;
663 * see {Frozen Objects}[rdoc-ref:frozen_objects.md].
664 */
665
666VALUE
668{
670
671 if (OBJ_FROZEN(ary)) return ary;
672
673 if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) {
674 ary_shrink_capa(ary);
675 }
676
677 return rb_obj_freeze(ary);
678}
679
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
686 differ. */
687VALUE
689{
690 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
691 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
692 ARY_SHARED_ROOT(ary1) == ARY_SHARED_ROOT(ary2) &&
693 ARY_HEAP_LEN(ary1) == ARY_HEAP_LEN(ary2)) {
694 return Qtrue;
695 }
696 return Qfalse;
697}
698
699static VALUE
700ary_alloc_embed(VALUE klass, long capa)
701{
702 size_t size = ary_embed_size(capa);
703 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
704 /* Created array is:
705 * FL_SET_EMBED((VALUE)ary);
706 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
707 */
708 return rb_newobj_of(klass, T_ARRAY | RARRAY_EMBED_FLAG, size);
709}
710
711static VALUE
712ary_alloc_heap(VALUE klass)
713{
714 NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY, sizeof(struct RArray));
715
716 ary->as.heap.len = 0;
717 ary->as.heap.aux.capa = 0;
718 ary->as.heap.ptr = NULL;
719
720 return (VALUE)ary;
721}
722
723static VALUE
724empty_ary_alloc(VALUE klass)
725{
726 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
727 return ary_alloc_embed(klass, 0);
728}
729
730static VALUE
731ary_new(VALUE klass, long capa)
732{
733 RUBY_ASSERT(ruby_thread_has_gvl_p());
734
735 VALUE ary;
736
737 if (capa < 0) {
738 rb_raise(rb_eArgError, "negative array size (or size too big)");
739 }
740 if (capa > ARY_MAX_SIZE) {
741 rb_raise(rb_eArgError, "array size too big");
742 }
743
744 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
745
746 if (ary_embeddable_p(capa)) {
747 ary = ary_alloc_embed(klass, capa);
748 }
749 else {
750 ary = ary_alloc_heap(klass);
751 ARY_SET_CAPA(ary, capa);
752 RUBY_ASSERT(!ARY_EMBED_P(ary));
753
754 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
755 ARY_SET_HEAP_LEN(ary, 0);
756 }
757
758 return ary;
759}
760
761VALUE
763{
764 return ary_new(rb_cArray, capa);
765}
766
767VALUE
768rb_ary_new(void)
769{
770 return rb_ary_new_capa(0);
771}
772
773VALUE
774(rb_ary_new_from_args)(long n, ...)
775{
776 va_list ar;
777 VALUE ary;
778 long i;
779
780 ary = rb_ary_new2(n);
781
782 va_start(ar, n);
783 for (i=0; i<n; i++) {
784 ARY_SET(ary, i, va_arg(ar, VALUE));
785 }
786 va_end(ar);
787
788 ARY_SET_LEN(ary, n);
789 return ary;
790}
791
792VALUE
793rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
794{
795 VALUE ary;
796
797 ary = ary_new(klass, n);
798 if (n > 0 && elts) {
799 ary_memcpy(ary, 0, n, elts);
800 ARY_SET_LEN(ary, n);
801 }
802
803 return ary;
804}
805
806VALUE
807rb_ary_new_from_values(long n, const VALUE *elts)
808{
809 return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
810}
811
812static VALUE
813ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa)
814{
815 size_t size = ary_embed_size(capa);
816 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
817 /* Created array is:
818 * FL_SET_EMBED((VALUE)ary);
819 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
820 */
821 return rb_ec_newobj_of(ec, klass, T_ARRAY | RARRAY_EMBED_FLAG, size);
822}
823
824static VALUE
825ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
826{
827 VALUE ary = rb_ec_newobj_of(ec, klass, T_ARRAY, sizeof(struct RArray));
828 RARRAY(ary)->as.heap.len = 0;
829 RARRAY(ary)->as.heap.aux.capa = 0;
830 RARRAY(ary)->as.heap.ptr = NULL;
831 return ary;
832}
833
834static VALUE
835ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
836{
837 VALUE ary;
838
839 if (capa < 0) {
840 rb_raise(rb_eArgError, "negative array size (or size too big)");
841 }
842 if (capa > ARY_MAX_SIZE) {
843 rb_raise(rb_eArgError, "array size too big");
844 }
845
846 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
847
848 if (ary_embeddable_p(capa)) {
849 ary = ec_ary_alloc_embed(ec, klass, capa);
850 }
851 else {
852 ary = ec_ary_alloc_heap(ec, klass);
853 ARY_SET_CAPA(ary, capa);
854 RUBY_ASSERT(!ARY_EMBED_P(ary));
855
856 ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa));
857 ARY_SET_HEAP_LEN(ary, 0);
858 }
859
860 return ary;
861}
862
863VALUE
864rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
865{
866 VALUE ary;
867
868 ary = ec_ary_new(ec, rb_cArray, n);
869 if (n > 0 && elts) {
870 ary_memcpy(ary, 0, n, elts);
871 ARY_SET_LEN(ary, n);
872 }
873
874 return ary;
875}
876
877VALUE
879{
880 VALUE ary = ary_new(0, capa);
881 return ary;
882}
883
884VALUE
885rb_ary_hidden_new_fill(long capa)
886{
888 ary_memfill(ary, 0, capa, Qnil);
889 ARY_SET_LEN(ary, capa);
890 return ary;
891}
892
893void
895{
896 if (ARY_OWNS_HEAP_P(ary)) {
897 if (USE_DEBUG_COUNTER &&
898 !ARY_SHARED_ROOT_P(ary) &&
899 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
900 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
901 }
902
903 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
904 ary_heap_free(ary);
905 }
906 else {
907 RB_DEBUG_COUNTER_INC(obj_ary_embed);
908 }
909
910 if (ARY_SHARED_P(ary)) {
911 RB_DEBUG_COUNTER_INC(obj_ary_shared);
912 }
913 if (ARY_SHARED_ROOT_P(ary) && ARY_SHARED_ROOT_OCCUPIED(ary)) {
914 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
915 }
916}
917
918static VALUE fake_ary_flags;
919
920static VALUE
921init_fake_ary_flags(void)
922{
923 struct RArray fake_ary = {0};
924 fake_ary.basic.flags = T_ARRAY | RARRAY_FAKEARY;
925 VALUE ary = (VALUE)&fake_ary;
926 RBASIC_SET_FULL_SHAPE_ID(ary, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER);
928 return fake_ary.basic.flags;
929}
930
931VALUE
932rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len)
933{
934 fake_ary->basic.flags = fake_ary_flags;
935 RBASIC_CLEAR_CLASS((VALUE)fake_ary);
936
937 // bypass frozen checks
938 fake_ary->as.heap.ptr = list;
939 fake_ary->as.heap.len = len;
940 fake_ary->as.heap.aux.capa = len;
941 return (VALUE)fake_ary;
942}
943
944size_t
945rb_ary_memsize(VALUE ary)
946{
947 if (ARY_OWNS_HEAP_P(ary)) {
948 return ARY_CAPA(ary) * sizeof(VALUE);
949 }
950 else {
951 return 0;
952 }
953}
954
955static VALUE
956ary_make_shared(VALUE ary)
957{
958 ary_verify(ary);
959
960 if (ARY_SHARED_P(ary)) {
961 return ARY_SHARED_ROOT(ary);
962 }
963 else if (ARY_SHARED_ROOT_P(ary)) {
964 return ary;
965 }
966 else if (OBJ_FROZEN(ary)) {
967 return ary;
968 }
969 else {
970 long capa = ARY_CAPA(ary);
971 long len = RARRAY_LEN(ary);
972
973 /* Shared roots cannot be embedded because the reference count
974 * (refcnt) is stored in as.heap.aux.capa. */
975 VALUE shared = ary_alloc_heap(0);
976 FL_SET_SHARED_ROOT(shared);
977
978 if (ARY_EMBED_P(ary)) {
979 VALUE *ptr = ary_heap_alloc_buffer(capa);
980 ARY_SET_PTR(shared, ptr);
981 ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary));
982
983 FL_UNSET_EMBED(ary);
984 ARY_SET_HEAP_LEN(ary, len);
985 ARY_SET_PTR(ary, ptr);
986 }
987 else {
988 ARY_SET_PTR(shared, RARRAY_CONST_PTR(ary));
989 }
990
991 ARY_SET_LEN(shared, capa);
992 ary_mem_clear(shared, len, capa - len);
993 rb_ary_set_shared(ary, shared);
994
995 ary_verify(shared);
996 ary_verify(ary);
997
998 return shared;
999 }
1000}
1001
1002static VALUE
1003ary_make_substitution(VALUE ary)
1004{
1005 long len = RARRAY_LEN(ary);
1006
1007 if (ary_embeddable_p(len)) {
1008 VALUE subst = rb_ary_new_capa(len);
1009 RUBY_ASSERT(ARY_EMBED_P(subst));
1010
1011 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
1012 ARY_SET_EMBED_LEN(subst, len);
1013 return subst;
1014 }
1015 else {
1016 return rb_ary_increment_share(ary_make_shared(ary));
1017 }
1018}
1019
1020VALUE
1021rb_assoc_new(VALUE car, VALUE cdr)
1022{
1023 return rb_ary_new3(2, car, cdr);
1024}
1025
1026VALUE
1027rb_to_array_type(VALUE ary)
1028{
1029 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1030}
1031#define to_ary rb_to_array_type
1032
1033VALUE
1035{
1036 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
1037}
1038
1039VALUE
1040rb_check_to_array(VALUE ary)
1041{
1042 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1043}
1044
1045VALUE
1046rb_to_array(VALUE ary)
1047{
1048 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
1049}
1050
1051/*
1052 * call-seq:
1053 * Array.try_convert(object) -> object, new_array, or nil
1054 *
1055 * Attempts to return an array, based on the given +object+.
1056 *
1057 * If +object+ is an array, returns +object+.
1058 *
1059 * Otherwise if +object+ responds to <tt>:to_ary</tt>.
1060 * calls <tt>object.to_ary</tt>:
1061 * if the return value is an array or +nil+, returns that value;
1062 * if not, raises TypeError.
1063 *
1064 * Otherwise returns +nil+.
1065 *
1066 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1067 */
1068
1069static VALUE
1070rb_ary_s_try_convert(VALUE dummy, VALUE ary)
1071{
1072 return rb_check_array_type(ary);
1073}
1074
1075/* :nodoc: */
1076static VALUE
1077rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
1078{
1079 VALUE ary;
1080
1081 if (klass == rb_cArray) {
1082 long size = 0;
1083 if (argc > 0 && FIXNUM_P(argv[0])) {
1084 size = FIX2LONG(argv[0]);
1085 if (size < 0) size = 0;
1086 }
1087
1088 ary = ary_new(klass, size);
1089
1090 rb_obj_call_init_kw(ary, argc, argv, RB_PASS_CALLED_KEYWORDS);
1091 }
1092 else {
1093 ary = rb_class_new_instance_pass_kw(argc, argv, klass);
1094 }
1095
1096 return ary;
1097}
1098
1099/*
1100 * call-seq:
1101 * Array.new -> new_empty_array
1102 * Array.new(array) -> new_array
1103 * Array.new(size, default_value = nil) -> new_array
1104 * Array.new(size = 0) {|index| ... } -> new_array
1105 *
1106 * Returns a new array.
1107 *
1108 * With no block and no argument given, returns a new empty array:
1109 *
1110 * Array.new # => []
1111 *
1112 * With no block and array argument given, returns a new array with the same elements:
1113 *
1114 * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
1115 *
1116 * With no block and integer argument given, returns a new array containing
1117 * that many instances of the given +default_value+:
1118 *
1119 * Array.new(0) # => []
1120 * Array.new(3) # => [nil, nil, nil]
1121 * Array.new(2, 3) # => [3, 3]
1122 *
1123 * With a block given, returns an array of the given +size+;
1124 * calls the block with each +index+ in the range <tt>(0...size)</tt>;
1125 * the element at that +index+ in the returned array is the blocks return value:
1126 *
1127 * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
1128 *
1129 * A common pitfall for new Rubyists is providing an expression as +default_value+:
1130 *
1131 * array = Array.new(2, {})
1132 * array # => [{}, {}]
1133 * array[0][:a] = 1
1134 * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
1135 *
1136 * If you want the elements of the array to be distinct, you should pass a block:
1137 *
1138 * array = Array.new(2) { {} }
1139 * array # => [{}, {}]
1140 * array[0][:a] = 1
1141 * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
1142 *
1143 * Raises TypeError if the first argument is not either an array
1144 * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
1145 * Raises ArgumentError if the first argument is a negative integer.
1146 *
1147 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1148 */
1149
1150static VALUE
1151rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1152{
1153 long len;
1154 VALUE size, val;
1155
1157 if (argc == 0) {
1158 rb_ary_reset(ary);
1159 RUBY_ASSERT(ARY_EMBED_P(ary));
1160 RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
1161 if (rb_block_given_p()) {
1162 rb_warning("given block not used");
1163 }
1164 return ary;
1165 }
1166 rb_scan_args(argc, argv, "02", &size, &val);
1167 if (argc == 1 && !FIXNUM_P(size)) {
1168 val = rb_check_array_type(size);
1169 if (!NIL_P(val)) {
1170 rb_ary_replace(ary, val);
1171 return ary;
1172 }
1173 }
1174
1175 len = NUM2LONG(size);
1176 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1177 if (len < 0) {
1178 rb_raise(rb_eArgError, "negative array size");
1179 }
1180 if (len > ARY_MAX_SIZE) {
1181 rb_raise(rb_eArgError, "array size too big");
1182 }
1183 /* recheck after argument conversion */
1185 ARY_SET_LEN(ary, 0);
1186 ary_resize_capa(ary, len);
1187 if (rb_block_given_p()) {
1188 long i;
1189
1190 if (argc == 2) {
1191 rb_warn("block supersedes default value argument");
1192 }
1193 for (i=0; i<len; i++) {
1195 ARY_SET_LEN(ary, i + 1);
1196 }
1197 }
1198 else {
1199 ary_memfill(ary, 0, len, val);
1200 ARY_SET_LEN(ary, len);
1201 }
1202 return ary;
1203}
1204
1205/*
1206 * Returns a new array, populated with the given objects:
1207 *
1208 * Array[1, 'a', /^A/] # => [1, "a", /^A/]
1209 * Array[] # => []
1210 * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
1211 *
1212 * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
1213 */
1214
1215static VALUE
1216rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1217{
1218 VALUE ary = ary_new(klass, argc);
1219 if (argc > 0 && argv) {
1220 ary_memcpy(ary, 0, argc, argv);
1221 ARY_SET_LEN(ary, argc);
1222 }
1223
1224 return ary;
1225}
1226
1227void
1228rb_ary_store(VALUE ary, long idx, VALUE val)
1229{
1230 long len = RARRAY_LEN(ary);
1231
1232 if (idx < 0) {
1233 idx += len;
1234 if (idx < 0) {
1235 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1236 idx - len, -len);
1237 }
1238 }
1239 else if (idx >= ARY_MAX_SIZE) {
1240 rb_raise(rb_eIndexError, "index %ld too big", idx);
1241 }
1242
1244 if (idx >= ARY_CAPA(ary)) {
1245 ary_double_capa(ary, idx);
1246 }
1247 if (idx > len) {
1248 ary_mem_clear(ary, len, idx - len + 1);
1249 }
1250
1251 if (idx >= len) {
1252 ARY_SET_LEN(ary, idx + 1);
1253 }
1254 ARY_SET(ary, idx, val);
1255}
1256
1257static VALUE
1258ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1259{
1260 RUBY_ASSERT(offset >= 0);
1261 RUBY_ASSERT(len >= 0);
1262 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1263
1264 VALUE result = ary_alloc_heap(klass);
1265 size_t embed_capa = ary_embed_capa(result);
1266 if ((size_t)len <= embed_capa) {
1267 FL_SET_EMBED(result);
1268 ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
1269 ARY_SET_EMBED_LEN(result, len);
1270 }
1271 else {
1272 VALUE shared = ary_make_shared(ary);
1273
1274 /* The ary_make_shared call may allocate, which can trigger a GC
1275 * compaction. This can cause the array to be embedded because it has
1276 * a length of 0. */
1277 FL_UNSET_EMBED(result);
1278
1279 ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
1280 ARY_SET_LEN(result, RARRAY_LEN(ary));
1281 rb_ary_set_shared(result, shared);
1282
1283 ARY_INCREASE_PTR(result, offset);
1284 ARY_SET_LEN(result, len);
1285
1286 ary_verify(shared);
1287 }
1288
1289 ary_verify(result);
1290 return result;
1291}
1292
1293static VALUE
1294ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
1295{
1296 RUBY_ASSERT(offset >= 0);
1297 RUBY_ASSERT(len >= 0);
1298 RUBY_ASSERT(offset+len <= RARRAY_LEN(ary));
1299 RUBY_ASSERT(step != 0);
1300
1301 const long orig_len = len;
1302
1303 if (step > 0 && step >= len) {
1304 VALUE result = ary_new(klass, 1);
1305 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1306 const VALUE *values = RARRAY_CONST_PTR(ary);
1307
1308 RB_OBJ_WRITE(result, ptr, values[offset]);
1309 ARY_SET_EMBED_LEN(result, 1);
1310 return result;
1311 }
1312 else if (step < 0 && step < -len) {
1313 step = -len;
1314 }
1315
1316 long ustep = (step < 0) ? -step : step;
1317 len = roomof(len, ustep);
1318
1319 long i;
1320 long j = offset + ((step > 0) ? 0 : (orig_len - 1));
1321
1322 VALUE result = ary_new(klass, len);
1323 if (ARY_EMBED_P(result)) {
1324 VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
1325 const VALUE *values = RARRAY_CONST_PTR(ary);
1326
1327 for (i = 0; i < len; ++i) {
1328 RB_OBJ_WRITE(result, ptr+i, values[j]);
1329 j += step;
1330 }
1331 ARY_SET_EMBED_LEN(result, len);
1332 }
1333 else {
1334 const VALUE *values = RARRAY_CONST_PTR(ary);
1335
1336 RARRAY_PTR_USE(result, ptr, {
1337 for (i = 0; i < len; ++i) {
1338 RB_OBJ_WRITE(result, ptr+i, values[j]);
1339 j += step;
1340 }
1341 });
1342 ARY_SET_LEN(result, len);
1343 }
1344
1345 return result;
1346}
1347
1348static VALUE
1349ary_make_shared_copy(VALUE ary)
1350{
1351 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
1352}
1353
1354static VALUE
1355ary_make_hidden_shared_copy(VALUE ary)
1356{
1357 return ary_make_partial(ary, 0, 0, RARRAY_LEN(ary));
1358}
1359
1360enum ary_take_pos_flags
1361{
1362 ARY_TAKE_FIRST = 0,
1363 ARY_TAKE_LAST = 1
1364};
1365
1366static VALUE
1367ary_take_first_or_last_n(VALUE ary, long n, enum ary_take_pos_flags last)
1368{
1369 long len = RARRAY_LEN(ary);
1370 long offset = 0;
1371
1372 if (n > len) {
1373 n = len;
1374 }
1375 else if (n < 0) {
1376 rb_raise(rb_eArgError, "negative array size");
1377 }
1378 if (last) {
1379 offset = len - n;
1380 }
1381 return ary_make_partial(ary, rb_cArray, offset, n);
1382}
1383
1384static VALUE
1385ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1386{
1387 argc = rb_check_arity(argc, 0, 1);
1388 /* the case optional argument is omitted should be handled in
1389 * callers of this function. if another arity case is added,
1390 * this arity check needs to rewrite. */
1391 RUBY_ASSERT_ALWAYS(argc == 1);
1392 return ary_take_first_or_last_n(ary, NUM2LONG(argv[0]), last);
1393}
1394
1395/*
1396 * call-seq:
1397 * self << object -> self
1398 *
1399 * Appends +object+ as the last element in +self+; returns +self+:
1400 *
1401 * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
1402 *
1403 * Appends +object+ as a single element, even if it is another array:
1404 *
1405 * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
1406 *
1407 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1408 */
1409
1410VALUE
1412{
1413 long idx = RARRAY_LEN((ary_verify(ary), ary));
1414 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1416 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1417 });
1418 ARY_SET_LEN(ary, idx + 1);
1419 ary_verify(ary);
1420 return ary;
1421}
1422
1423VALUE
1424rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1425{
1426 long oldlen = RARRAY_LEN(ary);
1427 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1428 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1429 ARY_SET_LEN(ary, oldlen + len);
1430 return ary;
1431}
1432
1433/*
1434 * call-seq:
1435 * push(*objects) -> self
1436 * append(*objects) -> self
1437 *
1438 * Appends each argument in +objects+ to +self+; returns +self+:
1439 *
1440 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1441 * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
1442 *
1443 * Appends each argument as a single element, even if it is another array:
1444 *
1445 * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
1446 a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
1447 *
1448 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1449 */
1450
1451static VALUE
1452rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1453{
1454 return rb_ary_cat(ary, argv, argc);
1455}
1456
1457VALUE
1459{
1460 long n;
1461 rb_ary_modify_check(ary);
1462 n = RARRAY_LEN(ary);
1463 if (n == 0) return Qnil;
1464 if (ARY_OWNS_HEAP_P(ary) &&
1465 n * 3 < ARY_CAPA(ary) &&
1466 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
1467 {
1468 ary_resize_capa(ary, n * 2);
1469 }
1470
1471 VALUE obj = RARRAY_AREF(ary, n - 1);
1472
1473 ARY_SET_LEN(ary, n - 1);
1474 ary_verify(ary);
1475 return obj;
1476}
1477
1478/*
1479 * call-seq:
1480 * pop -> object or nil
1481 * pop(count) -> new_array
1482 *
1483 * Removes and returns trailing elements of +self+.
1484 *
1485 * With no argument given, removes and returns the last element, if available;
1486 * otherwise returns +nil+:
1487 *
1488 * a = [:foo, 'bar', 2]
1489 * a.pop # => 2
1490 * a # => [:foo, "bar"]
1491 * [].pop # => nil
1492 *
1493 * With non-negative integer argument +count+ given,
1494 * returns a new array containing the trailing +count+ elements of +self+, as available:
1495 *
1496 * a = [:foo, 'bar', 2]
1497 * a.pop(2) # => ["bar", 2]
1498 * a # => [:foo]
1499 *
1500 * a = [:foo, 'bar', 2]
1501 * a.pop(50) # => [:foo, "bar", 2]
1502 * a # => []
1503 *
1504 * Related: Array#push;
1505 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1506 */
1507
1508static VALUE
1509rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1510{
1511 VALUE result;
1512
1513 if (argc == 0) {
1514 return rb_ary_pop(ary);
1515 }
1516
1517 rb_ary_modify_check(ary);
1518 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1519 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1520 ary_verify(ary);
1521 return result;
1522}
1523
1524VALUE
1526{
1527 VALUE top;
1528 long len = RARRAY_LEN(ary);
1529
1530 if (len == 0) {
1531 rb_ary_modify_check(ary);
1532 return Qnil;
1533 }
1534
1535 top = RARRAY_AREF(ary, 0);
1536
1537 rb_ary_behead(ary, 1);
1538
1539 return top;
1540}
1541
1542/*
1543 * call-seq:
1544 * shift -> object or nil
1545 * shift(count) -> new_array or nil
1546 *
1547 * Removes and returns leading elements from +self+.
1548 *
1549 * With no argument, removes and returns one element, if available,
1550 * or +nil+ otherwise:
1551 *
1552 * a = [0, 1, 2, 3]
1553 * a.shift # => 0
1554 * a # => [1, 2, 3]
1555 * [].shift # => nil
1556 *
1557 * With non-negative numeric argument +count+ given,
1558 * removes and returns the first +count+ elements:
1559 *
1560 * a = [0, 1, 2, 3]
1561 * a.shift(2) # => [0, 1]
1562 * a # => [2, 3]
1563 * a.shift(1.1) # => [2]
1564 * a # => [3]
1565 * a.shift(0) # => []
1566 * a # => [3]
1567 *
1568 * If +count+ is large,
1569 * removes and returns all elements:
1570 *
1571 * a = [0, 1, 2, 3]
1572 * a.shift(50) # => [0, 1, 2, 3]
1573 * a # => []
1574 *
1575 * If +self+ is empty, returns a new empty array.
1576 *
1577 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
1578 */
1579
1580static VALUE
1581rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1582{
1583 VALUE result;
1584 long n;
1585
1586 if (argc == 0) {
1587 return rb_ary_shift(ary);
1588 }
1589
1590 rb_ary_modify_check(ary);
1591 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1592 n = RARRAY_LEN(result);
1593 rb_ary_behead(ary,n);
1594
1595 return result;
1596}
1597
1598VALUE
1599rb_ary_behead(VALUE ary, long n)
1600{
1601 if (n <= 0) {
1602 return ary;
1603 }
1604
1605 rb_ary_modify_check(ary);
1606
1607 if (!ARY_SHARED_P(ary)) {
1608 if (ARY_EMBED_P(ary) || RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
1610 MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary) - n);
1611 }); /* WB: no new reference */
1612 ARY_INCREASE_LEN(ary, -n);
1613 ary_verify(ary);
1614 return ary;
1615 }
1616
1617 ary_mem_clear(ary, 0, n);
1618 ary_make_shared(ary);
1619 }
1620 else if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
1621 ary_mem_clear(ary, 0, n);
1622 }
1623
1624 ARY_INCREASE_PTR(ary, n);
1625 ARY_INCREASE_LEN(ary, -n);
1626 ary_verify(ary);
1627
1628 return ary;
1629}
1630
1631static VALUE
1632make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
1633{
1634 if (head - sharedp < argc) {
1635 long room = capa - len - argc;
1636
1637 room -= room >> 4;
1638 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1639 head = sharedp + argc + room;
1640 }
1641 ARY_SET_PTR(ary, head - argc);
1642 RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
1643
1644 ary_verify(ary);
1645 return ARY_SHARED_ROOT(ary);
1646}
1647
1648static VALUE
1649ary_modify_for_unshift(VALUE ary, int argc)
1650{
1651 long len = RARRAY_LEN(ary);
1652 long new_len = len + argc;
1653 long capa;
1654 const VALUE *head, *sharedp;
1655
1657 capa = ARY_CAPA(ary);
1658 if (capa - (capa >> 6) <= new_len) {
1659 ary_double_capa(ary, new_len);
1660 }
1661
1662 /* use shared array for big "queues" */
1663 if (new_len > ARY_DEFAULT_SIZE * 4 && !ARY_EMBED_P(ary)) {
1664 ary_verify(ary);
1665
1666 /* make a room for unshifted items */
1667 capa = ARY_CAPA(ary);
1668 ary_make_shared(ary);
1669
1670 head = sharedp = RARRAY_CONST_PTR(ary);
1671 return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
1672 }
1673 else {
1674 /* sliding items */
1676 MEMMOVE(ptr + argc, ptr, VALUE, len);
1677 });
1678
1679 ary_verify(ary);
1680 return ary;
1681 }
1682}
1683
1684static VALUE
1685ary_ensure_room_for_unshift(VALUE ary, int argc)
1686{
1687 long len = RARRAY_LEN(ary);
1688 long new_len = len + argc;
1689
1690 if (len > ARY_MAX_SIZE - argc) {
1691 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1692 }
1693 else if (! ARY_SHARED_P(ary)) {
1694 return ary_modify_for_unshift(ary, argc);
1695 }
1696 else {
1697 VALUE shared_root = ARY_SHARED_ROOT(ary);
1698 long capa = RARRAY_LEN(shared_root);
1699
1700 if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
1701 return ary_modify_for_unshift(ary, argc);
1702 }
1703 else if (new_len > capa) {
1704 return ary_modify_for_unshift(ary, argc);
1705 }
1706 else {
1707 const VALUE * head = RARRAY_CONST_PTR(ary);
1708 void *sharedp = (void *)RARRAY_CONST_PTR(shared_root);
1709
1710 rb_ary_modify_check(ary);
1711 return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
1712 }
1713 }
1714}
1715
1716/*
1717 * call-seq:
1718 * unshift(*objects) -> self
1719 * prepend(*objects) -> self
1720 *
1721 * Prepends the given +objects+ to +self+:
1722 *
1723 * a = [:foo, 'bar', 2]
1724 * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
1725 *
1726 * Related: Array#shift;
1727 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
1728 */
1729
1730VALUE
1731rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1732{
1733 long len = RARRAY_LEN(ary);
1734 VALUE target_ary;
1735
1736 if (argc == 0) {
1737 rb_ary_modify_check(ary);
1738 return ary;
1739 }
1740
1741 target_ary = ary_ensure_room_for_unshift(ary, argc);
1742 ary_memcpy0(ary, 0, argc, argv, target_ary);
1743 ARY_SET_LEN(ary, len + argc);
1744 return ary;
1745}
1746
1747VALUE
1748rb_ary_unshift(VALUE ary, VALUE item)
1749{
1750 return rb_ary_unshift_m(1, &item, ary);
1751}
1752
1753/* faster version - use this if you don't need to treat negative offset */
1754static inline VALUE
1755rb_ary_elt(VALUE ary, long offset)
1756{
1757 long len = RARRAY_LEN(ary);
1758 if (len == 0) return Qnil;
1759 if (offset < 0 || len <= offset) {
1760 return Qnil;
1761 }
1762 return RARRAY_AREF(ary, offset);
1763}
1764
1765VALUE
1766rb_ary_entry(VALUE ary, long offset)
1767{
1768 return rb_ary_entry_internal(ary, offset);
1769}
1770
1771static long
1772ary_subseq_len(VALUE ary, long beg, long len)
1773{
1774 long alen = RARRAY_LEN(ary);
1775
1776 if (beg > alen) return -1;
1777 if (beg < 0 || len < 0) return -1;
1778
1779 if (alen < len || alen < beg + len) {
1780 len = alen - beg;
1781 }
1782 ASSUME(len >= 0);
1783 return len;
1784}
1785
1786VALUE
1787rb_ary_subseq(VALUE ary, long beg, long len)
1788{
1789 const VALUE klass = rb_cArray;
1790 len = ary_subseq_len(ary, beg, len);
1791 if (len < 0) return Qnil;
1792 if (len == 0) return ary_new(klass, 0);
1793 return ary_make_partial(ary, klass, beg, len);
1794}
1795
1796static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1797
1798/*
1799 * call-seq:
1800 * self[offset] -> object or nil
1801 * self[offset, size] -> object or nil
1802 * self[range] -> object or nil
1803 * self[aseq] -> object or nil
1804 *
1805 * Returns elements from +self+; does not modify +self+.
1806 *
1807 * In brief:
1808 *
1809 * a = [:foo, 'bar', 2]
1810 *
1811 * # Single argument offset: returns one element.
1812 * a[0] # => :foo # Zero-based index.
1813 * a[-1] # => 2 # Negative index counts backwards from end.
1814 *
1815 * # Arguments offset and size: returns an array.
1816 * a[1, 2] # => ["bar", 2]
1817 * a[-2, 2] # => ["bar", 2] # Negative offset counts backwards from end.
1818 *
1819 * # Single argument range: returns an array.
1820 * a[0..1] # => [:foo, "bar"]
1821 * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
1822 * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
1823 *
1824 * When a single integer argument +offset+ is given, returns the element at offset +offset+:
1825 *
1826 * a = [:foo, 'bar', 2]
1827 * a[0] # => :foo
1828 * a[2] # => 2
1829 * a # => [:foo, "bar", 2]
1830 *
1831 * If +offset+ is negative, counts backwards from the end of +self+:
1832 *
1833 * a = [:foo, 'bar', 2]
1834 * a[-1] # => 2
1835 * a[-2] # => "bar"
1836 *
1837 * If +index+ is out of range, returns +nil+.
1838 *
1839 * When two Integer arguments +offset+ and +size+ are given,
1840 * returns a new array of size +size+ containing successive elements beginning at offset +offset+:
1841 *
1842 * a = [:foo, 'bar', 2]
1843 * a[0, 2] # => [:foo, "bar"]
1844 * a[1, 2] # => ["bar", 2]
1845 *
1846 * If <tt>offset + size</tt> is greater than <tt>self.size</tt>,
1847 * returns all elements from offset +offset+ to the end:
1848 *
1849 * a = [:foo, 'bar', 2]
1850 * a[0, 4] # => [:foo, "bar", 2]
1851 * a[1, 3] # => ["bar", 2]
1852 * a[2, 2] # => [2]
1853 *
1854 * If <tt>offset == self.size</tt> and <tt>size >= 0</tt>,
1855 * returns a new empty array.
1856 *
1857 * If +size+ is negative, returns +nil+.
1858 *
1859 * When a single Range argument +range+ is given,
1860 * treats <tt>range.min</tt> as +offset+ above
1861 * and <tt>range.size</tt> as +size+ above:
1862 *
1863 * a = [:foo, 'bar', 2]
1864 * a[0..1] # => [:foo, "bar"]
1865 * a[1..2] # => ["bar", 2]
1866 *
1867 * Special case: If <tt>range.start == a.size</tt>, returns a new empty array.
1868 *
1869 * If <tt>range.end</tt> is negative, calculates the end index from the end:
1870 *
1871 * a = [:foo, 'bar', 2]
1872 * a[0..-1] # => [:foo, "bar", 2]
1873 * a[0..-2] # => [:foo, "bar"]
1874 * a[0..-3] # => [:foo]
1875 *
1876 * If <tt>range.start</tt> is negative, calculates the start index from the end:
1877 *
1878 * a = [:foo, 'bar', 2]
1879 * a[-1..2] # => [2]
1880 * a[-2..2] # => ["bar", 2]
1881 * a[-3..2] # => [:foo, "bar", 2]
1882 *
1883 * If <tt>range.start</tt> is larger than the array size, returns +nil+.
1884 *
1885 * a = [:foo, 'bar', 2]
1886 * a[4..1] # => nil
1887 * a[4..0] # => nil
1888 * a[4..-1] # => nil
1889 *
1890 * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
1891 * returns an array of elements corresponding to the indexes produced by
1892 * the sequence.
1893 *
1894 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1895 * a[(1..).step(2)] # => ["data1", "data2", "data3"]
1896 *
1897 * Unlike slicing with range, if the start or the end of the arithmetic sequence
1898 * is larger than array size, throws RangeError.
1899 *
1900 * a = ['--', 'data1', '--', 'data2', '--', 'data3']
1901 * a[(1..11).step(2)]
1902 * # RangeError (((1..11).step(2)) out of range)
1903 * a[(7..).step(2)]
1904 * # RangeError (((7..).step(2)) out of range)
1905 *
1906 * If given a single argument, and its type is not one of the listed, tries to
1907 * convert it to Integer, and raises if it is impossible:
1908 *
1909 * a = [:foo, 'bar', 2]
1910 * # Raises TypeError (no implicit conversion of Symbol into Integer):
1911 * a[:foo]
1912 *
1913 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1914 */
1915
1916VALUE
1917rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
1918{
1919 rb_check_arity(argc, 1, 2);
1920 if (argc == 2) {
1921 return rb_ary_aref2(ary, argv[0], argv[1]);
1922 }
1923 return rb_ary_aref1(ary, argv[0]);
1924}
1925
1926static VALUE
1927rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1928{
1929 long beg = NUM2LONG(b);
1930 long len = NUM2LONG(e);
1931 if (beg < 0) {
1932 beg += RARRAY_LEN(ary);
1933 }
1934 return rb_ary_subseq(ary, beg, len);
1935}
1936
1937VALUE
1938rb_ary_aref1(VALUE ary, VALUE arg)
1939{
1940 long beg, len, step;
1941 const VALUE klass = rb_cArray;
1942
1943 /* special case - speeding up */
1944 if (FIXNUM_P(arg)) {
1945 return rb_ary_entry(ary, FIX2LONG(arg));
1946 }
1947 /* check if idx is Range or ArithmeticSequence */
1948 switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
1949 case Qfalse:
1950 break;
1951 case Qnil:
1952 return Qnil;
1953 default:
1954 if (step == 0) rb_raise(rb_eArgError, "slice step cannot be zero");
1955 len = ary_subseq_len(ary, beg, len);
1956 if (len <= 0) return ary_new(klass, 0);
1957 if (step == 1) return ary_make_partial(ary, klass, beg, len);
1958 return ary_make_partial_step(ary, klass, beg, len, step);
1959 }
1960
1961 return rb_ary_entry(ary, NUM2LONG(arg));
1962}
1963
1964/*
1965 * call-seq:
1966 * at(index) -> object or nil
1967 *
1968 * Returns the element of +self+ specified by the given +index+
1969 * or +nil+ if there is no such element;
1970 * +index+ must be an
1971 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
1972 *
1973 * For non-negative +index+, returns the element of +self+ at offset +index+:
1974 *
1975 * a = [:foo, 'bar', 2]
1976 * a.at(0) # => :foo
1977 * a.at(2) # => 2
1978 * a.at(2.0) # => 2
1979 *
1980 * For negative +index+, counts backwards from the end of +self+:
1981 *
1982 * a.at(-2) # => "bar"
1983 *
1984 * Related: Array#[];
1985 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
1986 */
1987
1988VALUE
1989rb_ary_at(VALUE ary, VALUE pos)
1990{
1991 return rb_ary_entry(ary, NUM2LONG(pos));
1992}
1993
1994#if 0
1995static VALUE
1996rb_ary_first(int argc, VALUE *argv, VALUE ary)
1997{
1998 if (argc == 0) {
1999 if (RARRAY_LEN(ary) == 0) return Qnil;
2000 return RARRAY_AREF(ary, 0);
2001 }
2002 else {
2003 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
2004 }
2005}
2006#endif
2007
2008static VALUE
2009ary_first(VALUE self)
2010{
2011 return (RARRAY_LEN(self) == 0) ? Qnil : RARRAY_AREF(self, 0);
2012}
2013
2014static VALUE
2015ary_last(VALUE self)
2016{
2017 long len = RARRAY_LEN(self);
2018 return (len == 0) ? Qnil : RARRAY_AREF(self, len-1);
2019}
2020
2021VALUE
2022rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
2023{
2024 if (argc == 0) {
2025 return ary_last(ary);
2026 }
2027 else {
2028 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
2029 }
2030}
2031
2032/*
2033 * call-seq:
2034 * fetch(index) -> element
2035 * fetch(index, default_value) -> element or default_value
2036 * fetch(index) {|index| ... } -> element or block_return_value
2037 *
2038 * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
2039 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
2040 *
2041 * With the single argument +index+ and no block,
2042 * returns the element at offset +index+:
2043 *
2044 * a = [:foo, 'bar', 2]
2045 * a.fetch(1) # => "bar"
2046 * a.fetch(1.1) # => "bar"
2047 *
2048 * If +index+ is negative, counts from the end of the array:
2049 *
2050 * a = [:foo, 'bar', 2]
2051 * a.fetch(-1) # => 2
2052 * a.fetch(-2) # => "bar"
2053 *
2054 * With arguments +index+ and +default_value+ (which may be any object) and no block,
2055 * returns +default_value+ if +index+ is out-of-range:
2056 *
2057 * a = [:foo, 'bar', 2]
2058 * a.fetch(1, nil) # => "bar"
2059 * a.fetch(3, :foo) # => :foo
2060 *
2061 * With argument +index+ and a block,
2062 * returns the element at offset +index+ if index is in range
2063 * (and the block is not called); otherwise calls the block with index and returns its return value:
2064 *
2065 * a = [:foo, 'bar', 2]
2066 * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
2067 * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
2068 *
2069 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
2070 */
2071
2072static VALUE
2073rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
2074{
2075 VALUE pos, ifnone;
2076 long block_given;
2077 long idx;
2078
2079 rb_scan_args(argc, argv, "11", &pos, &ifnone);
2080 block_given = rb_block_given_p();
2081 if (block_given && argc == 2) {
2082 rb_warn("block supersedes default value argument");
2083 }
2084 idx = NUM2LONG(pos);
2085
2086 if (idx < 0) {
2087 idx += RARRAY_LEN(ary);
2088 }
2089 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
2090 if (block_given) return rb_yield(pos);
2091 if (argc == 1) {
2092 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
2093 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
2094 }
2095 return ifnone;
2096 }
2097 return RARRAY_AREF(ary, idx);
2098}
2099
2100/*
2101 * call-seq:
2102 * find(if_none_proc = nil) {|element| ... } -> object or nil
2103 * find(if_none_proc = nil) -> enumerator
2104 *
2105 * Returns the first element for which the block returns a truthy value.
2106 *
2107 * With a block given, calls the block with successive elements of the array;
2108 * returns the first element for which the block returns a truthy value:
2109 *
2110 * [1, 3, 5].find {|element| element > 2} # => 3
2111 *
2112 * If no such element is found, calls +if_none_proc+ and returns its return value.
2113 *
2114 * [1, 3, 5].find(proc {-1}) {|element| element > 12} # => -1
2115 *
2116 * With no block given, returns an Enumerator.
2117 *
2118 */
2119
2120static VALUE
2121rb_ary_find(int argc, VALUE *argv, VALUE ary)
2122{
2123 VALUE if_none;
2124 long idx;
2125
2126 RETURN_ENUMERATOR(ary, argc, argv);
2127 if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
2128
2129 for (idx = 0; idx < RARRAY_LEN(ary); idx++) {
2130 VALUE elem = RARRAY_AREF(ary, idx);
2131 if (RTEST(rb_yield(elem))) {
2132 return elem;
2133 }
2134 }
2135
2136 if (!NIL_P(if_none)) {
2137 return rb_funcallv(if_none, idCall, 0, 0);
2138 }
2139 return Qnil;
2140}
2141
2142/*
2143 * call-seq:
2144 * rfind(if_none_proc = nil) {|element| ... } -> object or nil
2145 * rfind(if_none_proc = nil) -> enumerator
2146 *
2147 * Returns the last element for which the block returns a truthy value.
2148 *
2149 * With a block given, calls the block with successive elements of the array in
2150 * reverse order; returns the first element for which the block returns a truthy
2151 * value:
2152 *
2153 * [1, 2, 3, 4, 5, 6].rfind {|element| element < 5} # => 4
2154 *
2155 * If no such element is found, calls +if_none_proc+ and returns its return value.
2156 *
2157 * [1, 2, 3, 4].rfind(proc {0}) {|element| element < -2} # => 0
2158 *
2159 * With no block given, returns an Enumerator.
2160 *
2161 */
2162
2163static VALUE
2164rb_ary_rfind(int argc, VALUE *argv, VALUE ary)
2165{
2166 VALUE if_none;
2167 long len, idx;
2168
2169 RETURN_ENUMERATOR(ary, argc, argv);
2170 if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
2171
2172 idx = RARRAY_LEN(ary);
2173 while (idx--) {
2174 VALUE elem = RARRAY_AREF(ary, idx);
2175 if (RTEST(rb_yield(elem))) {
2176 return elem;
2177 }
2178
2179 len = RARRAY_LEN(ary);
2180 idx = (idx >= len) ? len : idx;
2181 }
2182
2183 if (!NIL_P(if_none)) {
2184 return rb_funcallv(if_none, idCall, 0, 0);
2185 }
2186 return Qnil;
2187}
2188
2189/*
2190 * call-seq:
2191 * find_index(object) -> integer or nil
2192 * find_index {|element| ... } -> integer or nil
2193 * find_index -> new_enumerator
2194 * index(object) -> integer or nil
2195 * index {|element| ... } -> integer or nil
2196 * index -> new_enumerator
2197 *
2198 * Returns the zero-based integer index of a specified element, or +nil+.
2199 *
2200 * With only argument +object+ given,
2201 * returns the index of the first element +element+
2202 * for which <tt>object == element</tt>:
2203 *
2204 * a = [:foo, 'bar', 2, 'bar']
2205 * a.index('bar') # => 1
2206 *
2207 * Returns +nil+ if no such element found.
2208 *
2209 * With only a block given,
2210 * calls the block with each successive element;
2211 * returns the index of the first element for which the block returns a truthy value:
2212 *
2213 * a = [:foo, 'bar', 2, 'bar']
2214 * a.index {|element| element == 'bar' } # => 1
2215 *
2216 * Returns +nil+ if the block never returns a truthy value.
2217 *
2218 * With neither an argument nor a block given, returns a new Enumerator.
2219 *
2220 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2221 */
2222
2223static VALUE
2224rb_ary_index(int argc, VALUE *argv, VALUE ary)
2225{
2226 VALUE val;
2227 long i;
2228
2229 if (argc == 0) {
2230 RETURN_ENUMERATOR(ary, 0, 0);
2231 for (i=0; i<RARRAY_LEN(ary); i++) {
2232 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
2233 return LONG2NUM(i);
2234 }
2235 }
2236 return Qnil;
2237 }
2238 rb_check_arity(argc, 0, 1);
2239 val = argv[0];
2240 if (rb_block_given_p())
2241 rb_warn("given block not used");
2242 for (i=0; i<RARRAY_LEN(ary); i++) {
2243 VALUE e = RARRAY_AREF(ary, i);
2244 if (rb_equal(e, val)) {
2245 return LONG2NUM(i);
2246 }
2247 }
2248 return Qnil;
2249}
2250
2251/*
2252 * call-seq:
2253 * rindex(object) -> integer or nil
2254 * rindex {|element| ... } -> integer or nil
2255 * rindex -> new_enumerator
2256 *
2257 * Returns the index of the last element for which <tt>object == element</tt>.
2258 *
2259 * With argument +object+ given, returns the index of the last such element found:
2260 *
2261 * a = [:foo, 'bar', 2, 'bar']
2262 * a.rindex('bar') # => 3
2263 *
2264 * Returns +nil+ if no such object found.
2265 *
2266 * With a block given, calls the block with each successive element;
2267 * returns the index of the last element for which the block returns a truthy value:
2268 *
2269 * a = [:foo, 'bar', 2, 'bar']
2270 * a.rindex {|element| element == 'bar' } # => 3
2271 *
2272 * Returns +nil+ if the block never returns a truthy value.
2273 *
2274 * When neither an argument nor a block is given, returns a new Enumerator.
2275 *
2276 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2277 */
2278
2279static VALUE
2280rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
2281{
2282 VALUE val;
2283 long i = RARRAY_LEN(ary), len;
2284
2285 if (argc == 0) {
2286 RETURN_ENUMERATOR(ary, 0, 0);
2287 while (i--) {
2288 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
2289 return LONG2NUM(i);
2290 if (i > (len = RARRAY_LEN(ary))) {
2291 i = len;
2292 }
2293 }
2294 return Qnil;
2295 }
2296 rb_check_arity(argc, 0, 1);
2297 val = argv[0];
2298 if (rb_block_given_p())
2299 rb_warn("given block not used");
2300 while (i--) {
2301 VALUE e = RARRAY_AREF(ary, i);
2302 if (rb_equal(e, val)) {
2303 return LONG2NUM(i);
2304 }
2305 if (i > RARRAY_LEN(ary)) {
2306 break;
2307 }
2308 }
2309 return Qnil;
2310}
2311
2312VALUE
2314{
2315 VALUE tmp = rb_check_array_type(obj);
2316
2317 if (!NIL_P(tmp)) return tmp;
2318 return rb_ary_new3(1, obj);
2319}
2320
2321static void
2322ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen, int self_insert)
2323{
2324 long olen;
2325
2326 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
2327 olen = RARRAY_LEN(ary);
2328 if (beg < 0) {
2329 beg += olen;
2330 if (beg < 0) {
2331 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2332 beg - olen, -olen);
2333 }
2334 }
2335 if (olen < len || olen < beg + len) {
2336 len = olen - beg;
2337 }
2338
2339 if (beg >= olen) {
2340 VALUE target_ary;
2341 if (beg > ARY_MAX_SIZE - rlen) {
2342 rb_raise(rb_eIndexError, "index %ld too big", beg);
2343 }
2344 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
2345 len = beg + rlen;
2346 ary_mem_clear(ary, olen, beg - olen);
2347 if (rlen > 0) {
2348 /* ary's storage may have moved; only ary itself needs re-deriving. */
2349 if (self_insert) rptr = RARRAY_CONST_PTR(ary);
2350 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
2351 }
2352 ARY_SET_LEN(ary, len);
2353 }
2354 else {
2355 long alen;
2356
2357 if (olen - len > ARY_MAX_SIZE - rlen) {
2358 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
2359 }
2361 alen = olen + rlen - len;
2362 if (alen >= ARY_CAPA(ary)) {
2363 ary_double_capa(ary, alen);
2364 }
2365
2366 if (len != rlen) {
2368 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
2369 VALUE, olen - (beg + len)));
2370 ARY_SET_LEN(ary, alen);
2371 }
2372 if (rlen > 0) {
2373 if (!self_insert) {
2374 rb_gc_writebarrier_remember(ary);
2375 }
2376 else {
2377 /* In this case, we're copying from a region in this array, so
2378 * we don't need to fire the write barrier. */
2379 rptr = RARRAY_CONST_PTR(ary);
2380 }
2381
2382 /* do not use RARRAY_PTR() because it can causes GC.
2383 * ary can contain T_NONE object because it is not cleared.
2384 */
2386 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
2387 }
2388 }
2389}
2390
2391static void
2392rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
2393{
2394 ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl), rpl == ary);
2395 RB_GC_GUARD(rpl);
2396}
2397
2398void
2399rb_ary_set_len(VALUE ary, long len)
2400{
2401 long capa;
2402
2403 rb_ary_modify_check(ary);
2404 if (ARY_SHARED_P(ary)) {
2405 rb_raise(rb_eRuntimeError, "can't set length of shared ");
2406 }
2407 if (len > (capa = (long)ARY_CAPA(ary))) {
2408 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
2409 }
2410 ARY_SET_LEN(ary, len);
2411}
2412
2413VALUE
2414rb_ary_modify_expand(VALUE ary, long expand)
2415{
2416 long len = RARRAY_LEN(ary);
2417
2418 if (expand < 0) {
2419 rb_raise(rb_eArgError, "negative expanding array size");
2420 }
2421 if (expand >= ARY_MAX_SIZE - len) {
2422 rb_raise(rb_eArgError, " size too big");
2423 }
2424 rb_ary_modify_check(ary);
2425 if (len + expand > ARY_CAPA(ary)) {
2426 ary_resize_capa(ary, len + expand);
2427 }
2428 return ary;
2429}
2430
2431VALUE
2433{
2434 long olen;
2435
2437 olen = RARRAY_LEN(ary);
2438 if (len == olen) return ary;
2439 if (len > ARY_MAX_SIZE) {
2440 rb_raise(rb_eIndexError, "index %ld too big", len);
2441 }
2442 if (len > olen) {
2443 if (len > ARY_CAPA(ary)) {
2444 ary_double_capa(ary, len);
2445 }
2446 ary_mem_clear(ary, olen, len - olen);
2447 ARY_SET_LEN(ary, len);
2448 }
2449 else if (ARY_EMBED_P(ary)) {
2450 ARY_SET_EMBED_LEN(ary, len);
2451 }
2452 else if (len <= ary_embed_capa(ary)) {
2453 const VALUE *ptr = ARY_HEAP_PTR(ary);
2454 long ptr_capa = ARY_HEAP_SIZE(ary);
2455 bool is_malloc_ptr = !ARY_SHARED_P(ary);
2456
2457 FL_SET_EMBED(ary);
2458
2459 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len); /* WB: no new reference */
2460 ARY_SET_EMBED_LEN(ary, len);
2461
2462 if (is_malloc_ptr) ruby_xfree_sized((void *)ptr, ptr_capa);
2463 }
2464 else {
2465 if (olen > len + ARY_DEFAULT_SIZE) {
2466 size_t new_capa = ary_heap_realloc(ary, len);
2467 ARY_SET_CAPA(ary, new_capa);
2468 }
2469 ARY_SET_HEAP_LEN(ary, len);
2470 }
2471 ary_verify(ary);
2472 return ary;
2473}
2474
2475static VALUE
2476ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
2477{
2478 rb_ary_store(ary, key, val);
2479 return val;
2480}
2481
2482static VALUE
2483ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
2484{
2485 rb_ary_splice(ary, beg, len, rb_ary_to_ary(val));
2486 return val;
2487}
2488
2489/*
2490 * call-seq:
2491 * self[index] = object -> object
2492 * self[start, length] = object -> object
2493 * self[range] = object -> object
2494 *
2495 * Assigns elements in +self+, based on the given +object+; returns +object+.
2496 *
2497 * In brief:
2498 *
2499 * a_orig = [:foo, 'bar', 2]
2500 *
2501 * # With argument index.
2502 * a = a_orig.dup
2503 * a[0] = 'foo' # => "foo"
2504 * a # => ["foo", "bar", 2]
2505 * a = a_orig.dup
2506 * a[7] = 'foo' # => "foo"
2507 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2508 *
2509 * # With arguments start and length.
2510 * a = a_orig.dup
2511 * a[0, 2] = 'foo' # => "foo"
2512 * a # => ["foo", 2]
2513 * a = a_orig.dup
2514 * a[6, 50] = 'foo' # => "foo"
2515 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2516 *
2517 * # With argument range.
2518 * a = a_orig.dup
2519 * a[0..1] = 'foo' # => "foo"
2520 * a # => ["foo", 2]
2521 * a = a_orig.dup
2522 * a[6..50] = 'foo' # => "foo"
2523 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2524 *
2525 * When Integer argument +index+ is given, assigns +object+ to an element in +self+.
2526 *
2527 * If +index+ is non-negative, assigns +object+ the element at offset +index+:
2528 *
2529 * a = [:foo, 'bar', 2]
2530 * a[0] = 'foo' # => "foo"
2531 * a # => ["foo", "bar", 2]
2532 *
2533 * If +index+ is greater than <tt>self.length</tt>, extends the array:
2534 *
2535 * a = [:foo, 'bar', 2]
2536 * a[7] = 'foo' # => "foo"
2537 * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
2538 *
2539 * If +index+ is negative, counts backwards from the end of the array:
2540 *
2541 * a = [:foo, 'bar', 2]
2542 * a[-1] = 'two' # => "two"
2543 * a # => [:foo, "bar", "two"]
2544 *
2545 * When Integer arguments +start+ and +length+ are given and +object+ is not an array,
2546 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2547 * and assigns +object+ at offset +start+:
2548 *
2549 * a = [:foo, 'bar', 2]
2550 * a[0, 2] = 'foo' # => "foo"
2551 * a # => ["foo", 2]
2552 *
2553 * If +start+ is negative, counts backwards from the end of the array:
2554 *
2555 * a = [:foo, 'bar', 2]
2556 * a[-2, 2] = 'foo' # => "foo"
2557 * a # => [:foo, "foo"]
2558 *
2559 * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
2560 * extends the array with +nil+, assigns +object+ at offset +start+,
2561 * and ignores +length+:
2562 *
2563 * a = [:foo, 'bar', 2]
2564 * a[6, 50] = 'foo' # => "foo"
2565 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2566 *
2567 * If +length+ is zero, shifts elements at and following offset +start+
2568 * and assigns +object+ at offset +start+:
2569 *
2570 * a = [:foo, 'bar', 2]
2571 * a[1, 0] = 'foo' # => "foo"
2572 * a # => [:foo, "foo", "bar", 2]
2573 *
2574 * If +length+ is too large for the existing array, does not extend the array:
2575 *
2576 * a = [:foo, 'bar', 2]
2577 * a[1, 5] = 'foo' # => "foo"
2578 * a # => [:foo, "foo"]
2579 *
2580 * When Range argument +range+ is given and +object+ is not an array,
2581 * removes <tt>length - 1</tt> elements beginning at offset +start+,
2582 * and assigns +object+ at offset +start+:
2583 *
2584 * a = [:foo, 'bar', 2]
2585 * a[0..1] = 'foo' # => "foo"
2586 * a # => ["foo", 2]
2587 *
2588 * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
2589 *
2590 * a = [:foo, 'bar', 2]
2591 * a[-2..2] = 'foo' # => "foo"
2592 * a # => [:foo, "foo"]
2593 *
2594 * If the array length is less than <tt>range.begin</tt>,
2595 * extends the array with +nil+, assigns +object+ at offset <tt>range.begin</tt>,
2596 * and ignores +length+:
2597 *
2598 * a = [:foo, 'bar', 2]
2599 * a[6..50] = 'foo' # => "foo"
2600 * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
2601 *
2602 * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
2603 * and assigns +object+ at offset +start+:
2604 *
2605 * a = [:foo, 'bar', 2]
2606 * a[1..0] = 'foo' # => "foo"
2607 * a # => [:foo, "foo", "bar", 2]
2608 *
2609 * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
2610 * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
2611 *
2612 * a = [:foo, 'bar', 2]
2613 * a[1..-1] = 'foo' # => "foo"
2614 * a # => [:foo, "foo"]
2615 * a = [:foo, 'bar', 2]
2616 * a[1..-2] = 'foo' # => "foo"
2617 * a # => [:foo, "foo", 2]
2618 * a = [:foo, 'bar', 2]
2619 * a[1..-3] = 'foo' # => "foo"
2620 * a # => [:foo, "foo", "bar", 2]
2621 * a = [:foo, 'bar', 2]
2622 *
2623 * If <tt>range.end</tt> is too large for the existing array,
2624 * replaces array elements, but does not extend the array with +nil+ values:
2625 *
2626 * a = [:foo, 'bar', 2]
2627 * a[1..5] = 'foo' # => "foo"
2628 * a # => [:foo, "foo"]
2629 *
2630 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2631 */
2632
2633static VALUE
2634rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2635{
2636 long offset, beg, len;
2637
2638 rb_check_arity(argc, 2, 3);
2639 rb_ary_modify_check(ary);
2640 if (argc == 3) {
2641 beg = NUM2LONG(argv[0]);
2642 len = NUM2LONG(argv[1]);
2643 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
2644 }
2645 if (FIXNUM_P(argv[0])) {
2646 offset = FIX2LONG(argv[0]);
2647 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2648 }
2649 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2650 /* check if idx is Range */
2651 return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
2652 }
2653
2654 offset = NUM2LONG(argv[0]);
2655 return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
2656}
2657
2658/*
2659 * call-seq:
2660 * insert(index, *objects) -> self
2661 *
2662 * Inserts the given +objects+ as elements of +self+;
2663 * returns +self+.
2664 *
2665 * When +index+ is non-negative, inserts +objects+
2666 * _before_ the element at offset +index+:
2667 *
2668 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2669 * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
2670 *
2671 * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
2672 *
2673 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2674 * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
2675 *
2676 * When +index+ is negative, inserts +objects+
2677 * _after_ the element at offset <tt>index + self.size</tt>:
2678 *
2679 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2680 * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
2681 *
2682 * With no +objects+ given, does nothing:
2683 *
2684 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
2685 * a.insert(1) # => ["a", "b", "c"]
2686 * a.insert(50) # => ["a", "b", "c"]
2687 * a.insert(-50) # => ["a", "b", "c"]
2688 *
2689 * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
2690 *
2691 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
2692 */
2693
2694static VALUE
2695rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2696{
2697 long pos;
2698
2700 rb_ary_modify_check(ary);
2701 pos = NUM2LONG(argv[0]);
2702 if (argc == 1) return ary;
2703 if (pos == -1) {
2704 pos = RARRAY_LEN(ary);
2705 }
2706 else if (pos < 0) {
2707 long minpos = -RARRAY_LEN(ary) - 1;
2708 if (pos < minpos) {
2709 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2710 pos, minpos);
2711 }
2712 pos++;
2713 }
2714 ary_splice(ary, pos, 0, argv + 1, argc - 1, FALSE);
2715 return ary;
2716}
2717
2718static VALUE
2719rb_ary_length(VALUE ary);
2720
2721static VALUE
2722ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2723{
2724 return rb_ary_length(ary);
2725}
2726
2727// These array primitives enable tight compatibility with the C implementation
2728// in terms of what method calls happen. They can use unchecked utilities such as
2729// FIX2LONG since unlike userland Ruby code, these methods cannot be traced with
2730// TracePoint (or ruby/debug.h APIs) and have their local variables changed from
2731// underneath them.
2732
2733// Return true if the index is at or past the end of the array.
2734VALUE
2735rb_builtin_ary_at_end(rb_execution_context_t *ec, VALUE self, VALUE index)
2736{
2737 return FIX2LONG(index) >= RARRAY_LEN(self) ? Qtrue : Qfalse;
2738}
2739
2740// Return the element at the given fixnum index.
2741VALUE
2742rb_builtin_ary_at(rb_execution_context_t *ec, VALUE self, VALUE index)
2743{
2744 return RARRAY_AREF(self, FIX2LONG(index));
2745}
2746
2747// Increment a fixnum by 1.
2748VALUE
2749rb_builtin_fixnum_inc(rb_execution_context_t *ec, VALUE self, VALUE num)
2750{
2751 return LONG2FIX(FIX2LONG(num) + 1);
2752}
2753
2754VALUE
2755rb_builtin_ary_first(rb_execution_context_t *ec, VALUE self)
2756{
2757 return ary_first(self);
2758}
2759
2760// Push a value onto an array and return the value.
2761static VALUE
2762rb_jit_ary_push(rb_execution_context_t *ec, VALUE self, VALUE ary, VALUE val)
2763{
2764 rb_ary_push(ary, val);
2765 return val;
2766}
2767
2768/*
2769 * call-seq:
2770 * each {|element| ... } -> self
2771 * each -> new_enumerator
2772 *
2773 * With a block given, iterates over the elements of +self+,
2774 * passing each element to the block;
2775 * returns +self+:
2776 *
2777 * a = [:foo, 'bar', 2]
2778 * a.each {|element| puts "#{element.class} #{element}" }
2779 *
2780 * Output:
2781 *
2782 * Symbol foo
2783 * String bar
2784 * Integer 2
2785 *
2786 * Allows the array to be modified during iteration:
2787 *
2788 * a = [:foo, 'bar', 2]
2789 * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
2790 *
2791 * Output:
2792 *
2793 * foo
2794 * bar
2795 *
2796 * With no block given, returns a new Enumerator.
2797 *
2798 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2799 */
2800
2801VALUE
2803{
2804 long i;
2805 ary_verify(ary);
2806 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2807 rb_execution_context_t *ec = GET_EC();
2808 for (i=0; i<RARRAY_LEN(ary); i++) {
2809 rb_ec_yield(ec, RARRAY_AREF(ary, i));
2810 }
2811 return ary;
2812}
2813
2814/*
2815 * call-seq:
2816 * each_index {|index| ... } -> self
2817 * each_index -> new_enumerator
2818 *
2819 * With a block given, iterates over the elements of +self+,
2820 * passing each <i>array index</i> to the block;
2821 * returns +self+:
2822 *
2823 * a = [:foo, 'bar', 2]
2824 * a.each_index {|index| puts "#{index} #{a[index]}" }
2825 *
2826 * Output:
2827 *
2828 * 0 foo
2829 * 1 bar
2830 * 2 2
2831 *
2832 * Allows the array to be modified during iteration:
2833 *
2834 * a = [:foo, 'bar', 2]
2835 * a.each_index {|index| puts index; a.clear if index > 0 }
2836 * a # => []
2837 *
2838 * Output:
2839 *
2840 * 0
2841 * 1
2842 *
2843 * With no block given, returns a new Enumerator.
2844 *
2845 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2846 */
2847
2848static VALUE
2849rb_ary_each_index(VALUE ary)
2850{
2851 long i;
2852 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2853
2854 for (i=0; i<RARRAY_LEN(ary); i++) {
2855 rb_yield(LONG2NUM(i));
2856 }
2857 return ary;
2858}
2859
2860/*
2861 * call-seq:
2862 * reverse_each {|element| ... } -> self
2863 * reverse_each -> Enumerator
2864 *
2865 * When a block given, iterates backwards over the elements of +self+,
2866 * passing, in reverse order, each element to the block;
2867 * returns +self+:
2868 *
2869 * a = []
2870 * [0, 1, 2].reverse_each {|element| a.push(element) }
2871 * a # => [2, 1, 0]
2872 *
2873 * Allows the array to be modified during iteration:
2874 *
2875 * a = ['a', 'b', 'c']
2876 * a.reverse_each {|element| a.clear if element.start_with?('b') }
2877 * a # => []
2878 *
2879 * When no block given, returns a new Enumerator.
2880 *
2881 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
2882 */
2883
2884static VALUE
2885rb_ary_reverse_each(VALUE ary)
2886{
2887 long len;
2888
2889 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2890 len = RARRAY_LEN(ary);
2891 while (len--) {
2892 long nlen;
2894 nlen = RARRAY_LEN(ary);
2895 if (nlen < len) {
2896 len = nlen;
2897 }
2898 }
2899 return ary;
2900}
2901
2902/*
2903 * call-seq:
2904 * length -> integer
2905 * size -> integer
2906 *
2907 * Returns the count of elements in +self+:
2908 *
2909 * [0, 1, 2].length # => 3
2910 * [].length # => 0
2911 *
2912 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2913 */
2914
2915static VALUE
2916rb_ary_length(VALUE ary)
2917{
2918 long len = RARRAY_LEN(ary);
2919 return LONG2NUM(len);
2920}
2921
2922/*
2923 * call-seq:
2924 * empty? -> true or false
2925 *
2926 * Returns +true+ if the count of elements in +self+ is zero,
2927 * +false+ otherwise.
2928 *
2929 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
2930 */
2931
2932static VALUE
2933rb_ary_empty_p(VALUE ary)
2934{
2935 return RBOOL(RARRAY_LEN(ary) == 0);
2936}
2937
2938VALUE
2940{
2941 long len = RARRAY_LEN(ary);
2942 VALUE dup = rb_ary_new2(len);
2943 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
2944 ARY_SET_LEN(dup, len);
2945
2946 ary_verify(ary);
2947 ary_verify(dup);
2948 return dup;
2949}
2950
2951VALUE
2953{
2954 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2955}
2956
2957#if USE_ZJIT
2958bool
2959rb_zjit_array_new_can_fastpath(long len, size_t *alloc_size_out, VALUE *flags_out)
2960{
2961 if (!ary_embeddable_p(len)) {
2962 return false;
2963 }
2964 long embed_size = ary_embed_size(len);
2965
2966 *alloc_size_out = embed_size;
2967 *flags_out = T_ARRAY | RARRAY_EMBED_FLAG | ((VALUE)len << RARRAY_EMBED_LEN_SHIFT);
2968 return true;
2969}
2970
2971bool
2972rb_zjit_array_dup_can_fastpath(VALUE ary, size_t *alloc_size_out, VALUE *flags_out, long *len_out)
2973{
2974 long len = RARRAY_LEN(ary);
2975 if (!rb_zjit_array_new_can_fastpath(len, alloc_size_out, flags_out)) {
2976 return false;
2977 }
2978 else {
2979 *len_out = len;
2980 return true;
2981 }
2982}
2983#endif
2984
2985extern VALUE rb_output_fs;
2986
2987static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2988
2989static VALUE
2990recursive_join(VALUE obj, VALUE argp, int recur)
2991{
2992 VALUE *arg = (VALUE *)argp;
2993 VALUE ary = arg[0];
2994 VALUE sep = arg[1];
2995 VALUE result = arg[2];
2996 int *first = (int *)arg[3];
2997
2998 if (recur) {
2999 rb_raise(rb_eArgError, "recursive array join");
3000 }
3001 else {
3002 ary_join_1(obj, ary, sep, 0, result, first);
3003 }
3004 return Qnil;
3005}
3006
3007static long
3008ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
3009{
3010 long i;
3011 VALUE val;
3012
3013 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
3014 for (i=0; i<max; i++) {
3015 val = RARRAY_AREF(ary, i);
3016 if (!RB_TYPE_P(val, T_STRING)) break;
3017 if (i > 0 && !NIL_P(sep))
3018 rb_str_buf_append(result, sep);
3019 rb_str_buf_append(result, val);
3020 }
3021 return i;
3022}
3023
3024static void
3025ary_join_1_str(VALUE dst, VALUE src, int *first)
3026{
3027 rb_str_buf_append(dst, src);
3028 if (*first) {
3029 rb_enc_copy(dst, src);
3030 *first = FALSE;
3031 }
3032}
3033
3034static void
3035ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
3036{
3037 if (val == ary) {
3038 rb_raise(rb_eArgError, "recursive array join");
3039 }
3040 else {
3041 VALUE args[4];
3042
3043 *first = FALSE;
3044 args[0] = val;
3045 args[1] = sep;
3046 args[2] = result;
3047 args[3] = (VALUE)first;
3048 rb_exec_recursive(recursive_join, obj, (VALUE)args);
3049 }
3050}
3051
3052static void
3053ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
3054{
3055 VALUE val, tmp;
3056
3057 for (; i<RARRAY_LEN(ary); i++) {
3058 if (i > 0 && !NIL_P(sep))
3059 rb_str_buf_append(result, sep);
3060
3061 val = RARRAY_AREF(ary, i);
3062 if (RB_TYPE_P(val, T_STRING)) {
3063 ary_join_1_str(result, val, first);
3064 }
3065 else if (RB_TYPE_P(val, T_ARRAY)) {
3066 ary_join_1_ary(val, ary, sep, result, val, first);
3067 }
3068 else if (!NIL_P(tmp = rb_check_string_type(val))) {
3069 ary_join_1_str(result, tmp, first);
3070 }
3071 else if (!NIL_P(tmp = rb_check_array_type(val))) {
3072 ary_join_1_ary(val, ary, sep, result, tmp, first);
3073 }
3074 else {
3075 ary_join_1_str(result, rb_obj_as_string(val), first);
3076 }
3077 }
3078}
3079
3080/* Fast path for Array#join: when every element is a String in one fast-path encoding
3081 * (UTF-8 / US-ASCII / ASCII-8BIT) and the separator is byte-compatible, the result can
3082 * be produced with a single memcpy pass instead of appending each element through
3083 * rb_str_buf_append. Returns the joined String, or Qundef when any of those invariants
3084 * does not hold -- the caller then uses the general path. No user code runs here, so
3085 * the array cannot be mutated underneath us. */
3086static VALUE
3087ary_join_fast(VALUE ary, VALUE sep)
3088{
3089 long n = RARRAY_LEN(ary);
3090 if (n == 0) return Qundef;
3091
3092 VALUE first = RARRAY_AREF(ary, 0);
3093 if (!RB_TYPE_P(first, T_STRING)) return Qundef;
3094 int encidx = ENCODING_GET(first);
3095 if (!rb_str_encindex_fastpath(encidx)) return Qundef;
3096
3097 /* cr accumulates the result code range exactly as rb_str_buf_append would. */
3099 long sep_len = 0;
3100 const char *sep_ptr = NULL;
3101 if (!NIL_P(sep)) {
3102 int sep_cr = rb_enc_str_coderange(sep);
3103 /* The separator must share the element encoding, or be 7-bit (encidx is
3104 ASCII-compatible, so a 7-bit separator concatenates without negotiation). */
3105 if (ENCODING_GET(sep) != encidx && sep_cr != ENC_CODERANGE_7BIT) return Qundef;
3106 sep_ptr = RSTRING_PTR(sep);
3107 sep_len = RSTRING_LEN(sep);
3108 if (n > 1) cr = ENC_CODERANGE_AND(cr, sep_cr);
3109 }
3110
3111 /* One pass: confirm the shared encoding, measure the length, merge code ranges. */
3112 long len = 1 + sep_len * (n - 1);
3113 for (long i = 0; i < n; i++) {
3114 VALUE s = RARRAY_AREF(ary, i);
3115 if (!RB_TYPE_P(s, T_STRING) || ENCODING_GET(s) != encidx) return Qundef;
3116 len += RSTRING_LEN(s);
3117 cr = ENC_CODERANGE_AND(cr, rb_enc_str_coderange(s));
3118 }
3119
3120 VALUE result = rb_str_buf_new(len);
3121 rb_enc_associate_index(result, encidx);
3122 char *const buf = RSTRING_PTR(result);
3123 char *p = buf;
3124 for (long i = 0; i < n; i++) {
3125 VALUE s = RARRAY_AREF(ary, i);
3126 long slen = RSTRING_LEN(s);
3127 if (i > 0 && sep_len) {
3128 memcpy(p, sep_ptr, sep_len);
3129 p += sep_len;
3130 }
3131 memcpy(p, RSTRING_PTR(s), slen);
3132 p += slen;
3133 }
3134
3135 ENC_CODERANGE_CLEAR(result); /* keep rb_str_set_len from rescanning the bytes */
3136 rb_str_set_len(result, p - buf);
3137 ENC_CODERANGE_SET(result, cr);
3138 return result;
3139}
3140
3141VALUE
3143{
3144 long len = 1, i;
3145 VALUE val, tmp, result;
3146
3147 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
3148
3149 if (!NIL_P(sep)) StringValue(sep);
3150
3151 result = ary_join_fast(ary, sep);
3152 if (!UNDEF_P(result)) return result;
3153
3154 if (!NIL_P(sep)) {
3155 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
3156 }
3157 long len_memo = RARRAY_LEN(ary);
3158 for (i=0; i < len_memo; i++) {
3159 val = RARRAY_AREF(ary, i);
3160 if (RB_UNLIKELY(!RB_TYPE_P(val, T_STRING))) {
3161 tmp = rb_check_string_type(val);
3162 if (NIL_P(tmp) || tmp != val) {
3163 int first;
3164 long n = RARRAY_LEN(ary);
3165 if (i > n) i = n;
3166 result = rb_str_buf_new(len + (n-i)*10);
3167 rb_enc_associate(result, rb_usascii_encoding());
3168 i = ary_join_0(ary, sep, i, result);
3169 first = i == 0;
3170 ary_join_1(ary, ary, sep, i, result, &first);
3171 return result;
3172 }
3173 len += RSTRING_LEN(tmp);
3174 len_memo = RARRAY_LEN(ary);
3175 }
3176 else {
3177 len += RSTRING_LEN(val);
3178 }
3179 }
3180
3181 result = rb_str_new(0, len);
3182 rb_str_set_len(result, 0);
3183
3184 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
3185
3186 return result;
3187}
3188
3189/*
3190 * call-seq:
3191 * join(separator = $,) -> new_string
3192 *
3193 * Returns the new string formed by joining the string-converted elements of +self+
3194 * with the given +separator+ (defaults to <tt>$,</tt>):
3195 *
3196 * $, # => nil
3197 * %w[].join # => ""
3198 * %w[foo].join # => "foo"
3199 * a = %w[foo bar baz] # => ["foo", "bar", "baz"]
3200 * a.join # => "foobarbaz"
3201 * a.join('|') # => "foo|bar|baz"
3202 * a.join(' :|: ') # => "foo :|: bar :|: baz"
3203 *
3204 * Flattens and joins nested arrays:
3205 *
3206 * [:foo, [:bar, [:baz, :bat]]].join # => "foobarbazbat"
3207 *
3208 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3209 */
3210static VALUE
3211rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
3212{
3213 VALUE sep;
3214
3215 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
3216 sep = rb_output_fs;
3217 if (!NIL_P(sep)) {
3218 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
3219 }
3220 }
3221
3222 return rb_ary_join(ary, sep);
3223}
3224
3225static VALUE
3226inspect_ary(VALUE ary, VALUE dummy, int recur)
3227{
3228 long i;
3229 VALUE s, str;
3230
3231 if (recur) return rb_usascii_str_new_cstr("[...]");
3232 str = rb_str_buf_new2("[");
3233 for (i=0; i<RARRAY_LEN(ary); i++) {
3234 s = rb_inspect(RARRAY_AREF(ary, i));
3235 if (i > 0) rb_str_buf_cat2(str, ", ");
3236 else rb_enc_copy(str, s);
3237 rb_str_buf_append(str, s);
3238 }
3239 rb_str_buf_cat2(str, "]");
3240 return str;
3241}
3242
3243/*
3244 * call-seq:
3245 * inspect -> new_string
3246 * to_s -> new_string
3247 *
3248 * Returns the new string formed by calling method <tt>#inspect</tt>
3249 * on each array element:
3250 *
3251 * a = [:foo, 'bar', 2]
3252 * a.inspect # => "[:foo, \"bar\", 2]"
3253 *
3254 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3255 */
3256
3257static VALUE
3258rb_ary_inspect(VALUE ary)
3259{
3260 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
3261 return rb_exec_recursive(inspect_ary, ary, 0);
3262}
3263
3264VALUE
3266{
3267 return rb_ary_inspect(ary);
3268}
3269
3270/*
3271 * call-seq:
3272 * to_a -> self or new_array
3273 *
3274 * When +self+ is an instance of \Array, returns +self+.
3275 *
3276 * Otherwise, returns a new array containing the elements of +self+:
3277 *
3278 * class MyArray < Array; end
3279 * my_a = MyArray.new(['foo', 'bar', 'two'])
3280 * a = my_a.to_a
3281 * a # => ["foo", "bar", "two"]
3282 * a.class # => Array # Not MyArray.
3283 *
3284 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3285 */
3286
3287static VALUE
3288rb_ary_to_a(VALUE ary)
3289{
3290 if (rb_obj_class(ary) != rb_cArray) {
3292 rb_ary_replace(dup, ary);
3293 return dup;
3294 }
3295 return ary;
3296}
3297
3298/*
3299 * call-seq:
3300 * to_h -> new_hash
3301 * to_h {|element| ... } -> new_hash
3302 *
3303 * Returns a new hash formed from +self+.
3304 *
3305 * With no block given, each element of +self+ must be a 2-element sub-array;
3306 * forms each sub-array into a key-value pair in the new hash:
3307 *
3308 * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
3309 * a.to_h # => {"foo" => "zero", "bar" => "one", "baz" => "two"}
3310 * [].to_h # => {}
3311 *
3312 * With a block given, the block must return a 2-element array;
3313 * calls the block with each element of +self+;
3314 * forms each returned array into a key-value pair in the returned hash:
3315 *
3316 * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
3317 * a.to_h {|element| [element, element.class] }
3318 * # => {"foo" => String, bar: Symbol, 1 => Integer, [2, 3] => Array, {baz: 4} => Hash}
3319 *
3320 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3321 */
3322
3323static VALUE
3324rb_ary_to_h(VALUE ary)
3325{
3326 long i;
3327 VALUE hash = rb_hash_new_capa(RARRAY_LEN(ary));
3328 int block_given = rb_block_given_p();
3329
3330 for (i=0; i<RARRAY_LEN(ary); i++) {
3331 const VALUE e = rb_ary_elt(ary, i);
3332 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
3333 const VALUE key_value_pair = rb_check_array_type(elt);
3334 if (NIL_P(key_value_pair)) {
3335 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
3336 rb_obj_class(elt), i);
3337 }
3338 if (RARRAY_LEN(key_value_pair) != 2) {
3339 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
3340 i, RARRAY_LEN(key_value_pair));
3341 }
3342 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
3343 }
3344 return hash;
3345}
3346
3347/*
3348 * call-seq:
3349 * to_ary -> self
3350 *
3351 * Returns +self+.
3352 */
3353
3354static VALUE
3355rb_ary_to_ary_m(VALUE ary)
3356{
3357 return ary;
3358}
3359
3360static void
3361ary_reverse(VALUE *p1, VALUE *p2)
3362{
3363 while (p1 < p2) {
3364 VALUE tmp = *p1;
3365 *p1++ = *p2;
3366 *p2-- = tmp;
3367 }
3368}
3369
3370VALUE
3372{
3373 VALUE *p2;
3374 long len = RARRAY_LEN(ary);
3375
3377 if (len > 1) {
3378 RARRAY_PTR_USE(ary, p1, {
3379 p2 = p1 + len - 1; /* points last item */
3380 ary_reverse(p1, p2);
3381 }); /* WB: no new reference */
3382 }
3383 return ary;
3384}
3385
3386/*
3387 * call-seq:
3388 * reverse! -> self
3389 *
3390 * Reverses the order of the elements of +self+;
3391 * returns +self+:
3392 *
3393 * a = [0, 1, 2]
3394 * a.reverse! # => [2, 1, 0]
3395 * a # => [2, 1, 0]
3396 *
3397 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3398 */
3399
3400static VALUE
3401rb_ary_reverse_bang(VALUE ary)
3402{
3403 return rb_ary_reverse(ary);
3404}
3405
3406/*
3407 * call-seq:
3408 * reverse -> new_array
3409 *
3410 * Returns a new array containing the elements of +self+ in reverse order:
3411 *
3412 * [0, 1, 2].reverse # => [2, 1, 0]
3413 *
3414 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
3415 */
3416
3417static VALUE
3418rb_ary_reverse_m(VALUE ary)
3419{
3420 long len = RARRAY_LEN(ary);
3421 VALUE dup = rb_ary_new2(len);
3422
3423 if (len > 0) {
3424 const VALUE *p1 = RARRAY_CONST_PTR(ary);
3425 VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
3426 do *p2-- = *p1++; while (--len > 0);
3427 rb_gc_writebarrier_remember(dup);
3428 }
3429 ARY_SET_LEN(dup, RARRAY_LEN(ary));
3430 return dup;
3431}
3432
3433static inline long
3434rotate_count(long cnt, long len)
3435{
3436 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
3437}
3438
3439static void
3440ary_rotate_ptr(VALUE *ptr, long len, long cnt)
3441{
3442 if (cnt == 1) {
3443 VALUE tmp = *ptr;
3444 memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
3445 *(ptr + len - 1) = tmp;
3446 }
3447 else if (cnt == len - 1) {
3448 VALUE tmp = *(ptr + len - 1);
3449 memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
3450 *ptr = tmp;
3451 }
3452 else {
3453 --len;
3454 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
3455 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
3456 if (len > 0) ary_reverse(ptr, ptr + len);
3457 }
3458}
3459
3460VALUE
3461rb_ary_rotate(VALUE ary, long cnt)
3462{
3464
3465 if (cnt != 0) {
3466 long len = RARRAY_LEN(ary);
3467 if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
3468 RARRAY_PTR_USE(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
3469 return ary;
3470 }
3471 }
3472 return Qnil;
3473}
3474
3475/*
3476 * call-seq:
3477 * rotate!(count = 1) -> self
3478 *
3479 * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
3480 *
3481 * With non-negative numeric +count+,
3482 * rotates +count+ elements from the beginning to the end:
3483 *
3484 * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
3485 [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
3486 *
3487 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3488 *
3489 * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
3490 *
3491 * If +count+ is zero, rotates no elements:
3492 *
3493 * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
3494 *
3495 * With a negative numeric +count+, rotates in the opposite direction,
3496 * from end to beginning:
3497 *
3498 * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
3499 *
3500 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3501 *
3502 * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
3503 *
3504 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3505 */
3506
3507static VALUE
3508rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
3509{
3510 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3511 rb_ary_rotate(ary, n);
3512 return ary;
3513}
3514
3515/*
3516 * call-seq:
3517 * rotate(count = 1) -> new_array
3518 *
3519 * Returns a new array formed from +self+ with elements
3520 * rotated from one end to the other.
3521 *
3522 * With non-negative numeric +count+,
3523 * rotates elements from the beginning to the end:
3524 *
3525 * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
3526 * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
3527 *
3528 * If +count+ is large, uses <tt>count % array.size</tt> as the count:
3529 *
3530 * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
3531 *
3532 * With a +count+ of zero, rotates no elements:
3533 *
3534 * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
3535 *
3536 * With negative numeric +count+, rotates in the opposite direction,
3537 * from the end to the beginning:
3538 *
3539 * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
3540 *
3541 * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
3542 *
3543 * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
3544 *
3545 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3546 */
3547
3548static VALUE
3549rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
3550{
3551 VALUE rotated;
3552 const VALUE *ptr;
3553 long len;
3554 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
3555
3556 len = RARRAY_LEN(ary);
3557 rotated = rb_ary_new2(len);
3558 if (len > 0) {
3559 cnt = rotate_count(cnt, len);
3561 len -= cnt;
3562 ary_memcpy(rotated, 0, len, ptr + cnt);
3563 ary_memcpy(rotated, len, cnt, ptr);
3564 }
3565 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
3566 return rotated;
3567}
3568
3569struct ary_sort_data {
3570 VALUE ary;
3571 VALUE receiver;
3572};
3573
3574static VALUE
3575sort_reentered(VALUE ary)
3576{
3577 if (RBASIC(ary)->klass) {
3578 rb_raise(rb_eRuntimeError, "sort reentered");
3579 }
3580 return Qnil;
3581}
3582
3583static void
3584sort_returned(struct ary_sort_data *data)
3585{
3586 if (rb_obj_frozen_p(data->receiver)) {
3587 rb_raise(rb_eFrozenError, "array frozen during sort");
3588 }
3589 sort_reentered(data->ary);
3590}
3591
3592static int
3593sort_1(const void *ap, const void *bp, void *dummy)
3594{
3595 struct ary_sort_data *data = dummy;
3596 VALUE retval = sort_reentered(data->ary);
3597 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3598 VALUE args[2];
3599 int n;
3600
3601 args[0] = a;
3602 args[1] = b;
3603 retval = rb_yield_values2(2, args);
3604 n = rb_cmpint(retval, a, b);
3605 sort_returned(data);
3606 return n;
3607}
3608
3609static int
3610sort_2(const void *ap, const void *bp, void *dummy)
3611{
3612 struct ary_sort_data *data = dummy;
3613 VALUE retval = sort_reentered(data->ary);
3614 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
3615 int n;
3616
3617 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(INTEGER)) {
3618 if ((long)a > (long)b) return 1;
3619 if ((long)a < (long)b) return -1;
3620 return 0;
3621 }
3622 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(STRING)) {
3623 return rb_str_cmp(a, b);
3624 }
3625 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(FLOAT)) {
3626 return rb_float_cmp(a, b);
3627 }
3628
3629 retval = rb_funcallv(a, id_cmp, 1, &b);
3630 n = rb_cmpint(retval, a, b);
3631 sort_returned(data);
3632
3633 return n;
3634}
3635
3636/*
3637 * call-seq:
3638 * sort! -> self
3639 * sort! {|a, b| ... } -> self
3640 *
3641 * Like Array#sort, but returns +self+ with its elements sorted in place.
3642 *
3643 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3644 */
3645
3646VALUE
3648{
3649 rb_ary_modify(ary);
3650 RUBY_ASSERT(!ARY_SHARED_P(ary));
3651 if (RARRAY_LEN(ary) > 1) {
3652 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
3653 struct ary_sort_data data;
3654 long len = RARRAY_LEN(ary);
3655 RBASIC_CLEAR_CLASS(tmp);
3656 data.ary = tmp;
3657 data.receiver = ary;
3658 RARRAY_PTR_USE(tmp, ptr, {
3659 ruby_qsort(ptr, len, sizeof(VALUE),
3660 rb_block_given_p()?sort_1:sort_2, &data);
3661 }); /* WB: no new reference */
3662 rb_ary_modify(ary);
3663 if (ARY_EMBED_P(tmp)) {
3664 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
3665 rb_ary_unshare(ary);
3666 FL_SET_EMBED(ary);
3667 }
3668 if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3669 ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3670 }
3671 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
3672 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
3673 }
3674 else {
3675 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
3676 FL_UNSET_SHARED(ary);
3677 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
3678 }
3679 else {
3680 RUBY_ASSERT(!ARY_SHARED_P(tmp));
3681 if (ARY_EMBED_P(ary)) {
3682 FL_UNSET_EMBED(ary);
3683 }
3684 else if (ARY_SHARED_P(ary)) {
3685 /* ary might be destructively operated in the given block */
3686 rb_ary_unshare(ary);
3687 }
3688 else {
3689 ary_heap_free(ary);
3690 }
3691 ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
3692 ARY_SET_HEAP_LEN(ary, len);
3693 ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
3694 }
3695 /* tmp was lost ownership for the ptr */
3696 FL_SET_EMBED(tmp);
3697 ARY_SET_EMBED_LEN(tmp, 0);
3698 OBJ_FREEZE(tmp);
3699 }
3700 /* tmp will be GC'ed. */
3701 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
3702 }
3703 ary_verify(ary);
3704 return ary;
3705}
3706
3707/*
3708 * call-seq:
3709 * sort -> new_array
3710 * sort {|a, b| ... } -> new_array
3711 *
3712 * Returns a new array containing the elements of +self+, sorted.
3713 *
3714 * With no block given, compares elements using operator <tt>#<=></tt>
3715 * (see Object#<=>):
3716 *
3717 * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
3718 *
3719 * With a block given, calls the block with each combination of pairs of elements from +self+;
3720 * for each pair +a+ and +b+, the block should return a numeric:
3721 *
3722 * - Negative when +b+ is to follow +a+.
3723 * - Zero when +a+ and +b+ are equivalent.
3724 * - Positive when +a+ is to follow +b+.
3725 *
3726 * Example:
3727 *
3728 * a = [3, 2, 0, 1]
3729 * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
3730 * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
3731 *
3732 * When the block returns zero, the order for +a+ and +b+ is indeterminate,
3733 * and may be unstable.
3734 *
3735 * See an example in Numeric#nonzero? for the idiom to sort more
3736 * complex structure.
3737 *
3738 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3739 */
3740
3741VALUE
3742rb_ary_sort(VALUE ary)
3743{
3744 ary = rb_ary_dup(ary);
3745 rb_ary_sort_bang(ary);
3746 return ary;
3747}
3748
3749static VALUE rb_ary_bsearch_index(VALUE ary);
3750
3751/*
3752 * call-seq:
3753 * bsearch {|element| ... } -> found_element or nil
3754 * bsearch -> new_enumerator
3755 *
3756 * Returns the element from +self+ found by a binary search,
3757 * or +nil+ if the search found no suitable element.
3758 *
3759 * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
3760 *
3761 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3762 */
3763
3764static VALUE
3765rb_ary_bsearch(VALUE ary)
3766{
3767 VALUE index_result = rb_ary_bsearch_index(ary);
3768
3769 if (FIXNUM_P(index_result)) {
3770 return rb_ary_entry(ary, FIX2LONG(index_result));
3771 }
3772 return index_result;
3773}
3774
3775/*
3776 * call-seq:
3777 * bsearch_index {|element| ... } -> integer or nil
3778 * bsearch_index -> new_enumerator
3779 *
3780 * Returns the integer index of the element from +self+ found by a binary search,
3781 * or +nil+ if the search found no suitable element.
3782 *
3783 * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
3784 *
3785 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
3786 */
3787
3788static VALUE
3789rb_ary_bsearch_index(VALUE ary)
3790{
3791 long low = 0, high = RARRAY_LEN(ary), mid;
3792 int smaller = 0, satisfied = 0;
3793 VALUE v, val;
3794
3795 RETURN_ENUMERATOR(ary, 0, 0);
3796 while (low < high) {
3797 mid = low + ((high - low) / 2);
3798 val = rb_ary_entry(ary, mid);
3799 v = rb_yield(val);
3800 if (FIXNUM_P(v)) {
3801 if (v == INT2FIX(0)) return INT2FIX(mid);
3802 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
3803 }
3804 else if (v == Qtrue) {
3805 satisfied = 1;
3806 smaller = 1;
3807 }
3808 else if (!RTEST(v)) {
3809 smaller = 0;
3810 }
3811 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
3812 const VALUE zero = INT2FIX(0);
3813 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
3814 case 0: return INT2FIX(mid);
3815 case 1: smaller = 0; break;
3816 case -1: smaller = 1;
3817 }
3818 }
3819 else {
3820 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
3821 " (must be numeric, true, false or nil)",
3822 rb_obj_class(v));
3823 }
3824 if (smaller) {
3825 high = mid;
3826 }
3827 else {
3828 low = mid + 1;
3829 }
3830 }
3831 if (!satisfied) return Qnil;
3832 return INT2FIX(low);
3833}
3834
3835
3836static VALUE
3837sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3838{
3839 return rb_yield(i);
3840}
3841
3842/*
3843 * call-seq:
3844 * sort_by! {|element| ... } -> self
3845 * sort_by! -> new_enumerator
3846 *
3847 * With a block given, sorts the elements of +self+ in place;
3848 * returns self.
3849 *
3850 * Calls the block with each successive element;
3851 * sorts elements based on the values returned from the block:
3852 *
3853 * a = ['aaaa', 'bbb', 'cc', 'd']
3854 * a.sort_by! {|element| element.size }
3855 * a # => ["d", "cc", "bbb", "aaaa"]
3856 *
3857 * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
3858 *
3859 * With no block given, returns a new Enumerator.
3860 *
3861 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
3862 */
3863
3864static VALUE
3865rb_ary_sort_by_bang(VALUE ary)
3866{
3867 VALUE sorted;
3868
3869 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3870 rb_ary_modify(ary);
3871 if (RARRAY_LEN(ary) > 1) {
3872 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3873 rb_ary_replace(ary, sorted);
3874 }
3875 return ary;
3876}
3877
3878
3879/*
3880 * call-seq:
3881 * collect {|element| ... } -> new_array
3882 * collect -> new_enumerator
3883 * map {|element| ... } -> new_array
3884 * map -> new_enumerator
3885 *
3886 * With a block given, calls the block with each element of +self+;
3887 * returns a new array whose elements are the return values from the block:
3888 *
3889 * a = [:foo, 'bar', 2]
3890 * a1 = a.map {|element| element.class }
3891 * a1 # => [Symbol, String, Integer]
3892 *
3893 * With no block given, returns a new Enumerator.
3894 *
3895 * Related: #collect!;
3896 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3897 */
3898
3899static VALUE
3900rb_ary_collect(VALUE ary)
3901{
3902 long i;
3903 VALUE collect;
3904
3905 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3906 collect = rb_ary_new2(RARRAY_LEN(ary));
3907 for (i = 0; i < RARRAY_LEN(ary); i++) {
3908 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3909 }
3910 return collect;
3911}
3912
3913
3914/*
3915 * call-seq:
3916 * collect! {|element| ... } -> self
3917 * collect! -> new_enumerator
3918 * map! {|element| ... } -> self
3919 * map! -> new_enumerator
3920 *
3921 * With a block given, calls the block with each element of +self+
3922 * and replaces the element with the block's return value;
3923 * returns +self+:
3924 *
3925 * a = [:foo, 'bar', 2]
3926 * a.map! { |element| element.class } # => [Symbol, String, Integer]
3927 *
3928 * With no block given, returns a new Enumerator.
3929 *
3930 * Related: #collect;
3931 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
3932 */
3933
3934static VALUE
3935rb_ary_collect_bang(VALUE ary)
3936{
3937 long i;
3938
3939 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3940 rb_ary_modify(ary);
3941 for (i = 0; i < RARRAY_LEN(ary); i++) {
3942 rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
3943 }
3944 return ary;
3945}
3946
3947VALUE
3948rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3949{
3950 VALUE result = rb_ary_new2(argc);
3951 long beg, len, i, j;
3952
3953 for (i=0; i<argc; i++) {
3954 if (FIXNUM_P(argv[i])) {
3955 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3956 continue;
3957 }
3958 /* check if idx is Range */
3959 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3960 long end = olen < beg+len ? olen : beg+len;
3961 for (j = beg; j < end; j++) {
3962 rb_ary_push(result, (*func)(obj, j));
3963 }
3964 if (beg + len > j)
3965 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3966 continue;
3967 }
3968 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3969 }
3970 return result;
3971}
3972
3973static VALUE
3974append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3975{
3976 long beg, len;
3977 if (FIXNUM_P(idx)) {
3978 beg = FIX2LONG(idx);
3979 }
3980 /* check if idx is Range */
3981 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3982 if (len > 0) {
3983 // rb_range_beg_len may run arbitrary code that modifies ary, so we
3984 // need to re-calculate olen
3985 const long olen = RARRAY_LEN(ary);
3986 const VALUE *const src = RARRAY_CONST_PTR(ary);
3987 const long end = beg + len;
3988 const long prevlen = RARRAY_LEN(result);
3989 if (beg < olen) {
3990 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3991 }
3992 if (end > olen) {
3993 rb_ary_store(result, prevlen + len - 1, Qnil);
3994 }
3995 }
3996 return result;
3997 }
3998 else {
3999 beg = NUM2LONG(idx);
4000 }
4001 return rb_ary_push(result, rb_ary_entry(ary, beg));
4002}
4003
4004/*
4005 * call-seq:
4006 * values_at(*specifiers) -> new_array
4007 *
4008 * Returns elements from +self+ in a new array; does not modify +self+.
4009 *
4010 * The objects included in the returned array are the elements of +self+
4011 * selected by the given +specifiers+,
4012 * each of which must be a numeric index or a Range.
4013 *
4014 * In brief:
4015 *
4016 * a = ['a', 'b', 'c', 'd']
4017 *
4018 * # Index specifiers.
4019 * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat.
4020 * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
4021 * a.values_at(-50, 50) # => [nil, nil] # Outside of self.
4022 *
4023 * # Range specifiers.
4024 * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end.
4025 * a.values_at(1...3) # => ["b", "c"] # End excluded.
4026 * a.values_at(3..1) # => [] # No such elements.
4027 *
4028 * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards.
4029 * a.values_at(-50..3) # Raises RangeError.
4030 *
4031 * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards.
4032 * a.values_at(1..-50) # => [] # No such elements.
4033 *
4034 * # Mixture of specifiers.
4035 * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]
4036 *
4037 * With no +specifiers+ given, returns a new empty array:
4038 *
4039 * a = ['a', 'b', 'c', 'd']
4040 * a.values_at # => []
4041 *
4042 * For each numeric specifier +index+, includes an element:
4043 *
4044 * - For each non-negative numeric specifier +index+ that is in-range (less than <tt>self.size</tt>),
4045 * includes the element at offset +index+:
4046 *
4047 * a.values_at(0, 2) # => ["a", "c"]
4048 * a.values_at(0.1, 2.9) # => ["a", "c"]
4049 *
4050 * - For each negative numeric +index+ that is in-range (greater than or equal to <tt>- self.size</tt>),
4051 * counts backwards from the end of +self+:
4052 *
4053 * a.values_at(-1, -4) # => ["d", "a"]
4054 *
4055 * The given indexes may be in any order, and may repeat:
4056 *
4057 * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]
4058 *
4059 * For each +index+ that is out-of-range, includes +nil+:
4060 *
4061 * a.values_at(4, -5) # => [nil, nil]
4062 *
4063 * For each Range specifier +range+, includes elements
4064 * according to <tt>range.begin</tt> and <tt>range.end</tt>:
4065 *
4066 * - If both <tt>range.begin</tt> and <tt>range.end</tt>
4067 * are non-negative and in-range (less than <tt>self.size</tt>),
4068 * includes elements from index <tt>range.begin</tt>
4069 * through <tt>range.end - 1</tt> (if <tt>range.exclude_end?</tt>),
4070 * or through <tt>range.end</tt> (otherwise):
4071 *
4072 * a.values_at(1..2) # => ["b", "c"]
4073 * a.values_at(1...2) # => ["b"]
4074 *
4075 * - If <tt>range.begin</tt> is negative and in-range (greater than or equal to <tt>- self.size</tt>),
4076 * counts backwards from the end of +self+:
4077 *
4078 * a.values_at(-2..3) # => ["c", "d"]
4079 *
4080 * - If <tt>range.begin</tt> is negative and out-of-range, raises an exception:
4081 *
4082 * a.values_at(-5..3) # Raises RangeError.
4083 *
4084 * - If <tt>range.end</tt> is positive and out-of-range,
4085 * extends the returned array with +nil+ elements:
4086 *
4087 * a.values_at(1..5) # => ["b", "c", "d", nil, nil]
4088 *
4089 * - If <tt>range.end</tt> is negative and in-range,
4090 * counts backwards from the end of +self+:
4091 *
4092 * a.values_at(1..-2) # => ["b", "c"]
4093 *
4094 * - If <tt>range.end</tt> is negative and out-of-range,
4095 * returns an empty array:
4096 *
4097 * a.values_at(1..-5) # => []
4098 *
4099 * The given ranges may be in any order and may repeat:
4100 *
4101 * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"]
4102 *
4103 * The given specifiers may be any mixture of indexes and ranges:
4104 *
4105 * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"]
4106 *
4107 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4108 */
4109
4110static VALUE
4111rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
4112{
4113 long i, olen = RARRAY_LEN(ary);
4114 VALUE result = rb_ary_new_capa(argc);
4115 for (i = 0; i < argc; ++i) {
4116 append_values_at_single(result, ary, olen, argv[i]);
4117 }
4118 RB_GC_GUARD(ary);
4119 return result;
4120}
4121
4122
4123/*
4124 * call-seq:
4125 * select {|element| ... } -> new_array
4126 * select -> new_enumerator
4127 * filter {|element| ... } -> new_array
4128 * filter -> new_enumerator
4129 *
4130 * With a block given, calls the block with each element of +self+;
4131 * returns a new array containing those elements of +self+
4132 * for which the block returns a truthy value:
4133 *
4134 * a = [:foo, 'bar', 2, :bam]
4135 * a.select {|element| element.to_s.start_with?('b') }
4136 * # => ["bar", :bam]
4137 *
4138 * With no block given, returns a new Enumerator.
4139 *
4140 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4141 */
4142
4143static VALUE
4144rb_ary_select(VALUE ary)
4145{
4146 VALUE result;
4147 long i;
4148
4149 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4150 result = rb_ary_new2(RARRAY_LEN(ary));
4151 for (i = 0; i < RARRAY_LEN(ary); i++) {
4152 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
4153 rb_ary_push(result, rb_ary_elt(ary, i));
4154 }
4155 }
4156 return result;
4157}
4158
4159struct select_bang_arg {
4160 VALUE ary;
4161 long len[2];
4162};
4163
4164static VALUE
4165select_bang_i(VALUE a)
4166{
4167 volatile struct select_bang_arg *arg = (void *)a;
4168 VALUE ary = arg->ary;
4169 long i1, i2;
4170
4171 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4172 VALUE v = RARRAY_AREF(ary, i1);
4173 if (!RTEST(rb_yield(v))) continue;
4174 if (i1 != i2) {
4175 rb_ary_store(ary, i2, v);
4176 }
4177 arg->len[1] = ++i2;
4178 }
4179 return (i1 == i2) ? Qnil : ary;
4180}
4181
4182static VALUE
4183select_bang_ensure(VALUE a)
4184{
4185 volatile struct select_bang_arg *arg = (void *)a;
4186 VALUE ary = arg->ary;
4187 long len = RARRAY_LEN(ary);
4188 long i1 = arg->len[0], i2 = arg->len[1];
4189
4190 if (i2 < len && i2 < i1) {
4191 long tail = 0;
4192 rb_ary_modify(ary);
4193 if (i1 < len) {
4194 tail = len - i1;
4195 RARRAY_PTR_USE(ary, ptr, {
4196 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
4197 });
4198 }
4199 ARY_SET_LEN(ary, i2 + tail);
4200 }
4201 return ary;
4202}
4203
4204/*
4205 * call-seq:
4206 * select! {|element| ... } -> self or nil
4207 * select! -> new_enumerator
4208 * filter! {|element| ... } -> self or nil
4209 * filter! -> new_enumerator
4210 *
4211 * With a block given, calls the block with each element of +self+;
4212 * removes from +self+ those elements for which the block returns +false+ or +nil+.
4213 *
4214 * Returns +self+ if any elements were removed:
4215 *
4216 * a = [:foo, 'bar', 2, :bam]
4217 * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
4218 *
4219 * Returns +nil+ if no elements were removed.
4220 *
4221 * With no block given, returns a new Enumerator.
4222 *
4223 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4224 */
4225
4226static VALUE
4227rb_ary_select_bang(VALUE ary)
4228{
4229 struct select_bang_arg args;
4230
4231 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4232 rb_ary_modify(ary);
4233
4234 args.ary = ary;
4235 args.len[0] = args.len[1] = 0;
4236 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4237}
4238
4239/*
4240 * call-seq:
4241 * keep_if {|element| ... } -> self
4242 * keep_if -> new_enumerator
4243 *
4244 * With a block given, calls the block with each element of +self+;
4245 * removes the element from +self+ if the block does not return a truthy value:
4246 *
4247 * a = [:foo, 'bar', 2, :bam]
4248 * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
4249 *
4250 * With no block given, returns a new Enumerator.
4251 *
4252 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4253 */
4254
4255static VALUE
4256rb_ary_keep_if(VALUE ary)
4257{
4258 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4259 rb_ary_select_bang(ary);
4260 return ary;
4261}
4262
4263static void
4264ary_resize_smaller(VALUE ary, long len)
4265{
4266 rb_ary_modify(ary);
4267 if (RARRAY_LEN(ary) > len) {
4268 ARY_SET_LEN(ary, len);
4269 if (len * 2 < ARY_CAPA(ary) &&
4270 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
4271 ary_resize_capa(ary, len * 2);
4272 }
4273 }
4274}
4275
4276/*
4277 * call-seq:
4278 * delete(object) -> last_removed_object
4279 * delete(object) {|element| ... } -> last_removed_object or block_return
4280 *
4281 * Removes zero or more elements from +self+.
4282 *
4283 * With no block given,
4284 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
4285 * returns the last removed element:
4286 *
4287 * a = [0, 1, 2, 2.0]
4288 * a.delete(2) # => 2.0
4289 * a # => [0, 1]
4290 *
4291 * Returns +nil+ if no elements removed:
4292 *
4293 * a.delete(2) # => nil
4294 *
4295 * With a block given,
4296 * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
4297 *
4298 * If any such elements are found, ignores the block
4299 * and returns the last removed element:
4300 *
4301 * a = [0, 1, 2, 2.0]
4302 * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
4303 * a # => [0, 1]
4304 *
4305 * If no such element is found, returns the block's return value:
4306 *
4307 * a.delete(2) {|element| "Element #{element} not found." }
4308 * # => "Element 2 not found."
4309 *
4310 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4311 */
4312
4313VALUE
4314rb_ary_delete(VALUE ary, VALUE item)
4315{
4316 VALUE v = item;
4317 long i1, i2;
4318
4319 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4320 VALUE e = RARRAY_AREF(ary, i1);
4321
4322 if (rb_equal(e, item)) {
4323 v = e;
4324 continue;
4325 }
4326 if (i1 != i2) {
4327 rb_ary_store(ary, i2, e);
4328 }
4329 i2++;
4330 }
4331 if (RARRAY_LEN(ary) == i2) {
4332 if (rb_block_given_p()) {
4333 return rb_yield(item);
4334 }
4335 return Qnil;
4336 }
4337
4338 ary_resize_smaller(ary, i2);
4339
4340 ary_verify(ary);
4341 return v;
4342}
4343
4344void
4345rb_ary_delete_same(VALUE ary, VALUE item)
4346{
4347 long i1, i2;
4348
4349 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
4350 VALUE e = RARRAY_AREF(ary, i1);
4351
4352 if (e == item) {
4353 continue;
4354 }
4355 if (i1 != i2) {
4356 rb_ary_store(ary, i2, e);
4357 }
4358 i2++;
4359 }
4360 if (RARRAY_LEN(ary) == i2) {
4361 return;
4362 }
4363
4364 ary_resize_smaller(ary, i2);
4365}
4366
4367VALUE
4368rb_ary_delete_at(VALUE ary, long pos)
4369{
4370 long len = RARRAY_LEN(ary);
4371 VALUE del;
4372
4373 if (pos >= len) return Qnil;
4374 if (pos < 0) {
4375 pos += len;
4376 if (pos < 0) return Qnil;
4377 }
4378
4379 rb_ary_modify(ary);
4380 del = RARRAY_AREF(ary, pos);
4381 RARRAY_PTR_USE(ary, ptr, {
4382 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
4383 });
4384 ARY_INCREASE_LEN(ary, -1);
4385 ary_verify(ary);
4386 return del;
4387}
4388
4389/*
4390 * call-seq:
4391 * delete_at(index) -> removed_object or nil
4392 *
4393 * Removes the element of +self+ at the given +index+, which must be an
4394 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
4395 *
4396 * When +index+ is non-negative, deletes the element at offset +index+:
4397 *
4398 * a = [:foo, 'bar', 2]
4399 * a.delete_at(1) # => "bar"
4400 * a # => [:foo, 2]
4401 *
4402 * When +index+ is negative, counts backward from the end of the array:
4403 *
4404 * a = [:foo, 'bar', 2]
4405 * a.delete_at(-2) # => "bar"
4406 * a # => [:foo, 2]
4407 *
4408 * When +index+ is out of range, returns +nil+.
4409 *
4410 * a = [:foo, 'bar', 2]
4411 * a.delete_at(3) # => nil
4412 * a.delete_at(-4) # => nil
4413 *
4414 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4415 */
4416
4417static VALUE
4418rb_ary_delete_at_m(VALUE ary, VALUE pos)
4419{
4420 return rb_ary_delete_at(ary, NUM2LONG(pos));
4421}
4422
4423static VALUE
4424ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
4425{
4426 const long orig_len = RARRAY_LEN(ary);
4427
4428 if (len < 0) {
4429 return Qnil;
4430 }
4431 else if (pos < -orig_len) {
4432 return Qnil;
4433 }
4434 else if (pos < 0) {
4435 pos += orig_len;
4436 }
4437 else if (orig_len < pos) {
4438 return Qnil;
4439 }
4440 if (orig_len < pos + len) {
4441 len = orig_len - pos;
4442 }
4443 if (len == 0) {
4444 return rb_ary_new2(0);
4445 }
4446 else {
4447 VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
4448 ary_splice(ary, pos, len, 0, 0, FALSE);
4449 return arg2;
4450 }
4451}
4452
4453/*
4454 * call-seq:
4455 * slice!(index) -> object or nil
4456 * slice!(start, length) -> new_array or nil
4457 * slice!(range) -> new_array or nil
4458 *
4459 * Removes and returns elements from +self+.
4460 *
4461 * With numeric argument +index+ given,
4462 * removes and returns the element at offset +index+:
4463 *
4464 * a = ['a', 'b', 'c', 'd']
4465 * a.slice!(2) # => "c"
4466 * a # => ["a", "b", "d"]
4467 * a.slice!(2.1) # => "d"
4468 * a # => ["a", "b"]
4469 *
4470 * If +index+ is negative, counts backwards from the end of +self+:
4471 *
4472 * a = ['a', 'b', 'c', 'd']
4473 * a.slice!(-2) # => "c"
4474 * a # => ["a", "b", "d"]
4475 *
4476 * If +index+ is out of range, returns +nil+.
4477 *
4478 * With numeric arguments +start+ and +length+ given,
4479 * removes +length+ elements from +self+ beginning at zero-based offset +start+;
4480 * returns the removed objects in a new array:
4481 *
4482 * a = ['a', 'b', 'c', 'd']
4483 * a.slice!(1, 2) # => ["b", "c"]
4484 * a # => ["a", "d"]
4485 * a.slice!(0.1, 1.1) # => ["a"]
4486 * a # => ["d"]
4487 *
4488 * If +start+ is negative, counts backwards from the end of +self+:
4489 *
4490 * a = ['a', 'b', 'c', 'd']
4491 * a.slice!(-2, 1) # => ["c"]
4492 * a # => ["a", "b", "d"]
4493 *
4494 * If +start+ is out-of-range, returns +nil+:
4495 *
4496 * a = ['a', 'b', 'c', 'd']
4497 * a.slice!(5, 1) # => nil
4498 * a.slice!(-5, 1) # => nil
4499 *
4500 * If <tt>start + length</tt> exceeds the array size,
4501 * removes and returns all elements from offset +start+ to the end:
4502 *
4503 * a = ['a', 'b', 'c', 'd']
4504 * a.slice!(2, 50) # => ["c", "d"]
4505 * a # => ["a", "b"]
4506 *
4507 * If <tt>start == a.size</tt> and +length+ is non-negative,
4508 * returns a new empty array.
4509 *
4510 * If +length+ is negative, returns +nil+.
4511 *
4512 * With Range argument +range+ given,
4513 * treats <tt>range.min</tt> as +start+ (as above)
4514 * and <tt>range.size</tt> as +length+ (as above):
4515 *
4516 * a = ['a', 'b', 'c', 'd']
4517 * a.slice!(1..2) # => ["b", "c"]
4518 * a # => ["a", "d"]
4519 *
4520 * If <tt>range.start == a.size</tt>, returns a new empty array:
4521 *
4522 * a = ['a', 'b', 'c', 'd']
4523 * a.slice!(4..5) # => []
4524 *
4525 * If <tt>range.start</tt> is larger than the array size, returns +nil+:
4526 *
4527 * a = ['a', 'b', 'c', 'd']
4528 a.slice!(5..6) # => nil
4529 *
4530 * If <tt>range.start</tt> is negative,
4531 * calculates the start index by counting backwards from the end of +self+:
4532 *
4533 * a = ['a', 'b', 'c', 'd']
4534 * a.slice!(-2..2) # => ["c"]
4535 *
4536 * If <tt>range.end</tt> is negative,
4537 * calculates the end index by counting backwards from the end of +self+:
4538 *
4539 * a = ['a', 'b', 'c', 'd']
4540 * a.slice!(0..-2) # => ["a", "b", "c"]
4541 *
4542 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4543 */
4544
4545static VALUE
4546rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
4547{
4548 VALUE arg1;
4549 long pos, len;
4550
4551 rb_ary_modify_check(ary);
4552 rb_check_arity(argc, 1, 2);
4553 arg1 = argv[0];
4554
4555 if (argc == 2) {
4556 pos = NUM2LONG(argv[0]);
4557 len = NUM2LONG(argv[1]);
4558 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4559 }
4560
4561 if (!FIXNUM_P(arg1)) {
4562 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
4563 case Qtrue:
4564 /* valid range */
4565 return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
4566 case Qnil:
4567 /* invalid range */
4568 return Qnil;
4569 default:
4570 /* not a range */
4571 break;
4572 }
4573 }
4574
4575 return rb_ary_delete_at(ary, NUM2LONG(arg1));
4576}
4577
4578static VALUE
4579ary_reject(VALUE orig, VALUE result)
4580{
4581 long i;
4582
4583 for (i = 0; i < RARRAY_LEN(orig); i++) {
4584 VALUE v = RARRAY_AREF(orig, i);
4585
4586 if (!RTEST(rb_yield(v))) {
4587 rb_ary_push(result, v);
4588 }
4589 }
4590 return result;
4591}
4592
4593static VALUE
4594reject_bang_i(VALUE a)
4595{
4596 volatile struct select_bang_arg *arg = (void *)a;
4597 VALUE ary = arg->ary;
4598 long i1, i2;
4599
4600 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
4601 VALUE v = RARRAY_AREF(ary, i1);
4602 if (RTEST(rb_yield(v))) continue;
4603 if (i1 != i2) {
4604 rb_ary_store(ary, i2, v);
4605 }
4606 arg->len[1] = ++i2;
4607 }
4608 return (i1 == i2) ? Qnil : ary;
4609}
4610
4611static VALUE
4612ary_reject_bang(VALUE ary)
4613{
4614 struct select_bang_arg args;
4615 rb_ary_modify_check(ary);
4616 args.ary = ary;
4617 args.len[0] = args.len[1] = 0;
4618 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
4619}
4620
4621/*
4622 * call-seq:
4623 * reject! {|element| ... } -> self or nil
4624 * reject! -> new_enumerator
4625 *
4626 * With a block given, calls the block with each element of +self+;
4627 * removes each element for which the block returns a truthy value.
4628 *
4629 * Returns +self+ if any elements removed:
4630 *
4631 * a = [:foo, 'bar', 2, 'bat']
4632 * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4633 *
4634 * Returns +nil+ if no elements removed.
4635 *
4636 * With no block given, returns a new Enumerator.
4637 *
4638 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4639 */
4640
4641static VALUE
4642rb_ary_reject_bang(VALUE ary)
4643{
4644 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4645 rb_ary_modify(ary);
4646 return ary_reject_bang(ary);
4647}
4648
4649/*
4650 * call-seq:
4651 * reject {|element| ... } -> new_array
4652 * reject -> new_enumerator
4653 *
4654 * With a block given, returns a new array whose elements are all those from +self+
4655 * for which the block returns +false+ or +nil+:
4656 *
4657 * a = [:foo, 'bar', 2, 'bat']
4658 * a1 = a.reject {|element| element.to_s.start_with?('b') }
4659 * a1 # => [:foo, 2]
4660 *
4661 * With no block given, returns a new Enumerator.
4662 *
4663 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
4664 */
4665
4666static VALUE
4667rb_ary_reject(VALUE ary)
4668{
4669 VALUE rejected_ary;
4670
4671 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4672 rejected_ary = rb_ary_new();
4673 ary_reject(ary, rejected_ary);
4674 return rejected_ary;
4675}
4676
4677/*
4678 * call-seq:
4679 * delete_if {|element| ... } -> self
4680 * delete_if -> new_numerator
4681 *
4682 * With a block given, calls the block with each element of +self+;
4683 * removes the element if the block returns a truthy value;
4684 * returns +self+:
4685 *
4686 * a = [:foo, 'bar', 2, 'bat']
4687 * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
4688 *
4689 * With no block given, returns a new Enumerator.
4690 *
4691 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4692 */
4693
4694static VALUE
4695rb_ary_delete_if(VALUE ary)
4696{
4697 ary_verify(ary);
4698 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
4699 ary_reject_bang(ary);
4700 return ary;
4701}
4702
4703static VALUE
4704take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
4705{
4706 VALUE *args = (VALUE *)cbarg;
4707 if (argc > 1) val = rb_ary_new4(argc, argv);
4708 rb_ary_push(args[0], val);
4709 if (--args[1] == 0) rb_iter_break();
4710 return Qnil;
4711}
4712
4713static VALUE
4714take_items(VALUE obj, long n)
4715{
4716 VALUE result = rb_check_array_type(obj);
4717 VALUE args[2];
4718
4719 if (n == 0) return result;
4720 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
4721 result = rb_ary_new2(n);
4722 args[0] = result; args[1] = (VALUE)n;
4723 if (UNDEF_P(rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args)))
4724 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
4725 rb_obj_class(obj));
4726 return result;
4727}
4728
4729
4730/*
4731 * call-seq:
4732 * zip(*other_arrays) -> new_array
4733 * zip(*other_arrays) {|sub_array| ... } -> nil
4734 *
4735 * With no block given, combines +self+ with the collection of +other_arrays+;
4736 * returns a new array of sub-arrays:
4737 *
4738 * [0, 1].zip(['zero', 'one'], [:zero, :one])
4739 * # => [[0, "zero", :zero], [1, "one", :one]]
4740 *
4741 * Returned:
4742 *
4743 * - The outer array is of size <tt>self.size</tt>.
4744 * - Each sub-array is of size <tt>other_arrays.size + 1</tt>.
4745 * - The _nth_ sub-array contains (in order):
4746 *
4747 * - The _nth_ element of +self+.
4748 * - The _nth_ element of each of the other arrays, as available.
4749 *
4750 * Example:
4751 *
4752 * a = [0, 1]
4753 * zipped = a.zip(['zero', 'one'], [:zero, :one])
4754 * # => [[0, "zero", :zero], [1, "one", :one]]
4755 * zipped.size # => 2 # Same size as a.
4756 * zipped.first.size # => 3 # Size of other arrays plus 1.
4757 *
4758 * When the other arrays are all the same size as +self+,
4759 * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays
4760 * (including +self+), with no omissions or additions:
4761 *
4762 * a = [:a0, :a1, :a2, :a3]
4763 * b = [:b0, :b1, :b2, :b3]
4764 * c = [:c0, :c1, :c2, :c3]
4765 * d = a.zip(b, c)
4766 * pp d
4767 * # =>
4768 * [[:a0, :b0, :c0],
4769 * [:a1, :b1, :c1],
4770 * [:a2, :b2, :c2],
4771 * [:a3, :b3, :c3]]
4772 *
4773 * When one of the other arrays is smaller than +self+,
4774 * pads the corresponding sub-array with +nil+ elements:
4775 *
4776 * a = [:a0, :a1, :a2, :a3]
4777 * b = [:b0, :b1, :b2]
4778 * c = [:c0, :c1]
4779 * d = a.zip(b, c)
4780 * pp d
4781 * # =>
4782 * [[:a0, :b0, :c0],
4783 * [:a1, :b1, :c1],
4784 * [:a2, :b2, nil],
4785 * [:a3, nil, nil]]
4786 *
4787 * When one of the other arrays is larger than +self+,
4788 * _ignores_ its trailing elements:
4789 *
4790 * a = [:a0, :a1, :a2, :a3]
4791 * b = [:b0, :b1, :b2, :b3, :b4]
4792 * c = [:c0, :c1, :c2, :c3, :c4, :c5]
4793 * d = a.zip(b, c)
4794 * pp d
4795 * # =>
4796 * [[:a0, :b0, :c0],
4797 * [:a1, :b1, :c1],
4798 * [:a2, :b2, :c2],
4799 * [:a3, :b3, :c3]]
4800 *
4801 * With a block given, calls the block with each of the other arrays;
4802 * returns +nil+:
4803 *
4804 * d = []
4805 * a = [:a0, :a1, :a2, :a3]
4806 * b = [:b0, :b1, :b2, :b3]
4807 * c = [:c0, :c1, :c2, :c3]
4808 * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
4809 * pp d
4810 * # =>
4811 * [[:c0, :b0, :a0],
4812 * [:c1, :b1, :a1],
4813 * [:c2, :b2, :a2],
4814 * [:c3, :b3, :a3]]
4815 *
4816 * For an *object* in *other_arrays* that is not actually an array,
4817 * forms the "other array" as <tt>object.to_ary</tt>, if defined,
4818 * or as <tt>object.each.to_a</tt> otherwise.
4819 *
4820 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4821 */
4822
4823static VALUE
4824rb_ary_zip(int argc, VALUE *argv, VALUE ary)
4825{
4826 int i, j;
4827 long len = RARRAY_LEN(ary);
4828 VALUE result = Qnil;
4829
4830 for (i=0; i<argc; i++) {
4831 argv[i] = take_items(argv[i], len);
4832 }
4833
4834 if (rb_block_given_p()) {
4835 int arity = rb_block_arity();
4836
4837 if (arity > 1) {
4838 VALUE work, *tmp;
4839
4840 tmp = ALLOCV_N(VALUE, work, argc+1);
4841
4842 for (i=0; i<RARRAY_LEN(ary); i++) {
4843 tmp[0] = RARRAY_AREF(ary, i);
4844 for (j=0; j<argc; j++) {
4845 tmp[j+1] = rb_ary_elt(argv[j], i);
4846 }
4847 rb_yield_values2(argc+1, tmp);
4848 }
4849
4850 if (work) ALLOCV_END(work);
4851 }
4852 else {
4853 for (i=0; i<RARRAY_LEN(ary); i++) {
4854 VALUE tmp = rb_ary_new2(argc+1);
4855
4856 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4857 for (j=0; j<argc; j++) {
4858 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4859 }
4860 rb_yield(tmp);
4861 }
4862 }
4863 }
4864 else {
4865 result = rb_ary_new_capa(len);
4866
4867 for (i=0; i<RARRAY_LEN(ary); i++) {
4868 VALUE tmp = rb_ary_new_capa(argc+1);
4869
4870 rb_ary_push(tmp, RARRAY_AREF(ary, i));
4871 for (j=0; j<argc; j++) {
4872 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
4873 }
4874 rb_ary_push(result, tmp);
4875 }
4876 }
4877
4878 return result;
4879}
4880
4881/*
4882 * call-seq:
4883 * transpose -> new_array
4884 *
4885 * Returns a new array that is +self+
4886 * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
4887 *
4888 * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
4889 * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
4890 *
4891 * The elements of +self+ must all be the same size.
4892 *
4893 * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
4894 */
4895
4896static VALUE
4897rb_ary_transpose(VALUE ary)
4898{
4899 long elen = -1, alen, i, j;
4900 VALUE tmp, result = 0;
4901
4902 alen = RARRAY_LEN(ary);
4903 if (alen == 0) return rb_ary_dup(ary);
4904 for (i=0; i<alen; i++) {
4905 tmp = to_ary(rb_ary_elt(ary, i));
4906 if (elen < 0) { /* first element */
4907 elen = RARRAY_LEN(tmp);
4908 result = rb_ary_new2(elen);
4909 for (j=0; j<elen; j++) {
4910 rb_ary_store(result, j, rb_ary_new2(alen));
4911 }
4912 }
4913 else if (elen != RARRAY_LEN(tmp)) {
4914 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
4915 RARRAY_LEN(tmp), elen);
4916 }
4917 for (j=0; j<elen; j++) {
4918 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
4919 }
4920 }
4921 return result;
4922}
4923
4924/*
4925 * call-seq:
4926 * initialize_copy(other_array) -> self
4927 * replace(other_array) -> self
4928 *
4929 * Replaces the elements of +self+ with the elements of +other_array+, which must be an
4930 * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
4931 * returns +self+:
4932 *
4933 * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
4934 * a.replace(['d', 'e']) # => ["d", "e"]
4935 *
4936 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
4937 */
4938
4939VALUE
4940rb_ary_replace(VALUE copy, VALUE orig)
4941{
4942 rb_ary_modify_check(copy);
4943 orig = to_ary(orig);
4944 if (copy == orig) return copy;
4945
4946 rb_ary_reset(copy);
4947
4948 /* orig has enough space to embed the contents of orig. */
4949 if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
4950 RUBY_ASSERT(ARY_EMBED_P(copy));
4951 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
4952 ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
4953 }
4954 /* orig is embedded but copy does not have enough space to embed the
4955 * contents of orig. */
4956 else if (ARY_EMBED_P(orig)) {
4957 long len = ARY_EMBED_LEN(orig);
4958 VALUE *ptr = ary_heap_alloc_buffer(len);
4959
4960 FL_UNSET_EMBED(copy);
4961 ARY_SET_PTR(copy, ptr);
4962 ARY_SET_LEN(copy, len);
4963 ARY_SET_CAPA(copy, len);
4964
4965 // No allocation and exception expected that could leave `copy` in a
4966 // bad state from the edits above.
4967 ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
4968 }
4969 /* Otherwise, orig is on heap and copy does not have enough space to embed
4970 * the contents of orig. */
4971 else {
4972 VALUE shared_root = ary_make_shared(orig);
4973 FL_UNSET_EMBED(copy);
4974 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
4975 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
4976 rb_ary_set_shared(copy, shared_root);
4977
4978 RUBY_ASSERT(RB_OBJ_SHAREABLE_P(copy) ? RB_OBJ_SHAREABLE_P(shared_root) : 1);
4979 }
4980 ary_verify(copy);
4981 return copy;
4982}
4983
4984/*
4985 * call-seq:
4986 * clear -> self
4987 *
4988 * Removes all elements from +self+; returns +self+:
4989 *
4990 * a = [:foo, 'bar', 2]
4991 * a.clear # => []
4992 *
4993 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
4994 */
4995
4996VALUE
4998{
4999 rb_ary_modify_check(ary);
5000 if (ARY_SHARED_P(ary)) {
5001 rb_ary_unshare(ary);
5002 FL_SET_EMBED(ary);
5003 ARY_SET_EMBED_LEN(ary, 0);
5004 }
5005 else {
5006 ARY_SET_LEN(ary, 0);
5007 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
5008 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
5009 }
5010 }
5011 ary_verify(ary);
5012 return ary;
5013}
5014
5015/*
5016 * call-seq:
5017 * fill(object, start = nil, count = nil) -> self
5018 * fill(object, range) -> self
5019 * fill(start = nil, count = nil) {|element| ... } -> self
5020 * fill(range) {|element| ... } -> self
5021 *
5022 * Replaces selected elements in +self+;
5023 * may add elements to +self+;
5024 * always returns +self+ (never a new array).
5025 *
5026 * In brief:
5027 *
5028 * # Non-negative start.
5029 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
5030 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5031 *
5032 * # Extends with specified values if necessary.
5033 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
5034 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
5035 *
5036 * # Fills with nils if necessary.
5037 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
5038 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
5039 *
5040 * # For negative start, counts backwards from the end.
5041 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
5042 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
5043 *
5044 * # Range.
5045 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
5046 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5047 *
5048 * When arguments +start+ and +count+ are given,
5049 * they select the elements of +self+ to be replaced;
5050 * each must be an
5051 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
5052 * (or +nil+):
5053 *
5054 * - +start+ specifies the zero-based offset of the first element to be replaced;
5055 * +nil+ means zero.
5056 * - +count+ is the number of consecutive elements to be replaced;
5057 * +nil+ means "all the rest."
5058 *
5059 * With argument +object+ given,
5060 * that one object is used for all replacements:
5061 *
5062 * o = Object.new # => #<Object:0x0000014e7bff7600>
5063 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
5064 * a.fill(o, 1, 2)
5065 * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
5066 *
5067 * With a block given, the block is called once for each element to be replaced;
5068 * the value passed to the block is the _index_ of the element to be replaced
5069 * (not the element itself);
5070 * the block's return value replaces the element:
5071 *
5072 * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
5073 * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
5074 *
5075 * For arguments +start+ and +count+:
5076 *
5077 * - If +start+ is non-negative,
5078 * replaces +count+ elements beginning at offset +start+:
5079 *
5080 * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
5081 * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
5082 * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
5083 *
5084 * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
5085 * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5086 * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
5087 *
5088 * Extends +self+ if necessary:
5089 *
5090 * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
5091 * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
5092 *
5093 * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
5094 * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
5095 *
5096 * Fills with +nil+ if necessary:
5097 *
5098 * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
5099 * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
5100 *
5101 * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
5102 * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
5103 *
5104 * Does nothing if +count+ is non-positive:
5105 *
5106 * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
5107 * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
5108 * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
5109 *
5110 * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5111 * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5112 * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5113 *
5114 * - If +start+ is negative, counts backwards from the end of +self+:
5115 *
5116 * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
5117 * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
5118 *
5119 * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
5120 * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
5121 *
5122 * Extends +self+ if necessary:
5123 *
5124 * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
5125 * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
5126 *
5127 * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
5128 * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
5129 *
5130 * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
5131 *
5132 * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
5133 * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
5134 *
5135 * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
5136 * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
5137 *
5138 * Does nothing if +count+ is non-positive:
5139 *
5140 * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
5141 * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
5142 *
5143 * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5144 * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
5145 *
5146 * When argument +range+ is given,
5147 * it must be a Range object whose members are numeric;
5148 * its +begin+ and +end+ values determine the elements of +self+
5149 * to be replaced:
5150 *
5151 * - If both +begin+ and +end+ are positive, they specify the first and last elements
5152 * to be replaced:
5153 *
5154 * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
5155 * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5156 *
5157 * If +end+ is smaller than +begin+, replaces no elements:
5158 *
5159 * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
5160 * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
5161 *
5162 * - If either is negative (or both are negative), counts backwards from the end of +self+:
5163 *
5164 * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
5165 * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
5166 * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
5167 *
5168 * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5169 * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5170 * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
5171 *
5172 * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
5173 *
5174 * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
5175 * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
5176 *
5177 * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
5178 * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
5179 *
5180 * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
5181 * replaces elements to the end of +self+:
5182 *
5183 * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
5184 * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
5185 *
5186 * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
5187 * replaces elements from the beginning of +self+:
5188 *
5189 * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
5190 * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
5191 *
5192 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5193 */
5194
5195static VALUE
5196rb_ary_fill(int argc, VALUE *argv, VALUE ary)
5197{
5198 VALUE item = Qundef, arg1, arg2;
5199 long beg = 0, end = 0, len = 0;
5200
5201 if (rb_block_given_p()) {
5202 rb_scan_args(argc, argv, "02", &arg1, &arg2);
5203 argc += 1; /* hackish */
5204 }
5205 else {
5206 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
5207 }
5208 switch (argc) {
5209 case 1:
5210 beg = 0;
5211 len = RARRAY_LEN(ary);
5212 break;
5213 case 2:
5214 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
5215 break;
5216 }
5217 /* fall through */
5218 case 3:
5219 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
5220 if (beg < 0) {
5221 beg = RARRAY_LEN(ary) + beg;
5222 if (beg < 0) beg = 0;
5223 }
5224 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
5225 break;
5226 }
5227 rb_ary_modify(ary);
5228 if (len < 0) {
5229 return ary;
5230 }
5231 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
5232 rb_raise(rb_eArgError, "argument too big");
5233 }
5234 end = beg + len;
5235 if (RARRAY_LEN(ary) < end) {
5236 if (end >= ARY_CAPA(ary)) {
5237 ary_resize_capa(ary, end);
5238 }
5239 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
5240 ARY_SET_LEN(ary, end);
5241 }
5242
5243 if (UNDEF_P(item)) {
5244 VALUE v;
5245 long i;
5246
5247 for (i=beg; i<end; i++) {
5248 v = rb_yield(LONG2NUM(i));
5249 if (i>=RARRAY_LEN(ary)) break;
5250 ARY_SET(ary, i, v);
5251 }
5252 }
5253 else {
5254 ary_memfill(ary, beg, len, item);
5255 }
5256 return ary;
5257}
5258
5259/*
5260 * call-seq:
5261 * self + other_array -> new_array
5262 *
5263 * Returns a new array containing all elements of +self+
5264 * followed by all elements of +other_array+:
5265 *
5266 * a = [0, 1] + [2, 3]
5267 * a # => [0, 1, 2, 3]
5268 *
5269 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5270 */
5271
5272VALUE
5274{
5275 VALUE z;
5276 long len, xlen, ylen;
5277
5278 y = to_ary(y);
5279 xlen = RARRAY_LEN(x);
5280 ylen = RARRAY_LEN(y);
5281 len = xlen + ylen;
5282 z = rb_ary_new2(len);
5283
5284 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
5285 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
5286 ARY_SET_LEN(z, len);
5287 return z;
5288}
5289
5290static VALUE
5291ary_append(VALUE x, VALUE y)
5292{
5293 if (RARRAY_LEN(y) > 0) {
5294 rb_ary_splice(x, RARRAY_LEN(x), 0, y);
5295 }
5296 return x;
5297}
5298
5299/*
5300 * call-seq:
5301 * concat(*other_arrays) -> self
5302 *
5303 * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
5304 *
5305 * a = [0, 1]
5306 * a.concat(['two', 'three'], [:four, :five], a)
5307 * # => [0, 1, "two", "three", :four, :five, 0, 1]
5308 *
5309 * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
5310 */
5311
5312static VALUE
5313rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
5314{
5315 rb_ary_modify_check(ary);
5316
5317 if (argc == 1) {
5318 rb_ary_concat(ary, argv[0]);
5319 }
5320 else if (argc > 1) {
5321 int i;
5322 VALUE args = rb_ary_hidden_new(argc);
5323 for (i = 0; i < argc; i++) {
5324 rb_ary_concat(args, argv[i]);
5325 }
5326 ary_append(ary, args);
5327 }
5328
5329 ary_verify(ary);
5330 return ary;
5331}
5332
5333VALUE
5335{
5336 return ary_append(x, to_ary(y));
5337}
5338
5339/*
5340 * call-seq:
5341 * self * n -> new_array
5342 * self * string_separator -> new_string
5343 *
5344 * When non-negative integer argument +n+ is given,
5345 * returns a new array built by concatenating +n+ copies of +self+:
5346 *
5347 * a = ['x', 'y']
5348 * a * 3 # => ["x", "y", "x", "y", "x", "y"]
5349 *
5350 * When string argument +string_separator+ is given,
5351 * equivalent to <tt>self.join(string_separator)</tt>:
5352 *
5353 * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
5354 *
5355 */
5356
5357static VALUE
5358rb_ary_times(VALUE ary, VALUE times)
5359{
5360 VALUE ary2, tmp;
5361 const VALUE *ptr;
5362 long t, len;
5363
5364 tmp = rb_check_string_type(times);
5365 if (!NIL_P(tmp)) {
5366 return rb_ary_join(ary, tmp);
5367 }
5368
5369 len = NUM2LONG(times);
5370 if (len == 0) {
5371 ary2 = ary_new(rb_cArray, 0);
5372 goto out;
5373 }
5374 if (len < 0) {
5375 rb_raise(rb_eArgError, "negative argument");
5376 }
5377 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
5378 rb_raise(rb_eArgError, "argument too big");
5379 }
5380 len *= RARRAY_LEN(ary);
5381
5382 ary2 = ary_new(rb_cArray, len);
5383 ARY_SET_LEN(ary2, len);
5384
5385 ptr = RARRAY_CONST_PTR(ary);
5386 t = RARRAY_LEN(ary);
5387 if (0 < t) {
5388 ary_memcpy(ary2, 0, t, ptr);
5389 while (t <= len/2) {
5390 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
5391 t *= 2;
5392 }
5393 if (t < len) {
5394 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
5395 }
5396 }
5397 out:
5398 return ary2;
5399}
5400
5401/*
5402 * call-seq:
5403 * assoc(object) -> found_array or nil
5404 *
5405 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5406 * and <tt>ele[0] == object</tt>:
5407 *
5408 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5409 * a.assoc(4) # => [4, 5, 6]
5410 *
5411 * Returns +nil+ if no such element is found.
5412 *
5413 * Related: Array#rassoc;
5414 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5415 */
5416
5417VALUE
5418rb_ary_assoc(VALUE ary, VALUE key)
5419{
5420 long i;
5421 VALUE v;
5422
5423 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5424 v = rb_check_array_type(RARRAY_AREF(ary, i));
5425 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
5426 rb_equal(RARRAY_AREF(v, 0), key))
5427 return v;
5428 }
5429 return Qnil;
5430}
5431
5432/*
5433 * call-seq:
5434 * rassoc(object) -> found_array or nil
5435 *
5436 * Returns the first element +ele+ in +self+ such that +ele+ is an array
5437 * and <tt>ele[1] == object</tt>:
5438 *
5439 * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
5440 * a.rassoc(4) # => [2, 4]
5441 * a.rassoc(5) # => [4, 5, 6]
5442 *
5443 * Returns +nil+ if no such element is found.
5444 *
5445 * Related: Array#assoc;
5446 * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
5447 */
5448
5449VALUE
5450rb_ary_rassoc(VALUE ary, VALUE value)
5451{
5452 long i;
5453 VALUE v;
5454
5455 for (i = 0; i < RARRAY_LEN(ary); ++i) {
5456 v = rb_check_array_type(RARRAY_AREF(ary, i));
5457 if (RB_TYPE_P(v, T_ARRAY) &&
5458 RARRAY_LEN(v) > 1 &&
5459 rb_equal(RARRAY_AREF(v, 1), value))
5460 return v;
5461 }
5462 return Qnil;
5463}
5464
5465static VALUE
5466recursive_equal(VALUE ary1, VALUE ary2, int recur)
5467{
5468 long i, len1;
5469 const VALUE *p1, *p2;
5470
5471 if (recur) return Qtrue; /* Subtle! */
5472
5473 /* rb_equal() can evacuate ptrs */
5474 p1 = RARRAY_CONST_PTR(ary1);
5475 p2 = RARRAY_CONST_PTR(ary2);
5476 len1 = RARRAY_LEN(ary1);
5477
5478 for (i = 0; i < len1; i++) {
5479 if (*p1 != *p2) {
5480 if (rb_equal(*p1, *p2)) {
5481 len1 = RARRAY_LEN(ary1);
5482 if (len1 != RARRAY_LEN(ary2))
5483 return Qfalse;
5484 if (len1 < i)
5485 return Qtrue;
5486 p1 = RARRAY_CONST_PTR(ary1) + i;
5487 p2 = RARRAY_CONST_PTR(ary2) + i;
5488 }
5489 else {
5490 return Qfalse;
5491 }
5492 }
5493 p1++;
5494 p2++;
5495 }
5496 return Qtrue;
5497}
5498
5499/*
5500 * call-seq:
5501 * self == other_array -> true or false
5502 *
5503 * Returns whether both:
5504 *
5505 * - +self+ and +other_array+ are the same size.
5506 * - Their corresponding elements are the same;
5507 * that is, for each index +i+ in <tt>(0...self.size)</tt>,
5508 * <tt>self[i] == other_array[i]</tt>.
5509 *
5510 * Examples:
5511 *
5512 * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
5513 * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
5514 * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
5515 * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
5516 *
5517 * This method is different from method Array#eql?,
5518 * which compares elements using <tt>Object#eql?</tt>.
5519 *
5520 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5521 */
5522
5523static VALUE
5524rb_ary_equal(VALUE ary1, VALUE ary2)
5525{
5526 if (ary1 == ary2) return Qtrue;
5527 if (!RB_TYPE_P(ary2, T_ARRAY)) {
5528 if (!rb_respond_to(ary2, idTo_ary)) {
5529 return Qfalse;
5530 }
5531 return rb_equal(ary2, ary1);
5532 }
5533 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5534 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5535 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
5536}
5537
5538static VALUE
5539recursive_eql(VALUE ary1, VALUE ary2, int recur)
5540{
5541 long i;
5542
5543 if (recur) return Qtrue; /* Subtle! */
5544 for (i=0; i<RARRAY_LEN(ary1); i++) {
5545 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
5546 return Qfalse;
5547 }
5548 return Qtrue;
5549}
5550
5551/*
5552 * call-seq:
5553 * eql?(other_array) -> true or false
5554 *
5555 * Returns +true+ if +self+ and +other_array+ are the same size,
5556 * and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
5557 *
5558 * a0 = [:foo, 'bar', 2]
5559 * a1 = [:foo, 'bar', 2]
5560 * a1.eql?(a0) # => true
5561 *
5562 * Otherwise, returns +false+.
5563 *
5564 * This method is different from method Array#==,
5565 * which compares using method <tt>Object#==</tt>.
5566 *
5567 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5568 */
5569
5570static VALUE
5571rb_ary_eql(VALUE ary1, VALUE ary2)
5572{
5573 if (ary1 == ary2) return Qtrue;
5574 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
5575 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
5576 if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
5577 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
5578}
5579
5580static VALUE
5581ary_hash_values(long len, const VALUE *elements, const VALUE ary)
5582{
5583 long i;
5584 st_index_t h;
5585 VALUE n;
5586
5587 h = rb_hash_start(len);
5588 h = rb_hash_uint(h, (st_index_t)rb_ary_hash_values);
5589 for (i=0; i<len; i++) {
5590 n = rb_hash(elements[i]);
5591 h = rb_hash_uint(h, NUM2LONG(n));
5592 if (ary) {
5593 len = RARRAY_LEN(ary);
5594 elements = RARRAY_CONST_PTR(ary);
5595 }
5596 }
5597 h = rb_hash_end(h);
5598 return ST2FIX(h);
5599}
5600
5601VALUE
5602rb_ary_hash_values(long len, const VALUE *elements)
5603{
5604 return ary_hash_values(len, elements, 0);
5605}
5606
5607/*
5608 * call-seq:
5609 * hash -> integer
5610 *
5611 * Returns the integer hash value for +self+.
5612 *
5613 * Two arrays with the same content will have the same hash value
5614 * (and will compare using eql?):
5615 *
5616 * ['a', 'b'].hash == ['a', 'b'].hash # => true
5617 * ['a', 'b'].hash == ['a', 'c'].hash # => false
5618 * ['a', 'b'].hash == ['a'].hash # => false
5619 *
5620 */
5621
5622static VALUE
5623rb_ary_hash(VALUE ary)
5624{
5626 return ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), ary);
5627}
5628
5629/*
5630 * call-seq:
5631 * include?(object) -> true or false
5632 *
5633 * Returns whether for some element +element+ in +self+,
5634 * <tt>object == element</tt>:
5635 *
5636 * [0, 1, 2].include?(2) # => true
5637 * [0, 1, 2].include?(2.0) # => true
5638 * [0, 1, 2].include?(2.1) # => false
5639 *
5640 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
5641 */
5642
5643VALUE
5644rb_ary_includes(VALUE ary, VALUE item)
5645{
5646 long i;
5647 VALUE e;
5648
5649 for (i=0; i<RARRAY_LEN(ary); i++) {
5650 e = RARRAY_AREF(ary, i);
5651 if (rb_equal(e, item)) {
5652 return Qtrue;
5653 }
5654 }
5655 return Qfalse;
5656}
5657
5658static VALUE
5659rb_ary_includes_by_eql(VALUE ary, VALUE item)
5660{
5661 long i;
5662 VALUE e;
5663
5664 for (i=0; i<RARRAY_LEN(ary); i++) {
5665 e = RARRAY_AREF(ary, i);
5666 if (rb_eql(item, e)) {
5667 return Qtrue;
5668 }
5669 }
5670 return Qfalse;
5671}
5672
5673static VALUE
5674recursive_cmp(VALUE ary1, VALUE ary2, int recur)
5675{
5676 long i, len;
5677
5678 if (recur) return Qundef; /* Subtle! */
5679 len = RARRAY_LEN(ary1);
5680 if (len > RARRAY_LEN(ary2)) {
5681 len = RARRAY_LEN(ary2);
5682 }
5683 for (i=0; i<len; i++) {
5684 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
5685 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
5686 if (v != INT2FIX(0)) {
5687 return v;
5688 }
5689 }
5690 return Qundef;
5691}
5692
5693/*
5694 * call-seq:
5695 * self <=> other_array -> -1, 0, or 1
5696 *
5697 * Returns -1, 0, or 1 as +self+ is determined
5698 * to be less than, equal to, or greater than +other_array+.
5699 *
5700 * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
5701 *
5702 * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
5703 * - Immediately returns 1 if <tt>result[i]</tt> is 1:
5704 *
5705 * [0, 1, 2] <=> [0, 0, 2] # => 1
5706 *
5707 * - Immediately returns -1 if <tt>result[i]</tt> is -1:
5708 *
5709 * [0, 1, 2] <=> [0, 2, 2] # => -1
5710 *
5711 * - Continues if <tt>result[i]</tt> is 0.
5712 *
5713 * When every +result+ is 0,
5714 * returns <tt>self.size <=> other_array.size</tt>
5715 * (see Integer#<=>):
5716 *
5717 * [0, 1, 2] <=> [0, 1] # => 1
5718 * [0, 1, 2] <=> [0, 1, 2] # => 0
5719 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5720 *
5721 * Note that when +other_array+ is larger than +self+,
5722 * its trailing elements do not affect the result:
5723 *
5724 * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
5725 * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
5726 * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
5727 *
5728 * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
5729 */
5730
5731VALUE
5732rb_ary_cmp(VALUE ary1, VALUE ary2)
5733{
5734 long len;
5735 VALUE v;
5736
5737 ary2 = rb_check_array_type(ary2);
5738 if (NIL_P(ary2)) return Qnil;
5739 if (ary1 == ary2) return INT2FIX(0);
5740 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
5741 if (!UNDEF_P(v)) return v;
5742 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
5743 if (len == 0) return INT2FIX(0);
5744 if (len > 0) return INT2FIX(1);
5745 return INT2FIX(-1);
5746}
5747
5748static void
5749rb_ary_union_set(VALUE set, VALUE ary)
5750{
5751 for (long i = 0; i < RARRAY_LEN(ary); i++) {
5752 rb_set_add_no_check(set, RARRAY_AREF(ary, i));
5753 }
5754}
5755
5756static VALUE
5757ary_to_set(VALUE ary)
5758{
5760 rb_ary_union_set(set, ary);
5761 return set;
5762}
5763
5764/*
5765 * call-seq:
5766 * self - other_array -> new_array
5767 *
5768 * Returns a new array containing only those elements of +self+
5769 * that are not found in +other_array+;
5770 * the order from +self+ is preserved:
5771 *
5772 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
5773 * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
5774 * [0, 1, 2] - [:foo] # => [0, 1, 2]
5775 *
5776 * Element are compared using method <tt>#eql?</tt>
5777 * (as defined in each element of +self+).
5778 *
5779 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5780 */
5781
5782VALUE
5783rb_ary_diff(VALUE ary1, VALUE ary2)
5784{
5785 ary2 = to_ary(ary2);
5786 if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
5787 VALUE ary3 = rb_ary_new();
5788
5789 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5790 for (long i = 0; i < RARRAY_LEN(ary1); i++) {
5791 VALUE elt = rb_ary_elt(ary1, i);
5792 if (rb_ary_includes_by_eql(ary2, elt)) continue;
5793 rb_ary_push(ary3, elt);
5794 }
5795 return ary3;
5796 }
5797
5798 VALUE set = ary_to_set(ary2);
5799 for (long i = 0; i < RARRAY_LEN(ary1); i++) {
5800 if (rb_set_lookup(set, RARRAY_AREF(ary1, i))) continue;
5801 rb_ary_push(ary3, rb_ary_elt(ary1, i));
5802 }
5803
5804 return ary3;
5805}
5806
5807/*
5808 * call-seq:
5809 * difference(*other_arrays = []) -> new_array
5810 *
5811 * Returns a new array containing only those elements from +self+
5812 * that are not found in any of the given +other_arrays+;
5813 * items are compared using <tt>eql?</tt>; order from +self+ is preserved:
5814 *
5815 * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
5816 * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
5817 * [0, 1, 2].difference([4]) # => [0, 1, 2]
5818 * [0, 1, 2].difference # => [0, 1, 2]
5819 *
5820 * Returns a copy of +self+ if no arguments are given.
5821 *
5822 * Related: Array#-;
5823 * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5824 */
5825
5826static VALUE
5827rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
5828{
5829 volatile VALUE t0;
5830 bool *is_set = ALLOCV_N(bool, t0, argc);
5831 VALUE ary_diff = rb_ary_new();
5832 long length = RARRAY_LEN(ary);
5833
5834 for (long i = 0; i < argc; i++) {
5835 argv[i] = to_ary(argv[i]);
5836 is_set[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
5837 if (is_set[i]) {
5838 argv[i] = ary_to_set(argv[i]);
5839 }
5840 }
5841
5842 for (long i = 0; i < RARRAY_LEN(ary); i++) {
5843 int j;
5844 VALUE elt = rb_ary_elt(ary, i);
5845 for (j = 0; j < argc; j++) {
5846 if (is_set[j]) {
5847 if (rb_set_lookup(argv[j], elt))
5848 break;
5849 }
5850 else {
5851 if (rb_ary_includes_by_eql(argv[j], elt)) break;
5852 }
5853 }
5854 if (j == argc) rb_ary_push(ary_diff, elt);
5855 }
5856
5857 ALLOCV_END(t0);
5858
5859 return ary_diff;
5860}
5861
5862
5863/*
5864 * call-seq:
5865 * self & other_array -> new_array
5866 *
5867 * Returns a new array containing the _intersection_ of +self+ and +other_array+;
5868 * that is, containing those elements found in both +self+ and +other_array+:
5869 *
5870 * [0, 1, 2, 3] & [1, 2] # => [1, 2]
5871 *
5872 * Omits duplicates:
5873 *
5874 * [0, 1, 1, 0] & [0, 1] # => [0, 1]
5875 *
5876 * Preserves order from +self+:
5877 *
5878 * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
5879 *
5880 * Identifies common elements using method <tt>#eql?</tt>
5881 * (as defined in each element of +self+).
5882 *
5883 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5884 */
5885
5886
5887static VALUE
5888rb_ary_and(VALUE ary1, VALUE ary2)
5889{
5890 ary2 = to_ary(ary2);
5891 VALUE ary3 = rb_ary_new();
5892 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
5893
5894 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5895 for (long i = 0; i < RARRAY_LEN(ary1); i++) {
5896 VALUE v = RARRAY_AREF(ary1, i);
5897 if (!rb_ary_includes_by_eql(ary2, v)) continue;
5898 if (rb_ary_includes_by_eql(ary3, v)) continue;
5899 rb_ary_push(ary3, v);
5900 }
5901 return ary3;
5902 }
5903
5904 VALUE set = ary_to_set(ary2);
5905
5906 for (long i = 0; i < RARRAY_LEN(ary1); i++) {
5907 VALUE v = RARRAY_AREF(ary1, i);
5908 if (rb_set_delete_no_check(set, v)) {
5909 rb_ary_push(ary3, v);
5910 }
5911 }
5912
5913 return ary3;
5914}
5915
5916/*
5917 * call-seq:
5918 * intersection(*other_arrays) -> new_array
5919 *
5920 * Returns a new array containing each element in +self+ that is +#eql?+
5921 * to at least one element in each of the given +other_arrays+;
5922 * duplicates are omitted:
5923 *
5924 * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
5925 *
5926 * Each element must correctly implement method <tt>#hash</tt>.
5927 *
5928 * Order from +self+ is preserved:
5929 *
5930 * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
5931 *
5932 * Returns a copy of +self+ if no arguments are given.
5933 *
5934 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5935 */
5936
5937static VALUE
5938rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
5939{
5940 VALUE result = rb_ary_dup(ary);
5941 int i;
5942
5943 for (i = 0; i < argc; i++) {
5944 result = rb_ary_and(result, argv[i]);
5945 }
5946
5947 return result;
5948}
5949
5950static void
5951rb_ary_union(VALUE ary_union, VALUE ary)
5952{
5953 long i;
5954 for (i = 0; i < RARRAY_LEN(ary); i++) {
5955 VALUE elt = rb_ary_elt(ary, i);
5956 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
5957 rb_ary_push(ary_union, elt);
5958 }
5959}
5960
5961/*
5962 * call-seq:
5963 * self | other_array -> new_array
5964 *
5965 * Returns the union of +self+ and +other_array+;
5966 * duplicates are removed; order is preserved;
5967 * items are compared using <tt>eql?</tt> and <tt>hash</tt>:
5968 *
5969 * [0, 1] | [2, 3] # => [0, 1, 2, 3]
5970 * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
5971 * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
5972 *
5973 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
5974 */
5975
5976static VALUE
5977rb_ary_or(VALUE ary1, VALUE ary2)
5978{
5979 ary2 = to_ary(ary2);
5980 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
5981 VALUE ary3 = rb_ary_new();
5982 rb_ary_union(ary3, ary1);
5983 rb_ary_union(ary3, ary2);
5984 return ary3;
5985 }
5986
5988 rb_ary_union_set(set, ary1);
5989 rb_ary_union_set(set, ary2);
5990
5991 return rb_set_to_a(set);
5992}
5993
5994/*
5995 * call-seq:
5996 * union(*other_arrays) -> new_array
5997 *
5998 * Returns a new array that is the union of the elements of +self+
5999 * and all given arrays +other_arrays+;
6000 * items are compared using <tt>eql?</tt> and <tt>hash</tt>:
6001 *
6002 * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
6003 *
6004 * Removes duplicates (preserving the first found):
6005 *
6006 * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
6007 *
6008 * Preserves order (preserving the position of the first found):
6009 *
6010 * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
6011 *
6012 * With no arguments given, returns a copy of +self+.
6013 *
6014 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
6015 */
6016
6017static VALUE
6018rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
6019{
6020 long sum = RARRAY_LEN(ary);
6021 for (int i = 0; i < argc; i++) {
6022 argv[i] = to_ary(argv[i]);
6023 sum += RARRAY_LEN(argv[i]);
6024 }
6025
6026 if (sum <= SMALL_ARRAY_LEN) {
6027 VALUE ary_union = rb_ary_new();
6028
6029 rb_ary_union(ary_union, ary);
6030 for (int i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
6031
6032 return ary_union;
6033 }
6034
6035 VALUE set = rb_obj_hide(rb_set_new_capa(sum));
6036 rb_ary_union_set(set, ary);
6037 for (int i = 0; i < argc; i++) rb_ary_union_set(set, argv[i]);
6038
6039 return rb_set_to_a(set);
6040}
6041
6042/*
6043 * call-seq:
6044 * intersect?(other_array) -> true or false
6045 *
6046 * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
6047 *
6048 * [1, 2, 3].intersect?([3, 4, 5]) # => true
6049 * [1, 2, 3].intersect?([4, 5, 6]) # => false
6050 *
6051 * Each element must correctly implement method <tt>#hash</tt>.
6052 *
6053 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6054 */
6055
6056static VALUE
6057rb_ary_intersect_p(VALUE ary1, VALUE ary2)
6058{
6059 ary2 = to_ary(ary2);
6060 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;
6061
6062 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
6063 for (long i = 0; i < RARRAY_LEN(ary1); i++) {
6064 VALUE v = RARRAY_AREF(ary1, i);
6065 if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
6066 }
6067 return Qfalse;
6068 }
6069
6070 VALUE shorter = ary1;
6071 VALUE longer = ary2;
6072 if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
6073 longer = ary1;
6074 shorter = ary2;
6075 }
6076
6077 VALUE set = ary_to_set(shorter);
6078 VALUE result = Qfalse;
6079
6080 for (long i = 0; i < RARRAY_LEN(longer); i++) {
6081 VALUE v = RARRAY_AREF(longer, i);
6082 if (rb_set_lookup(set, v)) {
6083 result = Qtrue;
6084 break;
6085 }
6086 }
6087
6088 return result;
6089}
6090
6091static VALUE
6092ary_max_generic(VALUE ary, long i, VALUE vmax)
6093{
6094 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6095
6096 VALUE v;
6097 for (; i < RARRAY_LEN(ary); ++i) {
6098 v = RARRAY_AREF(ary, i);
6099
6100 if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
6101 vmax = v;
6102 }
6103 }
6104
6105 return vmax;
6106}
6107
6108static VALUE
6109ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
6110{
6111 const long n = RARRAY_LEN(ary);
6112 RUBY_ASSERT(i > 0 && i < n);
6113 RUBY_ASSERT(FIXNUM_P(vmax));
6114
6115 VALUE v;
6116 for (; i < n; ++i) {
6117 v = RARRAY_AREF(ary, i);
6118
6119 if (FIXNUM_P(v)) {
6120 if ((long)vmax < (long)v) {
6121 vmax = v;
6122 }
6123 }
6124 else {
6125 return ary_max_generic(ary, i, vmax);
6126 }
6127 }
6128
6129 return vmax;
6130}
6131
6132static VALUE
6133ary_max_opt_float(VALUE ary, long i, VALUE vmax)
6134{
6135 const long n = RARRAY_LEN(ary);
6136 RUBY_ASSERT(i > 0 && i < n);
6138
6139 VALUE v;
6140 for (; i < n; ++i) {
6141 v = RARRAY_AREF(ary, i);
6142
6143 if (RB_FLOAT_TYPE_P(v)) {
6144 if (rb_float_cmp(vmax, v) < 0) {
6145 vmax = v;
6146 }
6147 }
6148 else {
6149 return ary_max_generic(ary, i, vmax);
6150 }
6151 }
6152
6153 return vmax;
6154}
6155
6156static VALUE
6157ary_max_opt_string(VALUE ary, long i, VALUE vmax)
6158{
6159 const long n = RARRAY_LEN(ary);
6160 RUBY_ASSERT(i > 0 && i < n);
6161 RUBY_ASSERT(STRING_P(vmax));
6162
6163 VALUE v;
6164 for (; i < n; ++i) {
6165 v = RARRAY_AREF(ary, i);
6166
6167 if (STRING_P(v)) {
6168 if (rb_str_cmp(vmax, v) < 0) {
6169 vmax = v;
6170 }
6171 }
6172 else {
6173 return ary_max_generic(ary, i, vmax);
6174 }
6175 }
6176
6177 return vmax;
6178}
6179
6180/*
6181 * call-seq:
6182 * max -> element
6183 * max(count) -> new_array
6184 * max {|a, b| ... } -> element
6185 * max(count) {|a, b| ... } -> new_array
6186 *
6187 * Returns one of the following:
6188 *
6189 * - The maximum-valued element from +self+.
6190 * - A new array of maximum-valued elements from +self+.
6191 *
6192 * Does not modify +self+.
6193 *
6194 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6195 * with a numeric.
6196 *
6197 * With no argument and no block, returns the element in +self+
6198 * having the maximum value per method <tt>#<=></tt>:
6199 *
6200 * [1, 0, 3, 2].max # => 3
6201 *
6202 * With non-negative numeric argument +count+ and no block,
6203 * returns a new array with at most +count+ elements,
6204 * in descending order, per method <tt>#<=></tt>:
6205 *
6206 * [1, 0, 3, 2].max(3) # => [3, 2, 1]
6207 * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
6208 * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
6209 * [1, 0, 3, 2].max(0) # => []
6210 *
6211 * With a block given, the block must return a numeric.
6212 *
6213 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6214 * returns the element having the maximum value per the block:
6215 *
6216 * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
6217 * # => "000"
6218 *
6219 * With non-negative numeric argument +count+ and a block,
6220 * returns a new array with at most +count+ elements,
6221 * in descending order, per the block:
6222 *
6223 * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
6224 * # => ["000", "00"]
6225 *
6226 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6227 */
6228static VALUE
6229rb_ary_max(int argc, VALUE *argv, VALUE ary)
6230{
6231 VALUE result = Qundef, v;
6232 VALUE num;
6233 long i;
6234
6235 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6236 return rb_nmin_run(ary, num, 0, 1, 1);
6237
6238 const long n = RARRAY_LEN(ary);
6239 if (rb_block_given_p()) {
6240 for (i = 0; i < RARRAY_LEN(ary); i++) {
6241 v = RARRAY_AREF(ary, i);
6242 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
6243 result = v;
6244 }
6245 }
6246 }
6247 else if (n > 0) {
6248 result = RARRAY_AREF(ary, 0);
6249 if (n > 1) {
6250 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6251 return ary_max_opt_fixnum(ary, 1, result);
6252 }
6253 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6254 return ary_max_opt_string(ary, 1, result);
6255 }
6256 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6257 return ary_max_opt_float(ary, 1, result);
6258 }
6259 else {
6260 return ary_max_generic(ary, 1, result);
6261 }
6262 }
6263 }
6264 if (UNDEF_P(result)) return Qnil;
6265 return result;
6266}
6267
6268static VALUE
6269ary_min_generic(VALUE ary, long i, VALUE vmin)
6270{
6271 RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
6272
6273 VALUE v;
6274 for (; i < RARRAY_LEN(ary); ++i) {
6275 v = RARRAY_AREF(ary, i);
6276
6277 if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
6278 vmin = v;
6279 }
6280 }
6281
6282 return vmin;
6283}
6284
6285static VALUE
6286ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
6287{
6288 const long n = RARRAY_LEN(ary);
6289 RUBY_ASSERT(i > 0 && i < n);
6290 RUBY_ASSERT(FIXNUM_P(vmin));
6291
6292 VALUE a;
6293 for (; i < n; ++i) {
6294 a = RARRAY_AREF(ary, i);
6295
6296 if (FIXNUM_P(a)) {
6297 if ((long)vmin > (long)a) {
6298 vmin = a;
6299 }
6300 }
6301 else {
6302 return ary_min_generic(ary, i, vmin);
6303 }
6304 }
6305
6306 return vmin;
6307}
6308
6309static VALUE
6310ary_min_opt_float(VALUE ary, long i, VALUE vmin)
6311{
6312 const long n = RARRAY_LEN(ary);
6313 RUBY_ASSERT(i > 0 && i < n);
6315
6316 VALUE a;
6317 for (; i < n; ++i) {
6318 a = RARRAY_AREF(ary, i);
6319
6320 if (RB_FLOAT_TYPE_P(a)) {
6321 if (rb_float_cmp(vmin, a) > 0) {
6322 vmin = a;
6323 }
6324 }
6325 else {
6326 return ary_min_generic(ary, i, vmin);
6327 }
6328 }
6329
6330 return vmin;
6331}
6332
6333static VALUE
6334ary_min_opt_string(VALUE ary, long i, VALUE vmin)
6335{
6336 const long n = RARRAY_LEN(ary);
6337 RUBY_ASSERT(i > 0 && i < n);
6338 RUBY_ASSERT(STRING_P(vmin));
6339
6340 VALUE a;
6341 for (; i < n; ++i) {
6342 a = RARRAY_AREF(ary, i);
6343
6344 if (STRING_P(a)) {
6345 if (rb_str_cmp(vmin, a) > 0) {
6346 vmin = a;
6347 }
6348 }
6349 else {
6350 return ary_min_generic(ary, i, vmin);
6351 }
6352 }
6353
6354 return vmin;
6355}
6356
6357/*
6358 * call-seq:
6359 * min -> element
6360 * min(count) -> new_array
6361 * min {|a, b| ... } -> element
6362 * min(count) {|a, b| ... } -> new_array
6363 *
6364 * Returns one of the following:
6365 *
6366 * - The minimum-valued element from +self+.
6367 * - A new array of minimum-valued elements from +self+.
6368 *
6369 * Does not modify +self+.
6370 *
6371 * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
6372 * with a numeric.
6373 *
6374 * With no argument and no block, returns the element in +self+
6375 * having the minimum value per method <tt>#<=></tt>:
6376 *
6377 * [1, 0, 3, 2].min # => 0
6378 *
6379 * With non-negative numeric argument +count+ and no block,
6380 * returns a new array with at most +count+ elements,
6381 * in ascending order, per method <tt>#<=></tt>:
6382 *
6383 * [1, 0, 3, 2].min(3) # => [0, 1, 2]
6384 * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
6385 * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
6386 * [1, 0, 3, 2].min(0) # => []
6387 *
6388 * With a block given, the block must return a numeric.
6389 *
6390 * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
6391 * returns the element having the minimum value per the block:
6392 *
6393 * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
6394 * # => ""
6395 *
6396 * With non-negative numeric argument +count+ and a block,
6397 * returns a new array with at most +count+ elements,
6398 * in ascending order, per the block:
6399 *
6400 * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
6401 * # => ["", "0"]
6402 *
6403 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6404 */
6405static VALUE
6406rb_ary_min(int argc, VALUE *argv, VALUE ary)
6407{
6408 VALUE result = Qundef, v;
6409 VALUE num;
6410 long i;
6411
6412 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
6413 return rb_nmin_run(ary, num, 0, 0, 1);
6414
6415 const long n = RARRAY_LEN(ary);
6416 if (rb_block_given_p()) {
6417 for (i = 0; i < RARRAY_LEN(ary); i++) {
6418 v = RARRAY_AREF(ary, i);
6419 if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
6420 result = v;
6421 }
6422 }
6423 }
6424 else if (n > 0) {
6425 result = RARRAY_AREF(ary, 0);
6426 if (n > 1) {
6427 if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
6428 return ary_min_opt_fixnum(ary, 1, result);
6429 }
6430 else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
6431 return ary_min_opt_string(ary, 1, result);
6432 }
6433 else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
6434 return ary_min_opt_float(ary, 1, result);
6435 }
6436 else {
6437 return ary_min_generic(ary, 1, result);
6438 }
6439 }
6440 }
6441 if (UNDEF_P(result)) return Qnil;
6442 return result;
6443}
6444
6445/*
6446 * call-seq:
6447 * minmax -> array
6448 * minmax {|a, b| ... } -> array
6449 *
6450 * Returns a 2-element array containing the minimum-valued and maximum-valued
6451 * elements from +self+;
6452 * does not modify +self+.
6453 *
6454 * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
6455 *
6456 * [1, 0, 3, 2].minmax # => [0, 3]
6457 *
6458 * With a block given, the block must return a numeric;
6459 * the block is called <tt>self.size - 1</tt> times to compare elements;
6460 * returns the elements having the minimum and maximum values per the block:
6461 *
6462 * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
6463 * # => ["", "000"]
6464 *
6465 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6466 */
6467static VALUE
6468rb_ary_minmax(VALUE ary)
6469{
6470 if (rb_block_given_p()) {
6471 return rb_call_super(0, NULL);
6472 }
6473 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
6474}
6475
6476static int
6477push_value_i(VALUE elt, VALUE ary)
6478{
6479 rb_ary_push(ary, elt);
6480 return ST_CONTINUE;
6481}
6482
6483/*
6484 * call-seq:
6485 * uniq! -> self or nil
6486 * uniq! {|element| ... } -> self or nil
6487 *
6488 * Removes duplicate elements from +self+, the first occurrence always being retained;
6489 * returns +self+ if any elements removed, +nil+ otherwise.
6490 *
6491 * With no block given, identifies and removes elements using method <tt>eql?</tt>
6492 * and <tt>hash</tt> to compare elements:
6493 *
6494 * a = [0, 0, 1, 1, 2, 2]
6495 * a.uniq! # => [0, 1, 2]
6496 * a.uniq! # => nil
6497 *
6498 * With a block given, calls the block for each element;
6499 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6500 * and <tt>hash</tt> to compare <i>block return values</i>;
6501 * that is, an element is a duplicate if its block return value
6502 * is the same as that of a previous element:
6503 *
6504 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6505 * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
6506 * a.uniq! {|element| element.size } # => nil
6507 *
6508 * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6509 */
6510static VALUE
6511rb_ary_uniq_bang(VALUE ary)
6512{
6513 rb_ary_modify_check(ary);
6514 if (RARRAY_LEN(ary) <= 1)
6515 return Qnil;
6516
6517 if (rb_block_given_p()) {
6519 VALUE uniq = rb_ary_new_capa(RARRAY_LEN(ary));
6520 for (long i = 0; i < RARRAY_LEN(ary); i++) {
6521 VALUE elt = rb_ary_elt(ary, i);
6522 if (rb_set_add_no_check(set, rb_yield(elt)))
6523 rb_ary_push(uniq, elt);
6524 }
6525 if (RARRAY_LEN(ary) == RARRAY_LEN(uniq))
6526 return Qnil;
6527 rb_ary_replace(ary, uniq);
6528 return ary;
6529 }
6530
6531 VALUE set = ary_to_set(ary);
6532 long size = (long)rb_set_size(set);
6533 if (RARRAY_LEN(ary) == size) {
6534 return Qnil;
6535 }
6536 rb_ary_modify_check(ary);
6537 ARY_SET_LEN(ary, 0);
6538 if (ARY_SHARED_P(ary)) {
6539 rb_ary_unshare(ary);
6540 FL_SET_EMBED(ary);
6541 }
6542 ary_resize_capa(ary, size);
6543 rb_set_foreach(set, push_value_i, ary);
6544
6545 return ary;
6546}
6547
6548/*
6549 * call-seq:
6550 * uniq -> new_array
6551 * uniq {|element| ... } -> new_array
6552 *
6553 * Returns a new array containing those elements from +self+ that are not duplicates,
6554 * the first occurrence always being retained.
6555 *
6556 * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
6557 * and <tt>hash</tt> to compare elements:
6558 *
6559 * a = [0, 0, 1, 1, 2, 2]
6560 * a.uniq # => [0, 1, 2]
6561 *
6562 * With a block given, calls the block for each element;
6563 * identifies and omits "duplicate" elements using method <tt>eql?</tt>
6564 * and <tt>hash</tt> to compare <i>block return values</i>;
6565 * that is, an element is a duplicate if its block return value
6566 * is the same as that of a previous element:
6567 *
6568 * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
6569 * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
6570 *
6571 * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
6572 */
6573
6574static VALUE
6575rb_ary_uniq(VALUE ary)
6576{
6577 if (RARRAY_LEN(ary) <= 1) {
6578 return rb_ary_dup(ary);
6579 }
6580
6582
6583 if (rb_block_given_p()) {
6584 VALUE uniq = rb_ary_new_capa(RARRAY_LEN(ary));
6585 for (long i = 0; i < RARRAY_LEN(ary); i++) {
6586 VALUE elt = rb_ary_elt(ary, i);
6587 if (rb_set_add_no_check(set, rb_yield(elt)))
6588 rb_ary_push(uniq, elt);
6589 }
6590 return uniq;
6591 }
6592 else {
6593 rb_ary_union_set(set, ary);
6594 return rb_set_to_a(set);
6595 }
6596}
6597
6598/*
6599 * call-seq:
6600 * compact! -> self or nil
6601 *
6602 * Removes all +nil+ elements from +self+;
6603 * Returns +self+ if any elements are removed, +nil+ otherwise:
6604 *
6605 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6606 * a.compact! # => [0, false, "", [], {}]
6607 * a # => [0, false, "", [], {}]
6608 * a.compact! # => nil
6609 *
6610 * Related: Array#compact;
6611 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6612 */
6613
6614VALUE
6615rb_ary_compact_bang(VALUE ary)
6616{
6617 VALUE *p, *t, *end;
6618 long n;
6619
6620 rb_ary_modify(ary);
6621 p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
6622 end = p + RARRAY_LEN(ary);
6623
6624 while (t < end) {
6625 if (NIL_P(*t)) t++;
6626 else *p++ = *t++;
6627 }
6628 n = p - RARRAY_CONST_PTR(ary);
6629 if (RARRAY_LEN(ary) == n) {
6630 return Qnil;
6631 }
6632 ary_resize_smaller(ary, n);
6633
6634 return ary;
6635}
6636
6637/*
6638 * call-seq:
6639 * compact -> new_array
6640 *
6641 * Returns a new array containing only the non-+nil+ elements from +self+;
6642 * element order is preserved:
6643 *
6644 * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
6645 * a.compact # => [0, false, "", [], {}]
6646 *
6647 * Related: Array#compact!;
6648 * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
6649 */
6650
6651static VALUE
6652rb_ary_compact(VALUE ary)
6653{
6654 ary = rb_ary_dup(ary);
6655 rb_ary_compact_bang(ary);
6656 return ary;
6657}
6658
6659/*
6660 * call-seq:
6661 * count -> integer
6662 * count(object) -> integer
6663 * count {|element| ... } -> integer
6664 *
6665 * Returns a count of specified elements.
6666 *
6667 * With no argument and no block, returns the count of all elements:
6668 *
6669 * [0, :one, 'two', 3, 3.0].count # => 5
6670 *
6671 * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
6672 *
6673 * [0, :one, 'two', 3, 3.0].count(3) # => 2
6674 *
6675 * With no argument and a block given, calls the block with each element;
6676 * returns the count of elements for which the block returns a truthy value:
6677 *
6678 * [0, 1, 2, 3].count {|element| element > 1 } # => 2
6679 *
6680 * With argument +object+ and a block given, issues a warning, ignores the block,
6681 * and returns the count of elements <tt>==</tt> to +object+.
6682 *
6683 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
6684 */
6685
6686static VALUE
6687rb_ary_count(int argc, VALUE *argv, VALUE ary)
6688{
6689 long i, n = 0;
6690
6691 if (rb_check_arity(argc, 0, 1) == 0) {
6692 VALUE v;
6693
6694 if (!rb_block_given_p())
6695 return LONG2NUM(RARRAY_LEN(ary));
6696
6697 for (i = 0; i < RARRAY_LEN(ary); i++) {
6698 v = RARRAY_AREF(ary, i);
6699 if (RTEST(rb_yield(v))) n++;
6700 }
6701 }
6702 else {
6703 VALUE obj = argv[0];
6704
6705 if (rb_block_given_p()) {
6706 rb_warn("given block not used");
6707 }
6708 for (i = 0; i < RARRAY_LEN(ary); i++) {
6709 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
6710 }
6711 }
6712
6713 return LONG2NUM(n);
6714}
6715
6716static VALUE
6717flatten(VALUE ary, int level)
6718{
6719 long i;
6720 VALUE stack, result, tmp = Qnil, elt;
6721 VALUE memo = Qfalse;
6722
6723 for (i = 0; i < RARRAY_LEN(ary); i++) {
6724 elt = RARRAY_AREF(ary, i);
6725 tmp = rb_check_array_type(elt);
6726 if (!NIL_P(tmp)) {
6727 break;
6728 }
6729 }
6730 if (NIL_P(tmp)) {
6731 return ary;
6732 }
6733 if (i > RARRAY_LEN(ary)) {
6734 /* ary was shrunk while converting an element with #to_ary, so
6735 the scanned elements may no longer exist in ary */
6736 i = RARRAY_LEN(ary);
6737 }
6738
6739 result = ary_new(0, RARRAY_LEN(ary));
6740 ary_memcpy(result, 0, i, RARRAY_CONST_PTR(ary));
6741 ARY_SET_LEN(result, i);
6742
6743 stack = ary_new(0, ARY_DEFAULT_SIZE);
6744 rb_ary_push(stack, ary);
6745 rb_ary_push(stack, LONG2NUM(i + 1));
6746
6747 if (level < 0) {
6748 memo = rb_obj_hide(rb_ident_set_new());
6749 rb_set_add(memo, ary);
6750 rb_set_add(memo, tmp);
6751 }
6752
6753 ary = tmp;
6754 i = 0;
6755
6756 while (1) {
6757 while (i < RARRAY_LEN(ary)) {
6758 elt = RARRAY_AREF(ary, i++);
6759 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
6760 rb_ary_push(result, elt);
6761 continue;
6762 }
6763 tmp = rb_check_array_type(elt);
6764 if (RBASIC(result)->klass) {
6765 if (RTEST(memo)) {
6766 rb_set_clear(memo);
6767 }
6768 rb_raise(rb_eRuntimeError, "flatten reentered");
6769 }
6770 if (NIL_P(tmp)) {
6771 rb_ary_push(result, elt);
6772 }
6773 else {
6774 if (memo) {
6775 if (rb_set_lookup(memo, tmp)) {
6776 rb_set_clear(memo);
6777 rb_raise(rb_eArgError, "tried to flatten recursive array");
6778 }
6779 rb_set_add(memo, tmp);
6780 }
6781 rb_ary_push(stack, ary);
6782 rb_ary_push(stack, LONG2NUM(i));
6783 ary = tmp;
6784 i = 0;
6785 }
6786 }
6787 if (RARRAY_LEN(stack) == 0) {
6788 break;
6789 }
6790 if (memo) {
6791 rb_set_delete(memo, ary);
6792 }
6793 tmp = rb_ary_pop(stack);
6794 i = NUM2LONG(tmp);
6795 ary = rb_ary_pop(stack);
6796 }
6797
6798 if (memo) {
6799 rb_set_clear(memo);
6800 }
6801
6802 RBASIC_SET_CLASS(result, rb_cArray);
6803 return result;
6804}
6805
6806static inline VALUE
6807single_nested_array(VALUE ary)
6808{
6809 // Fast path for the common variadic argument pattern:
6810 // def foo(*args)
6811 // args.flatten!
6812 // ...
6813 if (RARRAY_LEN(ary) == 1) {
6814 VALUE first = RARRAY_AREF(ary, 0);
6815 if (RB_TYPE_P(first, T_ARRAY) && CLASS_OF(first) == rb_cArray) {
6816 return first;
6817 }
6818 }
6819 return 0;
6820}
6821
6822/*
6823 * call-seq:
6824 * flatten!(depth = nil) -> self or nil
6825 *
6826 * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
6827 * +depth+ must be an
6828 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
6829 * or +nil+.
6830 * At each level of recursion:
6831 *
6832 * - Each element that is an array is "flattened"
6833 * (that is, replaced by its individual array elements).
6834 * - Each element that is not an array is unchanged
6835 * (even if the element is an object that has instance method +flatten+).
6836 *
6837 * Returns +nil+ if no elements were flattened.
6838 *
6839 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6840 *
6841 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6842 * a # => [0, [1, [2, 3], 4], 5, {foo: 0}, #<Set: {6, 7}>]
6843 * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {foo: 0}, #<Set: {6, 7}>]
6844 * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {foo: 0}, #<Set: {6, 7}>]
6845 * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6846 * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6847 *
6848 * With +nil+ or negative argument +depth+, flattens all levels:
6849 *
6850 * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6851 * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6852 *
6853 * Related: Array#flatten;
6854 * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
6855 */
6856
6857static VALUE
6858rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
6859{
6860 int mod = 0, level = -1;
6861 VALUE result, lv;
6862
6863 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
6864 rb_ary_modify_check(ary);
6865 if (!NIL_P(lv)) level = NUM2INT(lv);
6866 if (level == 0) return Qnil;
6867
6868 VALUE child = single_nested_array(ary);
6869 if (child) {
6870 if (level == 1) {
6871 result = child;
6872 }
6873 else {
6874 if (level > 1) level--;
6875 result = flatten(child, level);
6876 }
6877 }
6878 else {
6879 result = flatten(ary, level);
6880 if (result == ary) {
6881 return Qnil;
6882 }
6883 }
6884
6885 if (result != child && !(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
6886 rb_ary_replace(ary, result);
6887 if (mod) ARY_SET_EMBED_LEN(result, 0);
6888
6889 return ary;
6890}
6891
6892/*
6893 * call-seq:
6894 * flatten(depth = nil) -> new_array
6895 *
6896 * Returns a new array that is a recursive flattening of +self+
6897 * to +depth+ levels of recursion;
6898 * +depth+ must be an
6899 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
6900 * or +nil+.
6901 * At each level of recursion:
6902 *
6903 * - Each element that is an array is "flattened"
6904 * (that is, replaced by its individual array elements).
6905 * - Each element that is not an array is unchanged
6906 * (even if the element is an object that has instance method +flatten+).
6907 *
6908 * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
6909 *
6910 * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
6911 * a # => [0, [1, [2, 3], 4], 5, {foo: 0}, #<Set: {6, 7}>]
6912 * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {foo: 0}, #<Set: {6, 7}>]
6913 * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {foo: 0}, #<Set: {6, 7}>]
6914 * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {foo: 0}, #<Set: {6, 7}>]
6915 * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6916 * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6917 *
6918 * With +nil+ or negative +depth+, flattens all levels.
6919 *
6920 * a.flatten # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6921 * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {foo: 0}, #<Set: {6, 7}>]
6922 *
6923 * Related: Array#flatten!;
6924 * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
6925 */
6926
6927static VALUE
6928rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
6929{
6930 int level = -1;
6931 VALUE result;
6932
6933 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
6934 level = NUM2INT(argv[0]);
6935 if (level == 0) return ary_make_shared_copy(ary);
6936 }
6937
6938 VALUE child = single_nested_array(ary);
6939 if (child) {
6940 if (level == 1) {
6941 result = child;
6942 }
6943 else {
6944 level--;
6945 result = flatten(child, level);
6946 }
6947 }
6948 else {
6949 result = flatten(ary, level);
6950 }
6951
6952 if (result == ary || result == child) {
6953 return ary_make_shared_copy(result);
6954 }
6955
6956 return result;
6957}
6958
6959#define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
6960
6961static VALUE
6962rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6963{
6964 long i, len;
6965
6966 rb_ary_modify(ary);
6967 i = len = RARRAY_LEN(ary);
6968 RARRAY_PTR_USE(ary, ptr, {
6969 while (i > 1) {
6970 long j = RAND_UPTO(i);
6971 VALUE tmp;
6972 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
6973 rb_raise(rb_eRuntimeError, "modified during shuffle");
6974 }
6975 tmp = ptr[--i];
6976 ptr[i] = ptr[j];
6977 ptr[j] = tmp;
6978 }
6979 }); /* WB: no new reference */
6980 return ary;
6981}
6982
6983static VALUE
6984rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
6985{
6986 ary = rb_ary_dup(ary);
6987 rb_ary_shuffle_bang(ec, ary, randgen);
6988 return ary;
6989}
6990
6991static const rb_data_type_t ary_sample_memo_type = {
6992 .wrap_struct_name = "ary_sample_memo",
6993 .function = {
6994 .dfree = (RUBY_DATA_FUNC)st_free_table,
6995 },
6996 .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_THREAD_SAFE_FREE
6997};
6998
6999static VALUE
7000ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
7001{
7002 VALUE result;
7003 long n, len, i, j, k, idx[10];
7004 long rnds[numberof(idx)];
7005 long memo_threshold;
7006
7007 len = RARRAY_LEN(ary);
7008 if (!to_array) {
7009 if (len < 2)
7010 i = 0;
7011 else
7012 i = RAND_UPTO(len);
7013
7014 return rb_ary_elt(ary, i);
7015 }
7016 n = NUM2LONG(nv);
7017 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
7018 if (n > len) n = len;
7019 if (n <= numberof(idx)) {
7020 for (i = 0; i < n; ++i) {
7021 rnds[i] = RAND_UPTO(len - i);
7022 }
7023 }
7024 k = len;
7025 len = RARRAY_LEN(ary);
7026 if (len < k && n <= numberof(idx)) {
7027 for (i = 0; i < n; ++i) {
7028 if (rnds[i] >= len - i) return rb_ary_new_capa(0);
7029 }
7030 }
7031 if (n > len) n = len;
7032 switch (n) {
7033 case 0:
7034 return rb_ary_new_capa(0);
7035 case 1:
7036 i = rnds[0];
7037 return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
7038 case 2:
7039 i = rnds[0];
7040 j = rnds[1];
7041 if (j >= i) j++;
7042 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
7043 case 3:
7044 i = rnds[0];
7045 j = rnds[1];
7046 k = rnds[2];
7047 {
7048 long l = j, g = i;
7049 if (j >= i) l = i, g = ++j;
7050 if (k >= l && (++k >= g)) ++k;
7051 }
7052 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
7053 }
7054 memo_threshold =
7055 len < 2560 ? len / 128 :
7056 len < 5120 ? len / 64 :
7057 len < 10240 ? len / 32 :
7058 len / 16;
7059 if (n <= numberof(idx)) {
7060 long sorted[numberof(idx)];
7061 sorted[0] = idx[0] = rnds[0];
7062 for (i=1; i<n; i++) {
7063 k = rnds[i];
7064 for (j = 0; j < i; ++j) {
7065 if (k < sorted[j]) break;
7066 ++k;
7067 }
7068 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
7069 sorted[j] = idx[i] = k;
7070 }
7071 result = rb_ary_new_capa(n);
7072 RARRAY_PTR_USE(result, ptr_result, {
7073 for (i=0; i<n; i++) {
7074 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
7075 }
7076 });
7077 }
7078 else if (n <= memo_threshold / 2) {
7079 long max_idx = 0;
7080 VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0);
7081 st_table *memo = st_init_numtable_with_size(n);
7082 RTYPEDDATA_DATA(vmemo) = memo;
7083 result = rb_ary_new_capa(n);
7084 RARRAY_PTR_USE(result, ptr_result, {
7085 for (i=0; i<n; i++) {
7086 long r = RAND_UPTO(len-i) + i;
7087 ptr_result[i] = r;
7088 if (r > max_idx) max_idx = r;
7089 }
7090 len = RARRAY_LEN(ary);
7091 if (len <= max_idx) n = 0;
7092 else if (n > len) n = len;
7093 RARRAY_PTR_USE(ary, ptr_ary, {
7094 for (i=0; i<n; i++) {
7095 long j2 = j = ptr_result[i];
7096 long i2 = i;
7097 st_data_t value;
7098 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
7099 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
7100 st_insert(memo, (st_data_t)j, (st_data_t)i2);
7101 ptr_result[i] = ptr_ary[j2];
7102 }
7103 });
7104 });
7105 RTYPEDDATA_DATA(vmemo) = 0;
7106 st_free_table(memo);
7107 RB_GC_GUARD(vmemo);
7108 }
7109 else {
7110 result = rb_ary_dup(ary);
7111 RBASIC_CLEAR_CLASS(result);
7112 RB_GC_GUARD(ary);
7113 RARRAY_PTR_USE(result, ptr_result, {
7114 for (i=0; i<n; i++) {
7115 j = RAND_UPTO(len-i) + i;
7116 nv = ptr_result[j];
7117 ptr_result[j] = ptr_result[i];
7118 ptr_result[i] = nv;
7119 }
7120 });
7121 RBASIC_SET_CLASS_RAW(result, rb_cArray);
7122 }
7123 ARY_SET_LEN(result, n);
7124
7125 return result;
7126}
7127
7128static VALUE
7129ary_sized_alloc(rb_execution_context_t *ec, VALUE self)
7130{
7131 return rb_ary_new2(RARRAY_LEN(self));
7132}
7133
7134static VALUE
7135ary_sample0(rb_execution_context_t *ec, VALUE ary)
7136{
7137 return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
7138}
7139
7140static VALUE
7141rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
7142{
7143 long mul;
7144 VALUE n = Qnil;
7145 if (args && (RARRAY_LEN(args) > 0)) {
7146 n = RARRAY_AREF(args, 0);
7147 }
7148 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
7149 if (NIL_P(n)) return DBL2NUM(HUGE_VAL);
7150 mul = NUM2LONG(n);
7151 if (mul <= 0) return INT2FIX(0);
7152 n = LONG2NUM(mul);
7153 return rb_int_mul(rb_ary_length(self), n);
7154}
7155
7156/*
7157 * call-seq:
7158 * cycle(count = nil) {|element| ... } -> nil
7159 * cycle(count = nil) -> new_enumerator
7160 *
7161 * With a block given, may call the block, depending on the value of argument +count+;
7162 * +count+ must be an
7163 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
7164 * or +nil+.
7165 *
7166 * When +count+ is positive,
7167 * calls the block with each element, then does so repeatedly,
7168 * until it has done so +count+ times; returns +nil+:
7169 *
7170 * output = []
7171 * [0, 1].cycle(2) {|element| output.push(element) } # => nil
7172 * output # => [0, 1, 0, 1]
7173 *
7174 * When +count+ is zero or negative, does not call the block:
7175 *
7176 * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
7177 * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
7178 *
7179 * When +count+ is +nil+, cycles forever:
7180 *
7181 * # Prints 0 and 1 forever.
7182 * [0, 1].cycle {|element| puts element }
7183 * [0, 1].cycle(nil) {|element| puts element }
7184 *
7185 * With no block given, returns a new Enumerator.
7186 *
7187 * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7188 */
7189static VALUE
7190rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
7191{
7192 long n, i;
7193
7194 rb_check_arity(argc, 0, 1);
7195
7196 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
7197 if (argc == 0 || NIL_P(argv[0])) {
7198 n = -1;
7199 }
7200 else {
7201 n = NUM2LONG(argv[0]);
7202 if (n <= 0) return Qnil;
7203 }
7204
7205 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
7206 for (i=0; i<RARRAY_LEN(ary); i++) {
7207 rb_yield(RARRAY_AREF(ary, i));
7208 }
7209 }
7210 return Qnil;
7211}
7212
7213/*
7214 * Build a ruby array of the corresponding values and yield it to the
7215 * associated block.
7216 * Return the class of +values+ for reentry check.
7217 */
7218static int
7219yield_indexed_values(const VALUE values, const long r, const long *const p)
7220{
7221 const VALUE result = rb_ary_new2(r);
7222 long i;
7223
7224 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
7225 ARY_SET_LEN(result, r);
7226 rb_yield(result);
7227 return !RBASIC(values)->klass;
7228}
7229
7230/*
7231 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
7232 *
7233 * When we have a complete permutation of array indices, copy the values
7234 * at those indices into a new array and yield that array.
7235 *
7236 * n: the size of the set
7237 * r: the number of elements in each permutation
7238 * p: the array (of size r) that we're filling in
7239 * used: an array of booleans: whether a given index is already used
7240 * values: the Ruby array that holds the actual values to permute
7241 */
7242static void
7243permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
7244{
7245 long i = 0, index = 0;
7246
7247 for (;;) {
7248 const char *const unused = memchr(&used[i], 0, n-i);
7249 if (!unused) {
7250 if (!index) break;
7251 i = p[--index]; /* pop index */
7252 used[i++] = 0; /* index unused */
7253 }
7254 else {
7255 i = unused - used;
7256 p[index] = i;
7257 used[i] = 1; /* mark index used */
7258 ++index;
7259 if (index < r-1) { /* if not done yet */
7260 p[index] = i = 0;
7261 continue;
7262 }
7263 for (i = 0; i < n; ++i) {
7264 if (used[i]) continue;
7265 p[index] = i;
7266 if (!yield_indexed_values(values, r, p)) {
7267 rb_raise(rb_eRuntimeError, "permute reentered");
7268 }
7269 }
7270 i = p[--index]; /* pop index */
7271 used[i] = 0; /* index unused */
7272 p[index] = ++i;
7273 }
7274 }
7275}
7276
7277/*
7278 * Returns the product of from, from-1, ..., from - how_many + 1.
7279 * https://en.wikipedia.org/wiki/Pochhammer_symbol
7280 */
7281static VALUE
7282descending_factorial(long from, long how_many)
7283{
7284 VALUE cnt;
7285 if (how_many > 0) {
7286 cnt = LONG2FIX(from);
7287 while (--how_many > 0) {
7288 long v = --from;
7289 cnt = rb_int_mul(cnt, LONG2FIX(v));
7290 }
7291 }
7292 else {
7293 cnt = LONG2FIX(how_many == 0);
7294 }
7295 return cnt;
7296}
7297
7298static VALUE
7299binomial_coefficient(long comb, long size)
7300{
7301 VALUE r;
7302 long i;
7303 if (comb > size-comb) {
7304 comb = size-comb;
7305 }
7306 if (comb < 0) {
7307 return LONG2FIX(0);
7308 }
7309 else if (comb == 0) {
7310 return LONG2FIX(1);
7311 }
7312 r = LONG2FIX(size);
7313 for (i = 1; i < comb; ++i) {
7314 r = rb_int_mul(r, LONG2FIX(size - i));
7315 r = rb_int_idiv(r, LONG2FIX(i + 1));
7316 }
7317 return r;
7318}
7319
7320static VALUE
7321rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7322{
7323 long n = RARRAY_LEN(ary);
7324 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
7325
7326 return descending_factorial(n, k);
7327}
7328
7329/*
7330 * call-seq:
7331 * permutation(count = self.size) {|permutation| ... } -> self
7332 * permutation(count = self.size) -> new_enumerator
7333 *
7334 * Iterates over permutations of the elements of +self+;
7335 * the order of permutations is indeterminate.
7336 *
7337 * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
7338 * calls the block with each permutation of +self+ of size +count+;
7339 * returns +self+:
7340 *
7341 * a = [0, 1, 2]
7342 * perms = []
7343 * a.permutation(1) {|perm| perms.push(perm) }
7344 * perms # => [[0], [1], [2]]
7345 *
7346 * perms = []
7347 * a.permutation(2) {|perm| perms.push(perm) }
7348 * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
7349 *
7350 * perms = []
7351 * a.permutation(3) {|perm| perms.push(perm) }
7352 * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
7353 *
7354 * When +count+ is zero, calls the block once with a new empty array:
7355 *
7356 * perms = []
7357 * a.permutation(0) {|perm| perms.push(perm) }
7358 * perms # => [[]]
7359 *
7360 * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
7361 * does not call the block:
7362 *
7363 * a.permutation(-1) {|permutation| fail 'Cannot happen' }
7364 * a.permutation(4) {|permutation| fail 'Cannot happen' }
7365 *
7366 * With no block given, returns a new Enumerator.
7367 *
7368 * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7369 */
7370
7371static VALUE
7372rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
7373{
7374 long r, i;
7375
7376 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
7377 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
7378 r = NUM2LONG(argv[0]); /* Permutation size from argument */
7379 }
7380 else {
7381 r = RARRAY_LEN(ary);
7382 }
7383
7384 long n = RARRAY_LEN(ary);
7385
7386 if (r < 0 || n < r) {
7387 /* no permutations: yield nothing */
7388 }
7389 else if (r == 0) { /* exactly one permutation: the zero-length array */
7391 }
7392 else if (r == 1) { /* this is a special, easy case */
7393 for (i = 0; i < RARRAY_LEN(ary); i++) {
7394 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7395 }
7396 }
7397 else { /* this is the general case */
7398 volatile VALUE t0;
7399 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
7400 char *used = (char*)(p + r);
7401 VALUE ary0 = ary_make_hidden_shared_copy(ary); /* private defensive copy of ary */
7402
7403 MEMZERO(used, char, n); /* initialize array */
7404
7405 permute0(n, r, p, used, ary0); /* compute and yield permutations */
7406 ALLOCV_END(t0);
7407 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7408 }
7409 return ary;
7410}
7411
7412static void
7413combinate0(const long len, const long n, long *const stack, const VALUE values)
7414{
7415 long lev = 0;
7416
7417 MEMZERO(stack+1, long, n);
7418 stack[0] = -1;
7419 for (;;) {
7420 for (lev++; lev < n; lev++) {
7421 stack[lev+1] = stack[lev]+1;
7422 }
7423 if (!yield_indexed_values(values, n, stack+1)) {
7424 rb_raise(rb_eRuntimeError, "combination reentered");
7425 }
7426 do {
7427 if (lev == 0) return;
7428 stack[lev--]++;
7429 } while (stack[lev+1]+n == len+lev+1);
7430 }
7431}
7432
7433static VALUE
7434rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
7435{
7436 long n = RARRAY_LEN(ary);
7437 long k = NUM2LONG(RARRAY_AREF(args, 0));
7438
7439 return binomial_coefficient(k, n);
7440}
7441
7442/*
7443 * call-seq:
7444 * combination(count) {|element| ... } -> self
7445 * combination(count) -> new_enumerator
7446 *
7447 * When a block and a positive
7448 * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
7449 * argument +count+ (<tt>0 < count <= self.size</tt>)
7450 * are given, calls the block with each combination of +self+ of size +count+;
7451 * returns +self+:
7452 *
7453 * a = %w[a b c] # => ["a", "b", "c"]
7454 * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
7455 *
7456 * Output:
7457 *
7458 * ["a", "b"]
7459 * ["a", "c"]
7460 * ["b", "c"]
7461 *
7462 * The order of the yielded combinations is not guaranteed.
7463 *
7464 * When +count+ is zero, calls the block once with a new empty array:
7465 *
7466 * a.combination(0) {|combination| p combination }
7467 * [].combination(0) {|combination| p combination }
7468 *
7469 * Output:
7470 *
7471 * []
7472 * []
7473 *
7474 * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
7475 * does not call the block:
7476 *
7477 * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7478 * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
7479 *
7480 * With no block given, returns a new Enumerator.
7481 *
7482 * Related: Array#permutation;
7483 * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
7484 */
7485
7486static VALUE
7487rb_ary_combination(VALUE ary, VALUE num)
7488{
7489 long i, n, len;
7490
7491 n = NUM2LONG(num);
7492 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
7493 len = RARRAY_LEN(ary);
7494 if (n < 0 || len < n) {
7495 /* yield nothing */
7496 }
7497 else if (n == 0) {
7499 }
7500 else if (n == 1) {
7501 for (i = 0; i < RARRAY_LEN(ary); i++) {
7502 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7503 }
7504 }
7505 else {
7506 VALUE ary0 = ary_make_hidden_shared_copy(ary); /* private defensive copy of ary */
7507 volatile VALUE t0;
7508 long *stack = ALLOCV_N(long, t0, n+1);
7509
7510 combinate0(len, n, stack, ary0);
7511 ALLOCV_END(t0);
7512 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7513 }
7514 return ary;
7515}
7516
7517/*
7518 * Compute repeated permutations of +r+ elements of the set
7519 * <code>[0..n-1]</code>.
7520 *
7521 * When we have a complete repeated permutation of array indices, copy the
7522 * values at those indices into a new array and yield that array.
7523 *
7524 * n: the size of the set
7525 * r: the number of elements in each permutation
7526 * p: the array (of size r) that we're filling in
7527 * values: the Ruby array that holds the actual values to permute
7528 */
7529static void
7530rpermute0(const long n, const long r, long *const p, const VALUE values)
7531{
7532 long i = 0, index = 0;
7533
7534 p[index] = i;
7535 for (;;) {
7536 if (++index < r-1) {
7537 p[index] = i = 0;
7538 continue;
7539 }
7540 for (i = 0; i < n; ++i) {
7541 p[index] = i;
7542 if (!yield_indexed_values(values, r, p)) {
7543 rb_raise(rb_eRuntimeError, "repeated permute reentered");
7544 }
7545 }
7546 do {
7547 if (index <= 0) return;
7548 } while ((i = ++p[--index]) >= n);
7549 }
7550}
7551
7552static VALUE
7553rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
7554{
7555 long n = RARRAY_LEN(ary);
7556 long k = NUM2LONG(RARRAY_AREF(args, 0));
7557
7558 if (k < 0) {
7559 return LONG2FIX(0);
7560 }
7561 if (n <= 0) {
7562 return LONG2FIX(!k);
7563 }
7564 return rb_int_positive_pow(n, (unsigned long)k);
7565}
7566
7567/*
7568 * call-seq:
7569 * repeated_permutation(size) {|permutation| ... } -> self
7570 * repeated_permutation(size) -> new_enumerator
7571 *
7572 * With a block given, calls the block with each repeated permutation of length +size+
7573 * of the elements of +self+;
7574 * each permutation is an array;
7575 * returns +self+. The order of the permutations is indeterminate.
7576 *
7577 * If a positive integer argument +size+ is given,
7578 * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
7579 * The number of permutations is <tt>self.size**size</tt>.
7580 *
7581 * Examples:
7582 *
7583 * - +size+ is 1:
7584 *
7585 * p = []
7586 * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
7587 * p # => [[0], [1], [2]]
7588 *
7589 * - +size+ is 2:
7590 *
7591 * p = []
7592 * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
7593 * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
7594 *
7595 * If +size+ is zero, calls the block once with an empty array.
7596 *
7597 * If +size+ is negative, does not call the block:
7598 *
7599 * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
7600 *
7601 * With no block given, returns a new Enumerator.
7602 *
7603 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7604 */
7605static VALUE
7606rb_ary_repeated_permutation(VALUE ary, VALUE num)
7607{
7608 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
7609 long r = NUM2LONG(num); /* Permutation size from argument */
7610 long n = RARRAY_LEN(ary);
7611
7612 if (r < 0) {
7613 /* no permutations: yield nothing */
7614 }
7615 else if (r == 0) { /* exactly one permutation: the zero-length array */
7617 }
7618 else if (r == 1) { /* this is a special, easy case */
7619 for (long i = 0; i < RARRAY_LEN(ary); i++) {
7620 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7621 }
7622 }
7623 else { /* this is the general case */
7624 volatile VALUE t0;
7625 long *p = ALLOCV_N(long, t0, r);
7626 VALUE ary0 = ary_make_hidden_shared_copy(ary); /* private defensive copy of ary */
7627
7628 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
7629 ALLOCV_END(t0);
7630 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7631 }
7632 return ary;
7633}
7634
7635static void
7636rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
7637{
7638 long i = 0, index = 0;
7639
7640 p[index] = i;
7641 for (;;) {
7642 if (++index < r-1) {
7643 p[index] = i;
7644 continue;
7645 }
7646 for (; i < n; ++i) {
7647 p[index] = i;
7648 if (!yield_indexed_values(values, r, p)) {
7649 rb_raise(rb_eRuntimeError, "repeated combination reentered");
7650 }
7651 }
7652 do {
7653 if (index <= 0) return;
7654 } while ((i = ++p[--index]) >= n);
7655 }
7656}
7657
7658static VALUE
7659rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
7660{
7661 long n = RARRAY_LEN(ary);
7662 long k = NUM2LONG(RARRAY_AREF(args, 0));
7663 if (k == 0) {
7664 return LONG2FIX(1);
7665 }
7666 return binomial_coefficient(k, n + k - 1);
7667}
7668
7669/*
7670 * call-seq:
7671 * repeated_combination(size) {|combination| ... } -> self
7672 * repeated_combination(size) -> new_enumerator
7673 *
7674 * With a block given, calls the block with each repeated combination of length +size+
7675 * of the elements of +self+;
7676 * each combination is an array;
7677 * returns +self+. The order of the combinations is indeterminate.
7678 *
7679 * If a positive integer argument +size+ is given,
7680 * calls the block with each +size+-tuple repeated combination of the elements of +self+.
7681 * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
7682 *
7683 * Examples:
7684 *
7685 * - +size+ is 1:
7686 *
7687 * c = []
7688 * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
7689 * c # => [[0], [1], [2]]
7690 *
7691 * - +size+ is 2:
7692 *
7693 * c = []
7694 * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
7695 * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
7696 *
7697 * If +size+ is zero, calls the block once with an empty array.
7698 *
7699 * If +size+ is negative, does not call the block:
7700 *
7701 * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
7702 *
7703 * With no block given, returns a new Enumerator.
7704 *
7705 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7706 */
7707
7708static VALUE
7709rb_ary_repeated_combination(VALUE ary, VALUE num)
7710{
7711 long n, i, len;
7712
7713 n = NUM2LONG(num); /* Combination size from argument */
7714 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
7715 len = RARRAY_LEN(ary);
7716 if (n < 0) {
7717 /* yield nothing */
7718 }
7719 else if (n == 0) {
7721 }
7722 else if (n == 1) {
7723 for (i = 0; i < RARRAY_LEN(ary); i++) {
7724 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
7725 }
7726 }
7727 else if (len == 0) {
7728 /* yield nothing */
7729 }
7730 else {
7731 volatile VALUE t0;
7732 long *p = ALLOCV_N(long, t0, n);
7733 VALUE ary0 = ary_make_hidden_shared_copy(ary); /* private defensive copy of ary */
7734
7735 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
7736 ALLOCV_END(t0);
7737 RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
7738 }
7739 return ary;
7740}
7741
7742/*
7743 * call-seq:
7744 * product(*other_arrays) -> new_array
7745 * product(*other_arrays) {|combination| ... } -> self
7746 *
7747 * Computes all combinations of elements from all the arrays,
7748 * including both +self+ and +other_arrays+:
7749 *
7750 * - The number of combinations is the product of the sizes of all the arrays,
7751 * including both +self+ and +other_arrays+.
7752 * - The order of the returned combinations is indeterminate.
7753 *
7754 * With no block given, returns the combinations as an array of arrays:
7755 *
7756 * p = [0, 1].product([2, 3])
7757 * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7758 * p.size # => 4
7759 * p = [0, 1].product([2, 3], [4, 5])
7760 * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
7761 * p.size # => 8
7762 *
7763 * If +self+ or any argument is empty, returns an empty array:
7764 *
7765 * [].product([2, 3], [4, 5]) # => []
7766 * [0, 1].product([2, 3], []) # => []
7767 *
7768 * If no argument is given, returns an array of 1-element arrays,
7769 * each containing an element of +self+:
7770 *
7771 * [0, 1, 2].product # => [[0], [1], [2]]
7772 *
7773 * With a block given, calls the block with each combination; returns +self+:
7774 *
7775 * p = []
7776 * [0, 1].product([2, 3]) {|combination| p.push(combination) }
7777 * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
7778 *
7779 * If +self+ or any argument is empty, does not call the block:
7780 *
7781 * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
7782 * # => []
7783 * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
7784 * # => [0, 1]
7785 *
7786 * If no argument is given, calls the block with each element of +self+ as a 1-element array:
7787 *
7788 * p = []
7789 * [0, 1].product {|combination| p.push(combination) }
7790 * p # => [[0], [1]]
7791 *
7792 * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
7793 */
7794
7795static VALUE
7796rb_ary_product(int argc, VALUE *argv, VALUE ary)
7797{
7798 int n = argc+1; /* How many arrays we're operating on */
7799 volatile VALUE t0 = rb_ary_hidden_new(n);
7800 volatile VALUE t1 = Qundef;
7801 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
7802 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
7803 VALUE result = Qnil; /* The array we'll be returning, when no block given */
7804 long i,j;
7805 long resultlen = 1;
7806
7807 /* initialize the arrays of arrays */
7808 ARY_SET_LEN(t0, n);
7809 arrays[0] = ary;
7810 for (i = 1; i < n; i++) arrays[i] = Qnil;
7811 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
7812
7813 /* initialize the counters for the arrays */
7814 for (i = 0; i < n; i++) counters[i] = 0;
7815
7816 /* Otherwise, allocate and fill in an array of results */
7817 if (rb_block_given_p()) {
7818 /* Make defensive copies of arrays; exit if any is empty */
7819 for (i = 0; i < n; i++) {
7820 if (RARRAY_LEN(arrays[i]) == 0) goto done;
7821 arrays[i] = ary_make_shared_copy(arrays[i]);
7822 }
7823 }
7824 else {
7825 /* Compute the length of the result array; return [] if any is empty */
7826 for (i = 0; i < n; i++) {
7827 long k = RARRAY_LEN(arrays[i]);
7828 if (k == 0) {
7829 result = rb_ary_new2(0);
7830 goto done;
7831 }
7832 if (MUL_OVERFLOW_LONG_P(resultlen, k))
7833 rb_raise(rb_eRangeError, "too big to product");
7834 resultlen *= k;
7835 }
7836 result = rb_ary_new2(resultlen);
7837 }
7838 for (;;) {
7839 int m;
7840 /* fill in one subarray */
7841 VALUE subarray = rb_ary_new2(n);
7842 for (j = 0; j < n; j++) {
7843 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
7844 }
7845
7846 /* put it on the result array */
7847 if (NIL_P(result)) {
7848 FL_SET(t0, RARRAY_SHARED_ROOT_FLAG);
7849 rb_yield(subarray);
7850 if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
7851 rb_raise(rb_eRuntimeError, "product reentered");
7852 }
7853 else {
7854 FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
7855 }
7856 }
7857 else {
7858 rb_ary_push(result, subarray);
7859 }
7860
7861 /*
7862 * Increment the last counter. If it overflows, reset to 0
7863 * and increment the one before it.
7864 */
7865 m = n-1;
7866 counters[m]++;
7867 while (counters[m] == RARRAY_LEN(arrays[m])) {
7868 counters[m] = 0;
7869 /* If the first counter overflows, we are done */
7870 if (--m < 0) goto done;
7871 counters[m]++;
7872 }
7873 }
7874
7875done:
7876 ALLOCV_END(t1);
7877
7878 return NIL_P(result) ? ary : result;
7879}
7880
7881/*
7882 * call-seq:
7883 * take(count) -> new_array
7884 *
7885 * Returns a new array containing the first +count+ element of +self+
7886 * (as available);
7887 * +count+ must be a non-negative numeric;
7888 * does not modify +self+:
7889 *
7890 * a = ['a', 'b', 'c', 'd']
7891 * a.take(2) # => ["a", "b"]
7892 * a.take(2.1) # => ["a", "b"]
7893 * a.take(50) # => ["a", "b", "c", "d"]
7894 * a.take(0) # => []
7895 *
7896 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7897 */
7898
7899static VALUE
7900rb_ary_take(VALUE obj, VALUE n)
7901{
7902 long len = NUM2LONG(n);
7903 if (len < 0) {
7904 rb_raise(rb_eArgError, "attempt to take negative size");
7905 }
7906 return rb_ary_subseq(obj, 0, len);
7907}
7908
7909/*
7910 * call-seq:
7911 * take_while {|element| ... } -> new_array
7912 * take_while -> new_enumerator
7913 *
7914 * With a block given, calls the block with each successive element of +self+;
7915 * stops iterating if the block returns +false+ or +nil+;
7916 * returns a new array containing those elements for which the block returned a truthy value:
7917 *
7918 * a = [0, 1, 2, 3, 4, 5]
7919 * a.take_while {|element| element < 3 } # => [0, 1, 2]
7920 * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
7921 * a.take_while {|element| false } # => []
7922 *
7923 * With no block given, returns a new Enumerator.
7924 *
7925 * Does not modify +self+.
7926 *
7927 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7928 */
7929
7930static VALUE
7931rb_ary_take_while(VALUE ary)
7932{
7933 long i;
7934
7935 RETURN_ENUMERATOR(ary, 0, 0);
7936 for (i = 0; i < RARRAY_LEN(ary); i++) {
7937 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
7938 }
7939 return rb_ary_take(ary, LONG2FIX(i));
7940}
7941
7942/*
7943 * call-seq:
7944 * drop(count) -> new_array
7945 *
7946 * Returns a new array containing all but the first +count+ element of +self+,
7947 * where +count+ is a non-negative integer;
7948 * does not modify +self+.
7949 *
7950 * Examples:
7951 *
7952 * a = [0, 1, 2, 3, 4, 5]
7953 * a.drop(0) # => [0, 1, 2, 3, 4, 5]
7954 * a.drop(1) # => [1, 2, 3, 4, 5]
7955 * a.drop(2) # => [2, 3, 4, 5]
7956 * a.drop(9) # => []
7957 *
7958 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7959 */
7960
7961static VALUE
7962rb_ary_drop(VALUE ary, VALUE n)
7963{
7964 VALUE result;
7965 long pos = NUM2LONG(n);
7966 if (pos < 0) {
7967 rb_raise(rb_eArgError, "attempt to drop negative size");
7968 }
7969
7970 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
7971 if (NIL_P(result)) result = rb_ary_new();
7972 return result;
7973}
7974
7975/*
7976 * call-seq:
7977 * drop_while {|element| ... } -> new_array
7978 * drop_while -> new_enumerator
7979 *
7980 * With a block given, calls the block with each successive element of +self+;
7981 * stops if the block returns +false+ or +nil+;
7982 * returns a new array _omitting_ those elements for which the block returned a truthy value;
7983 * does not modify +self+:
7984 *
7985 * a = [0, 1, 2, 3, 4, 5]
7986 * a.drop_while {|element| element < 3 } # => [3, 4, 5]
7987 *
7988 * With no block given, returns a new Enumerator.
7989 *
7990 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
7991 */
7992
7993static VALUE
7994rb_ary_drop_while(VALUE ary)
7995{
7996 long i;
7997
7998 RETURN_ENUMERATOR(ary, 0, 0);
7999 for (i = 0; i < RARRAY_LEN(ary); i++) {
8000 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
8001 }
8002 return rb_ary_drop(ary, LONG2FIX(i));
8003}
8004
8005/*
8006 * call-seq:
8007 * any? -> true or false
8008 * any?(object) -> true or false
8009 * any? {|element| ... } -> true or false
8010 *
8011 * Returns whether for any element of +self+, a given criterion is satisfied.
8012 *
8013 * With no block and no argument, returns whether any element of +self+ is truthy:
8014 *
8015 * [nil, false, []].any? # => true # Array object is truthy.
8016 * [nil, false, {}].any? # => true # Hash object is truthy.
8017 * [nil, false, ''].any? # => true # String object is truthy.
8018 * [nil, false].any? # => false # Nil and false are not truthy.
8019 *
8020 * With argument +object+ given,
8021 * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
8022 *
8023 * [nil, false, 0].any?(0) # => true
8024 * [nil, false, 1].any?(0) # => false
8025 * [nil, false, 'food'].any?(/foo/) # => true
8026 * [nil, false, 'food'].any?(/bar/) # => false
8027 *
8028 * With a block given,
8029 * calls the block with each element in +self+;
8030 * returns whether the block returns any truthy value:
8031 *
8032 * [0, 1, 2].any? {|ele| ele < 1 } # => true
8033 * [0, 1, 2].any? {|ele| ele < 0 } # => false
8034 *
8035 * With both a block and argument +object+ given,
8036 * ignores the block and uses +object+ as above.
8037 *
8038 * <b>Special case</b>: returns +false+ if +self+ is empty
8039 * (regardless of any given argument or block).
8040 *
8041 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8042 */
8043
8044static VALUE
8045rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
8046{
8047 long i, len = RARRAY_LEN(ary);
8048
8049 rb_check_arity(argc, 0, 1);
8050 if (!len) return Qfalse;
8051 if (argc) {
8052 if (rb_block_given_p()) {
8053 rb_warn("given block not used");
8054 }
8055 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8056 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
8057 }
8058 }
8059 else if (!rb_block_given_p()) {
8060 for (i = 0; i < len; ++i) {
8061 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
8062 }
8063 }
8064 else {
8065 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8066 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
8067 }
8068 }
8069 return Qfalse;
8070}
8071
8072/*
8073 * call-seq:
8074 * all? -> true or false
8075 * all?(object) -> true or false
8076 * all? {|element| ... } -> true or false
8077 *
8078 * Returns whether for every element of +self+,
8079 * a given criterion is satisfied.
8080 *
8081 * With no block and no argument,
8082 * returns whether every element of +self+ is truthy:
8083 *
8084 * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
8085 * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
8086 * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
8087 *
8088 * With argument +object+ given, returns whether <tt>object === ele</tt>
8089 * for every element +ele+ in +self+:
8090 *
8091 * [0, 0, 0].all?(0) # => true
8092 * [0, 1, 2].all?(1) # => false
8093 * ['food', 'fool', 'foot'].all?(/foo/) # => true
8094 * ['food', 'drink'].all?(/foo/) # => false
8095 *
8096 * With a block given, calls the block with each element in +self+;
8097 * returns whether the block returns only truthy values:
8098 *
8099 * [0, 1, 2].all? { |ele| ele < 3 } # => true
8100 * [0, 1, 2].all? { |ele| ele < 2 } # => false
8101 *
8102 * With both a block and argument +object+ given,
8103 * ignores the block and uses +object+ as above.
8104 *
8105 * <b>Special case</b>: returns +true+ if +self+ is empty
8106 * (regardless of any given argument or block).
8107 *
8108 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8109 */
8110
8111static VALUE
8112rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
8113{
8114 long i, len = RARRAY_LEN(ary);
8115
8116 rb_check_arity(argc, 0, 1);
8117 if (!len) return Qtrue;
8118 if (argc) {
8119 if (rb_block_given_p()) {
8120 rb_warn("given block not used");
8121 }
8122 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8123 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
8124 }
8125 }
8126 else if (!rb_block_given_p()) {
8127 for (i = 0; i < len; ++i) {
8128 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
8129 }
8130 }
8131 else {
8132 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8133 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
8134 }
8135 }
8136 return Qtrue;
8137}
8138
8139/*
8140 * call-seq:
8141 * none? -> true or false
8142 * none?(object) -> true or false
8143 * none? {|element| ... } -> true or false
8144 *
8145 * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
8146 *
8147 * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
8148 * +false+ otherwise:
8149 *
8150 * [nil, false].none? # => true
8151 * [nil, 0, false].none? # => false
8152 * [].none? # => true
8153 *
8154 * With argument +object+ given, returns +false+ if for any element +element+,
8155 * <tt>object === element</tt>; +true+ otherwise:
8156 *
8157 * ['food', 'drink'].none?(/bar/) # => true
8158 * ['food', 'drink'].none?(/foo/) # => false
8159 * [].none?(/foo/) # => true
8160 * [0, 1, 2].none?(3) # => true
8161 * [0, 1, 2].none?(1) # => false
8162 *
8163 * With a block given, calls the block with each element in +self+;
8164 * returns +true+ if the block returns no truthy value, +false+ otherwise:
8165 *
8166 * [0, 1, 2].none? {|element| element > 3 } # => true
8167 * [0, 1, 2].none? {|element| element > 1 } # => false
8168 *
8169 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8170 */
8171
8172static VALUE
8173rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
8174{
8175 long i, len = RARRAY_LEN(ary);
8176
8177 rb_check_arity(argc, 0, 1);
8178 if (!len) return Qtrue;
8179 if (argc) {
8180 if (rb_block_given_p()) {
8181 rb_warn("given block not used");
8182 }
8183 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8184 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
8185 }
8186 }
8187 else if (!rb_block_given_p()) {
8188 for (i = 0; i < len; ++i) {
8189 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
8190 }
8191 }
8192 else {
8193 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8194 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
8195 }
8196 }
8197 return Qtrue;
8198}
8199
8200/*
8201 * call-seq:
8202 * one? -> true or false
8203 * one? {|element| ... } -> true or false
8204 * one?(object) -> true or false
8205 *
8206 * Returns +true+ if exactly one element of +self+ meets a given criterion.
8207 *
8208 * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
8209 * +false+ otherwise:
8210 *
8211 * [nil, 0].one? # => true
8212 * [0, 0].one? # => false
8213 * [nil, nil].one? # => false
8214 * [].one? # => false
8215 *
8216 * With a block given, calls the block with each element in +self+;
8217 * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
8218 *
8219 * [0, 1, 2].one? {|element| element > 0 } # => false
8220 * [0, 1, 2].one? {|element| element > 1 } # => true
8221 * [0, 1, 2].one? {|element| element > 2 } # => false
8222 *
8223 * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
8224 * +false+ otherwise:
8225 *
8226 * [0, 1, 2].one?(0) # => true
8227 * [0, 0, 1].one?(0) # => false
8228 * [1, 1, 2].one?(0) # => false
8229 * ['food', 'drink'].one?(/bar/) # => false
8230 * ['food', 'drink'].one?(/foo/) # => true
8231 * [].one?(/foo/) # => false
8232 *
8233 * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
8234 */
8235
8236static VALUE
8237rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
8238{
8239 long i, len = RARRAY_LEN(ary);
8240 VALUE result = Qfalse;
8241
8242 rb_check_arity(argc, 0, 1);
8243 if (!len) return Qfalse;
8244 if (argc) {
8245 if (rb_block_given_p()) {
8246 rb_warn("given block not used");
8247 }
8248 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8249 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
8250 if (result) return Qfalse;
8251 result = Qtrue;
8252 }
8253 }
8254 }
8255 else if (!rb_block_given_p()) {
8256 for (i = 0; i < len; ++i) {
8257 if (RTEST(RARRAY_AREF(ary, i))) {
8258 if (result) return Qfalse;
8259 result = Qtrue;
8260 }
8261 }
8262 }
8263 else {
8264 for (i = 0; i < RARRAY_LEN(ary); ++i) {
8265 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
8266 if (result) return Qfalse;
8267 result = Qtrue;
8268 }
8269 }
8270 }
8271 return result;
8272}
8273
8274/*
8275 * call-seq:
8276 * dig(index, *identifiers) -> object
8277 *
8278 * Finds and returns the object in nested object
8279 * specified by +index+ and +identifiers+;
8280 * the nested objects may be instances of various classes.
8281 * See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
8282 *
8283 * Examples:
8284 *
8285 * a = [:foo, [:bar, :baz, [:bat, :bam]]]
8286 * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
8287 * a.dig(1, 2) # => [:bat, :bam]
8288 * a.dig(1, 2, 0) # => :bat
8289 * a.dig(1, 2, 3) # => nil
8290 *
8291 * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
8292 */
8293
8294static VALUE
8295rb_ary_dig(int argc, VALUE *argv, VALUE self)
8296{
8298 self = rb_ary_at(self, *argv);
8299 if (!--argc) return self;
8300 ++argv;
8301 return rb_obj_dig(argc, argv, self, Qnil);
8302}
8303
8304static inline VALUE
8305finish_exact_sum(long n, VALUE r, VALUE v, int z)
8306{
8307 if (n != 0)
8308 v = rb_fix_plus(LONG2FIX(n), v);
8309 if (!UNDEF_P(r)) {
8310 v = rb_rational_plus(r, v);
8311 }
8312 else if (!n && z) {
8313 v = rb_fix_plus(LONG2FIX(0), v);
8314 }
8315 return v;
8316}
8317
8318/*
8319 * call-seq:
8320 * sum(init = 0) -> object
8321 * sum(init = 0) {|element| ... } -> object
8322 *
8323 * With no block given, returns the sum of +init+ and all elements of +self+;
8324 * for array +array+ and value +init+, equivalent to:
8325 *
8326 * sum = init
8327 * array.each {|element| sum += element }
8328 * sum
8329 *
8330 * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
8331 *
8332 * Examples:
8333 *
8334 * [0, 1, 2, 3].sum # => 6
8335 * [0, 1, 2, 3].sum(100) # => 106
8336 * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
8337 * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
8338 * # => [2, 3, :foo, :bar, "foo", "bar"]
8339 *
8340 * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
8341 *
8342 * # Raises TypeError: Array can't be coerced into Integer.
8343 * [[:foo, :bar], ['foo', 'bar']].sum(2)
8344 *
8345 * With a block given, calls the block with each element of +self+;
8346 * the block's return value (instead of the element itself) is used as the addend:
8347 *
8348 * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
8349 * # => "Coerced and concatenated: zero1two"
8350 *
8351 * Notes:
8352 *
8353 * - Array#join and Array#flatten may be faster than Array#sum
8354 * for an array of strings or an array of arrays.
8355 * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
8356 *
8357 */
8358
8359static VALUE
8360rb_ary_sum(int argc, VALUE *argv, VALUE ary)
8361{
8362 VALUE e, v, r;
8363 long i, n;
8364 int block_given;
8365
8366 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
8367
8368 block_given = rb_block_given_p();
8369
8370 if (RARRAY_LEN(ary) == 0)
8371 return v;
8372
8373 n = 0;
8374 r = Qundef;
8375
8376 bool init_is_float = RB_FLOAT_TYPE_P(v);
8377 if (init_is_float) {
8378 v = LONG2FIX(0);
8379 }
8380 else if (!RB_INTEGER_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
8381 i = 0;
8382 goto init_is_a_value;
8383 }
8384
8385 for (i = 0; i < RARRAY_LEN(ary); i++) {
8386 e = RARRAY_AREF(ary, i);
8387 if (block_given)
8388 e = rb_yield(e);
8389 if (FIXNUM_P(e)) {
8390 n += FIX2LONG(e); /* should not overflow long type */
8391 if (!FIXABLE(n)) {
8392 v = rb_big_plus(LONG2NUM(n), v);
8393 n = 0;
8394 }
8395 }
8396 else if (RB_BIGNUM_TYPE_P(e))
8397 v = rb_big_plus(e, v);
8398 else if (RB_TYPE_P(e, T_RATIONAL)) {
8399 if (UNDEF_P(r))
8400 r = e;
8401 else
8402 r = rb_rational_plus(r, e);
8403 }
8404 else
8405 goto not_exact;
8406 }
8407 v = finish_exact_sum(n, r, v, argc!=0);
8408 if (init_is_float) v = rb_float_plus(argv[0], v);
8409 return v;
8410
8411 not_exact:
8412 v = finish_exact_sum(n, r, v, i!=0);
8413
8414 if (init_is_float || RB_FLOAT_TYPE_P(e)) {
8415 /*
8416 * Kahan-Babuska balancing compensated summation algorithm
8417 * See https://link.springer.com/article/10.1007/s00607-005-0139-x
8418 */
8419 double f, c;
8420 double x, t;
8421
8422 f = NUM2DBL(v);
8423 c = 0.0;
8424 goto has_float_value;
8425 for (; i < RARRAY_LEN(ary); i++) {
8426 e = RARRAY_AREF(ary, i);
8427 if (block_given)
8428 e = rb_yield(e);
8429 if (RB_FLOAT_TYPE_P(e))
8430 has_float_value:
8431 x = RFLOAT_VALUE(e);
8432 else if (FIXNUM_P(e))
8433 x = FIX2LONG(e);
8434 else if (RB_BIGNUM_TYPE_P(e))
8435 x = rb_big2dbl(e);
8436 else if (RB_TYPE_P(e, T_RATIONAL))
8437 x = rb_num2dbl(e);
8438 else
8439 goto not_float;
8440
8441 if (isnan(f)) continue;
8442 if (isnan(x)) {
8443 f = x;
8444 continue;
8445 }
8446 if (isinf(x)) {
8447 if (isinf(f) && signbit(x) != signbit(f))
8448 f = NAN;
8449 else
8450 f = x;
8451 continue;
8452 }
8453 if (isinf(f)) continue;
8454
8455 t = f + x;
8456 if (fabs(f) >= fabs(x))
8457 c += ((f - t) + x);
8458 else
8459 c += ((x - t) + f);
8460 f = t;
8461 }
8462 f += c;
8463 return DBL2NUM(f);
8464
8465 not_float:
8466 v = DBL2NUM(f);
8467 }
8468
8469 goto has_some_value;
8470 init_is_a_value:
8471 for (; i < RARRAY_LEN(ary); i++) {
8472 e = RARRAY_AREF(ary, i);
8473 if (block_given)
8474 e = rb_yield(e);
8475 has_some_value:
8476 v = rb_funcall(v, idPLUS, 1, e);
8477 }
8478 return v;
8479}
8480
8481/* :nodoc: */
8482static VALUE
8483rb_ary_deconstruct(VALUE ary)
8484{
8485 return ary;
8486}
8487
8488/*
8489 * An \Array object is an ordered, integer-indexed collection of objects,
8490 * called _elements_;
8491 * the object represents
8492 * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
8493 *
8494 * An element may be any object (even another array);
8495 * elements may be any mixture of objects of different types.
8496 *
8497 * Important data structures that use arrays include:
8498 *
8499 * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
8500 * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
8501 * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
8502 * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
8503 * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
8504 * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
8505 * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
8506 *
8507 * There are also array-like data structures:
8508 *
8509 * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
8510 * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
8511 * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
8512 * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
8513 * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
8514 *
8515 * == \Array Indexes
8516 *
8517 * \Array indexing starts at 0, as in C or Java.
8518 *
8519 * A non-negative index is an offset from the first element:
8520 *
8521 * - Index 0 indicates the first element.
8522 * - Index 1 indicates the second element.
8523 * - ...
8524 *
8525 * A negative index is an offset, backwards, from the end of the array:
8526 *
8527 * - Index -1 indicates the last element.
8528 * - Index -2 indicates the next-to-last element.
8529 * - ...
8530 *
8531 *
8532 * === In-Range and Out-of-Range Indexes
8533 *
8534 * A non-negative index is <i>in range</i> if and only if it is smaller than
8535 * the size of the array. For a 3-element array:
8536 *
8537 * - Indexes 0 through 2 are in range.
8538 * - Index 3 is out of range.
8539 *
8540 * A negative index is <i>in range</i> if and only if its absolute value is
8541 * not larger than the size of the array. For a 3-element array:
8542 *
8543 * - Indexes -1 through -3 are in range.
8544 * - Index -4 is out of range.
8545 *
8546 * === Effective Index
8547 *
8548 * Although the effective index into an array is always an integer,
8549 * some methods (both within class \Array and elsewhere)
8550 * accept one or more non-integer arguments that are
8551 * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
8552 *
8553 * == Creating Arrays
8554 *
8555 * You can create an \Array object explicitly with:
8556 *
8557 * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
8558 *
8559 * [1, 'one', :one, [2, 'two', :two]]
8560 *
8561 * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@w-and-w-String-Array-Literals]:
8562 *
8563 * %w[foo bar baz] # => ["foo", "bar", "baz"]
8564 * %w[1 % *] # => ["1", "%", "*"]
8565 *
8566 * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@i+and-I-Symbol-Array+Literals]:
8567 *
8568 * %i[foo bar baz] # => [:foo, :bar, :baz]
8569 * %i[1 % *] # => [:"1", :%, :*]
8570 *
8571 * - Method Kernel#Array:
8572 *
8573 * Array(["a", "b"]) # => ["a", "b"]
8574 * Array(1..5) # => [1, 2, 3, 4, 5]
8575 * Array(key: :value) # => [[:key, :value]]
8576 * Array(nil) # => []
8577 * Array(1) # => [1]
8578 * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
8579 *
8580 * - Method Array.new:
8581 *
8582 * Array.new # => []
8583 * Array.new(3) # => [nil, nil, nil]
8584 * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
8585 * Array.new(3, true) # => [true, true, true]
8586 *
8587 * Note that the last example above populates the array
8588 * with references to the same object.
8589 * This is recommended only in cases where that object is a natively immutable object
8590 * such as a symbol, a numeric, +nil+, +true+, or +false+.
8591 *
8592 * Another way to create an array with various objects, using a block;
8593 * this usage is safe for mutable objects such as hashes, strings or
8594 * other arrays:
8595 *
8596 * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
8597 *
8598 * Here is a way to create a multi-dimensional array:
8599 *
8600 * Array.new(3) {Array.new(3)}
8601 * # => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
8602 *
8603 * A number of Ruby methods, both in the core and in the standard library,
8604 * provide instance method +to_a+, which converts an object to an array.
8605 *
8606 * - ARGF#to_a
8607 * - Array#to_a
8608 * - Enumerable#to_a
8609 * - Hash#to_a
8610 * - MatchData#to_a
8611 * - NilClass#to_a
8612 * - OptionParser#to_a
8613 * - Range#to_a
8614 * - Set#to_a
8615 * - Struct#to_a
8616 * - Time#to_a
8617 * - Benchmark::Tms#to_a
8618 * - CSV::Table#to_a
8619 * - Enumerator::Lazy#to_a
8620 * - Gem::List#to_a
8621 * - Gem::NameTuple#to_a
8622 * - Gem::Platform#to_a
8623 * - Gem::RequestSet::Lockfile::Tokenizer#to_a
8624 * - Gem::SourceList#to_a
8625 * - OpenSSL::X509::Extension#to_a
8626 * - OpenSSL::X509::Name#to_a
8627 * - Racc::ISet#to_a
8628 * - Rinda::RingFinger#to_a
8629 * - Ripper::Lexer::Elem#to_a
8630 * - RubyVM::InstructionSequence#to_a
8631 * - YAML::DBM#to_a
8632 *
8633 * == Example Usage
8634 *
8635 * In addition to the methods it mixes in through the Enumerable module,
8636 * class \Array has proprietary methods for accessing, searching and otherwise
8637 * manipulating arrays.
8638 *
8639 * Some of the more common ones are illustrated below.
8640 *
8641 * == Accessing Elements
8642 *
8643 * Elements in an array can be retrieved using the Array#[] method. It can
8644 * take a single integer argument (a numeric index), a pair of arguments
8645 * (start and length) or a range. Negative indices start counting from the end,
8646 * with -1 being the last element.
8647 *
8648 * arr = [1, 2, 3, 4, 5, 6]
8649 * arr[2] #=> 3
8650 * arr[100] #=> nil
8651 * arr[-3] #=> 4
8652 * arr[2, 3] #=> [3, 4, 5]
8653 * arr[1..4] #=> [2, 3, 4, 5]
8654 * arr[1..-3] #=> [2, 3, 4]
8655 *
8656 * Another way to access a particular array element is by using the #at method
8657 *
8658 * arr.at(0) #=> 1
8659 *
8660 * The #slice method works in an identical manner to Array#[].
8661 *
8662 * To raise an error for indices outside of the array bounds or else to
8663 * provide a default value when that happens, you can use #fetch.
8664 *
8665 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
8666 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
8667 * arr.fetch(100, "oops") #=> "oops"
8668 *
8669 * The special methods #first and #last will return the first and last
8670 * elements of an array, respectively.
8671 *
8672 * arr.first #=> 1
8673 * arr.last #=> 6
8674 *
8675 * To return the first +n+ elements of an array, use #take
8676 *
8677 * arr.take(3) #=> [1, 2, 3]
8678 *
8679 * #drop does the opposite of #take, by returning the elements after +n+
8680 * elements have been dropped:
8681 *
8682 * arr.drop(3) #=> [4, 5, 6]
8683 *
8684 * == Obtaining Information about an \Array
8685 *
8686 * An array keeps track of its own length at all times. To query an array
8687 * about the number of elements it contains, use #length, #count or #size.
8688 *
8689 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
8690 * browsers.length #=> 5
8691 * browsers.count #=> 5
8692 *
8693 * To check whether an array contains any elements at all
8694 *
8695 * browsers.empty? #=> false
8696 *
8697 * To check whether a particular item is included in the array
8698 *
8699 * browsers.include?('Konqueror') #=> false
8700 *
8701 * == Adding Items to an \Array
8702 *
8703 * Items can be added to the end of an array by using either #push or #<<
8704 *
8705 * arr = [1, 2, 3, 4]
8706 * arr.push(5) #=> [1, 2, 3, 4, 5]
8707 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
8708 *
8709 * #unshift will add a new item to the beginning of an array.
8710 *
8711 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
8712 *
8713 * With #insert you can add a new element to an array at any position.
8714 *
8715 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
8716 *
8717 * Using the #insert method, you can also insert multiple values at once:
8718 *
8719 * arr.insert(3, 'orange', 'pear', 'grapefruit')
8720 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
8721 *
8722 * == Removing Items from an \Array
8723 *
8724 * The method #pop removes the last element in an array and returns it:
8725 *
8726 * arr = [1, 2, 3, 4, 5, 6]
8727 * arr.pop #=> 6
8728 * arr #=> [1, 2, 3, 4, 5]
8729 *
8730 * To retrieve and at the same time remove the first item, use #shift:
8731 *
8732 * arr.shift #=> 1
8733 * arr #=> [2, 3, 4, 5]
8734 *
8735 * To delete an element at a particular index:
8736 *
8737 * arr.delete_at(2) #=> 4
8738 * arr #=> [2, 3, 5]
8739 *
8740 * To delete a particular element anywhere in an array, use #delete:
8741 *
8742 * arr = [1, 2, 2, 3]
8743 * arr.delete(2) #=> 2
8744 * arr #=> [1,3]
8745 *
8746 * A useful method if you need to remove +nil+ values from an array is
8747 * #compact:
8748 *
8749 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
8750 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
8751 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
8752 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
8753 * arr #=> ['foo', 0, 'bar', 7, 'baz']
8754 *
8755 * Another common need is to remove duplicate elements from an array.
8756 *
8757 * It has the non-destructive #uniq, and destructive method #uniq!
8758 *
8759 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
8760 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
8761 *
8762 * == Iterating over an \Array
8763 *
8764 * Like all classes that include the Enumerable module, class \Array has an each
8765 * method, which defines what elements should be iterated over and how. In
8766 * case of Array#each, all elements in +self+ are yielded to
8767 * the supplied block in sequence.
8768 *
8769 * Note that this operation leaves the array unchanged.
8770 *
8771 * arr = [1, 2, 3, 4, 5]
8772 * arr.each {|a| print a -= 10, " "}
8773 * # prints: -9 -8 -7 -6 -5
8774 * #=> [1, 2, 3, 4, 5]
8775 *
8776 * Another sometimes useful iterator is #reverse_each which will iterate over
8777 * the elements in the array in reverse order.
8778 *
8779 * words = %w[first second third fourth fifth sixth]
8780 * str = ""
8781 * words.reverse_each {|word| str += "#{word} "}
8782 * p str #=> "sixth fifth fourth third second first "
8783 *
8784 * The #map method can be used to create a new array based on the original
8785 * array, but with the values modified by the supplied block:
8786 *
8787 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
8788 * arr #=> [1, 2, 3, 4, 5]
8789 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
8790 * arr #=> [1, 4, 9, 16, 25]
8791 *
8792 *
8793 * == Selecting Items from an \Array
8794 *
8795 * Elements can be selected from an array according to criteria defined in a
8796 * block. The selection can happen in a destructive or a non-destructive
8797 * manner. While the destructive operations will modify the array they were
8798 * called on, the non-destructive methods usually return a new array with the
8799 * selected elements, but leave the original array unchanged.
8800 *
8801 * === Non-destructive Selection
8802 *
8803 * arr = [1, 2, 3, 4, 5, 6]
8804 * arr.select {|a| a > 3} #=> [4, 5, 6]
8805 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
8806 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
8807 * arr #=> [1, 2, 3, 4, 5, 6]
8808 *
8809 * === Destructive Selection
8810 *
8811 * #select! and #reject! are the corresponding destructive methods to #select
8812 * and #reject
8813 *
8814 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
8815 * opposite result when supplied with the same block:
8816 *
8817 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
8818 * arr #=> [4, 5, 6]
8819 *
8820 * arr = [1, 2, 3, 4, 5, 6]
8821 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
8822 * arr #=> [1, 2, 3]
8823 *
8824 * == What's Here
8825 *
8826 * First, what's elsewhere. Class \Array:
8827 *
8828 * - Inherits from {class Object}[rdoc-ref:Object@Whats-Here].
8829 * - Includes {module Enumerable}[rdoc-ref:Enumerable@Whats-Here],
8830 * which provides dozens of additional methods.
8831 *
8832 * Here, class \Array provides methods that are useful for:
8833 *
8834 * - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
8835 * - {Querying}[rdoc-ref:Array@Methods+for+Querying]
8836 * - {Comparing}[rdoc-ref:Array@Methods+for+Comparing]
8837 * - {Fetching}[rdoc-ref:Array@Methods+for+Fetching]
8838 * - {Assigning}[rdoc-ref:Array@Methods+for+Assigning]
8839 * - {Deleting}[rdoc-ref:Array@Methods+for+Deleting]
8840 * - {Combining}[rdoc-ref:Array@Methods+for+Combining]
8841 * - {Iterating}[rdoc-ref:Array@Methods+for+Iterating]
8842 * - {Converting}[rdoc-ref:Array@Methods+for+Converting]
8843 * - {And more....}[rdoc-ref:Array@Other+Methods]
8844 *
8845 * === Methods for Creating an \Array
8846 *
8847 * - ::[]: Returns a new array populated with given objects.
8848 * - ::new: Returns a new array.
8849 * - ::try_convert: Returns a new array created from a given object.
8850 *
8851 * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
8852 *
8853 * === Methods for Querying
8854 *
8855 * - #all?: Returns whether all elements meet a given criterion.
8856 * - #any?: Returns whether any element meets a given criterion.
8857 * - #count: Returns the count of elements that meet a given criterion.
8858 * - #empty?: Returns whether there are no elements.
8859 * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
8860 * - #hash: Returns the integer hash code.
8861 * - #include?: Returns whether any element <tt>==</tt> a given object.
8862 * - #length (aliased as #size): Returns the count of elements.
8863 * - #none?: Returns whether no element <tt>==</tt> a given object.
8864 * - #one?: Returns whether exactly one element <tt>==</tt> a given object.
8865 * - #rindex: Returns the index of the last element that meets a given criterion.
8866 *
8867 * === Methods for Comparing
8868 *
8869 * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
8870 * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
8871 * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding element in a given object.
8872
8873 * === Methods for Fetching
8874 *
8875 * These methods do not modify +self+.
8876 *
8877 * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
8878 * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
8879 * - #at: Returns the element at a given offset.
8880 * - #bsearch: Returns an element selected via a binary search as determined by a given block.
8881 * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
8882 * - #compact: Returns an array containing all non-+nil+ elements.
8883 * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
8884 * - #drop: Returns trailing elements as determined by a given index.
8885 * - #drop_while: Returns trailing elements as determined by a given block.
8886 * - #fetch: Returns the element at a given offset.
8887 * - #fetch_values: Returns elements at given offsets.
8888 * - #first: Returns one or more leading elements.
8889 * - #last: Returns one or more trailing elements.
8890 * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8891 * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
8892 * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
8893 * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
8894 * - #reject: Returns an array containing elements not rejected by a given block.
8895 * - #reverse: Returns all elements in reverse order.
8896 * - #rotate: Returns all elements with some rotated from one end to the other.
8897 * - #sample: Returns one or more random elements.
8898 * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
8899 * - #shuffle: Returns elements in a random order.
8900 * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
8901 * - #take: Returns leading elements as determined by a given index.
8902 * - #take_while: Returns leading elements as determined by a given block.
8903 * - #uniq: Returns an array containing non-duplicate elements.
8904 * - #values_at: Returns the elements at given offsets.
8905 *
8906 * === Methods for Assigning
8907 *
8908 * These methods add, replace, or reorder elements in +self+.
8909 *
8910 * - #<<: Appends an element.
8911 * - #[]=: Assigns specified elements with a given object.
8912 * - #concat: Appends all elements from given arrays.
8913 * - #fill: Replaces specified elements with specified objects.
8914 * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
8915 * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
8916 * - #insert: Inserts given objects at a given offset; does not replace elements.
8917 * - #push (aliased as #append): Appends elements.
8918 * - #reverse!: Replaces +self+ with its elements reversed.
8919 * - #rotate!: Replaces +self+ with its elements rotated.
8920 * - #shuffle!: Replaces +self+ with its elements in random order.
8921 * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
8922 * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
8923 * - #unshift (aliased as #prepend): Prepends leading elements.
8924 *
8925 * === Methods for Deleting
8926 *
8927 * Each of these methods removes elements from +self+:
8928 *
8929 * - #clear: Removes all elements.
8930 * - #compact!: Removes all +nil+ elements.
8931 * - #delete: Removes elements equal to a given object.
8932 * - #delete_at: Removes the element at a given offset.
8933 * - #delete_if: Removes elements specified by a given block.
8934 * - #keep_if: Removes elements not specified by a given block.
8935 * - #pop: Removes and returns the last element.
8936 * - #reject!: Removes elements specified by a given block.
8937 * - #select! (aliased as #filter!): Removes elements not specified by a given block.
8938 * - #shift: Removes and returns the first element.
8939 * - #slice!: Removes and returns a sequence of elements.
8940 * - #uniq!: Removes duplicates.
8941 *
8942 * === Methods for Combining
8943 *
8944 * - #&: Returns an array containing elements found both in +self+ and a given array.
8945 * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
8946 * - #-: Returns an array containing all elements of +self+ that are not found in a given array.
8947 * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
8948 * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
8949 * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
8950 * - #product: Returns or yields all combinations of elements from +self+ and given arrays.
8951 * - #reverse: Returns an array containing all elements of +self+ in reverse order.
8952 * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
8953 *
8954 * === Methods for Iterating
8955 *
8956 * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
8957 * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
8958 * - #each: Passes each element to a given block.
8959 * - #each_index: Passes each element index to a given block.
8960 * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
8961 * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
8962 * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
8963 * - #reverse_each: Passes each element, in reverse order, to a given block.
8964 *
8965 * === Methods for Converting
8966 *
8967 * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
8968 * - #collect! (aliased as #map!): Replaces each element with a block return-value.
8969 * - #flatten: Returns an array that is a recursive flattening of +self+.
8970 * - #inspect (aliased as #to_s): Returns a new String containing the elements.
8971 * - #join: Returns a new String containing the elements joined by the field separator.
8972 * - #to_a: Returns +self+ or a new array containing all elements.
8973 * - #to_ary: Returns +self+.
8974 * - #to_h: Returns a new hash formed from the elements.
8975 * - #transpose: Transposes +self+, which must be an array of arrays.
8976 * - #zip: Returns a new array of arrays containing +self+ and given arrays.
8977 *
8978 * === Other Methods
8979 *
8980 * - #*: Returns one of the following:
8981 *
8982 * - With integer argument +n+, a new array that is the concatenation
8983 * of +n+ copies of +self+.
8984 * - With string argument +field_separator+, a new string that is equivalent to
8985 * <tt>join(field_separator)</tt>.
8986 *
8987 * - #pack: Packs the elements into a binary sequence.
8988 * - #sum: Returns a sum of elements according to either <tt>+</tt> or a given block.
8989 */
8990
8991void
8992Init_Array(void)
8993{
8994 fake_ary_flags = init_fake_ary_flags();
8995
8996 rb_cArray = rb_define_class("Array", rb_cObject);
8998
8999 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
9000 rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
9001 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
9002 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
9003 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
9004 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
9005
9006 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
9007 rb_define_alias(rb_cArray, "to_s", "inspect");
9008 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
9009 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
9010 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
9011
9012 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
9013 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
9014 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
9015
9017 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
9018 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
9019 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
9020 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
9021 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
9022 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
9023 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
9024 rb_define_method(rb_cArray, "intersect?", rb_ary_intersect_p, 1);
9026 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
9027 rb_define_alias(rb_cArray, "append", "push");
9028 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
9029 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
9030 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
9031 rb_define_alias(rb_cArray, "prepend", "unshift");
9032 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
9034 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
9035 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
9036 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
9037 rb_define_method(rb_cArray, "size", rb_ary_length, 0);
9038 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
9039 rb_define_method(rb_cArray, "find", rb_ary_find, -1);
9040 rb_define_method(rb_cArray, "detect", rb_ary_find, -1);
9041 rb_define_method(rb_cArray, "rfind", rb_ary_rfind, -1);
9042 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
9043 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
9044 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
9045 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
9046 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
9047 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
9048 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
9049 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
9052 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
9053 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
9054 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
9055 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
9056 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
9057 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
9058 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
9059 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
9060 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
9061 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
9062 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
9064 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
9065 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
9066 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
9067 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
9068 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
9069 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
9072 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
9075
9076 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
9077 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
9078
9081
9083 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
9084
9085 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
9086 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
9087 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
9088
9089 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
9090 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
9091 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
9092
9093 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
9094 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
9095 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
9096 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
9097 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
9098 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
9099 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
9100 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
9101 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
9102 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
9103 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
9104 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
9105 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
9106
9107 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
9108 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
9109 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
9110 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
9111 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
9112 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
9113 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
9114 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
9115 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
9116 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
9117 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
9118 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
9120
9121 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
9122
9123 rb_cArray_empty_frozen = RB_OBJ_SET_SHAREABLE(rb_ary_freeze(rb_ary_new()));
9124 rb_vm_register_global_object(rb_cArray_empty_frozen);
9125}
9126
9127#include "array.rbinc"
#define RUBY_ASSERT_ALWAYS(expr,...)
A variant of RUBY_ASSERT that does not interface with RUBY_DEBUG.
Definition assert.h:199
#define RBIMPL_ASSERT_OR_ASSUME(...)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
Definition assert.h:311
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
ruby_coderange_type
What rb_enc_str_coderange() returns.
Definition coderange.h:33
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
Definition class.c:1769
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition class.c:3094
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition class.c:3384
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition eval.c:1035
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition value_type.h:87
#define ENC_CODERANGE_7BIT
Old name of RUBY_ENC_CODERANGE_7BIT.
Definition coderange.h:180
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
Definition fl_type.h:130
#define rb_str_buf_cat2
Old name of rb_usascii_str_new_cstr.
Definition string.h:1707
#define RFLOAT_VALUE
Old name of rb_float_value.
Definition double.h:28
#define T_STRING
Old name of RUBY_T_STRING.
Definition value_type.h:78
#define ENC_CODERANGE_AND(a, b)
Old name of RB_ENC_CODERANGE_AND.
Definition coderange.h:188
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition long.h:48
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
Definition fl_type.h:133
#define rb_str_buf_new2
Old name of rb_str_buf_new_cstr.
Definition string.h:1704
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition fl_type.h:131
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:205
#define rb_ary_new4
Old name of rb_ary_new_from_values.
Definition array.h:659
#define FIXABLE
Old name of RB_FIXABLE.
Definition fixnum.h:25
#define ENCODING_GET(obj)
Old name of RB_ENCODING_GET.
Definition encoding.h:109
#define LONG2FIX
Old name of RB_INT2FIX.
Definition long.h:49
#define ASSUME
Old name of RBIMPL_ASSUME.
Definition assume.h:27
#define T_RATIONAL
Old name of RUBY_T_RATIONAL.
Definition value_type.h:76
#define ALLOC_N
Old name of RB_ALLOC_N.
Definition memory.h:399
#define NUM2DBL
Old name of rb_num2dbl.
Definition double.h:27
#define FL_SET
Old name of RB_FL_SET.
Definition fl_type.h:125
#define rb_ary_new3
Old name of rb_ary_new_from_args.
Definition array.h:658
#define LONG2NUM
Old name of RB_LONG2NUM.
Definition long.h:50
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
Definition string.h:1705
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
Definition st_data_t.h:33
#define NUM2INT
Old name of RB_NUM2INT.
Definition int.h:44
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition long.h:46
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition memory.h:405
#define DBL2NUM
Old name of rb_float_new.
Definition double.h:29
#define FL_TEST
Old name of RB_FL_TEST.
Definition fl_type.h:127
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition long.h:51
#define ENC_CODERANGE_CLEAR(obj)
Old name of RB_ENC_CODERANGE_CLEAR.
Definition coderange.h:187
#define FL_UNSET
Old name of RB_FL_UNSET.
Definition fl_type.h:129
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition array.h:657
#define ENC_CODERANGE_SET(obj, cr)
Old name of RB_ENC_CODERANGE_SET.
Definition coderange.h:186
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
Definition fl_type.h:126
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition memory.h:406
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:478
void rb_iter_break(void)
Breaks from a block.
Definition vm.c:2381
VALUE rb_eFrozenError
FrozenError exception.
Definition error.c:1472
VALUE rb_eRangeError
RangeError exception.
Definition error.c:1477
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1473
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1471
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:468
VALUE rb_eIndexError
IndexError exception.
Definition error.c:1475
void rb_warning(const char *fmt,...)
Issues a warning.
Definition error.c:499
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
Definition error.h:48
VALUE rb_cArray
Array class.
VALUE rb_cObject
Object class.
Definition object.c:60
VALUE rb_mEnumerable
Enumerable module.
Definition enum.c:28
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition object.c:94
VALUE rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass)
Identical to rb_class_new_instance(), except it passes the passed keywords if any to the #initialize ...
Definition object.c:2270
VALUE rb_obj_frozen_p(VALUE obj)
Same as RB_OBJ_FROZEN(), but returns Qtrue/Qfalse instead of #bool.
Definition object.c:1316
int rb_eql(VALUE lhs, VALUE rhs)
Checks for equality of the passed objects, in terms of Object#eql?.
Definition object.c:153
VALUE rb_cNumeric
Numeric class.
Definition numeric.c:200
VALUE rb_cRandom
Random class.
Definition random.c:244
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:234
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition object.c:669
double rb_num2dbl(VALUE num)
Converts an instance of rb_cNumeric into C's double.
Definition object.c:3836
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:140
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
Definition object.c:906
VALUE rb_obj_freeze(VALUE obj)
Same as RB_OBJ_FREEZE(), but returns the given object.
Definition object.c:1309
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
Definition gc.h:504
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
Definition gc.h:492
Encoding relates APIs.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1123
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
Definition vm_eval.c:1081
VALUE rb_call_super(int argc, const VALUE *argv)
This resembles ruby's super.
Definition vm_eval.c:363
VALUE rb_ary_rotate(VALUE ary, long rot)
Destructively rotates the passed array in-place to towards its end.
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Identical to rb_ary_new_from_args(), except how objects are passed.
VALUE rb_ary_cmp(VALUE lhs, VALUE rhs)
Recursively compares each elements of the two arrays one-by-one using <=>.
VALUE rb_ary_rassoc(VALUE alist, VALUE key)
Identical to rb_ary_assoc(), except it scans the passed array from the opposite direction.
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
VALUE rb_ary_assoc(VALUE alist, VALUE key)
Looks up the passed key, assuming the passed array is an alist.
VALUE rb_ary_reverse(VALUE ary)
Destructively reverses the passed array in-place.
VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs)
Queries if the passed two arrays share the same backend storage.
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
VALUE rb_ary_sort(VALUE ary)
Creates a copy of the passed array, whose elements are sorted according to their <=> result.
VALUE rb_ary_resurrect(VALUE ary)
I guess there is no use case of this function in extension libraries, but this is a routine identical...
VALUE rb_ary_dup(VALUE ary)
Duplicates an array.
VALUE rb_ary_includes(VALUE ary, VALUE elem)
Queries if the passed array has the passed entry.
VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
Queries element(s) of an array.
VALUE rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE(*func)(VALUE obj, long oidx))
This was a generalisation of Array#values_at, Struct#values_at, and MatchData#values_at.
void rb_ary_free(VALUE ary)
Destroys the given array for no reason.
VALUE rb_ary_each(VALUE ary)
Iteratively yields each element of the passed array to the implicitly passed block if any.
VALUE rb_ary_delete_at(VALUE ary, long pos)
Destructively removes an element which resides at the specific index of the passed array.
VALUE rb_ary_plus(VALUE lhs, VALUE rhs)
Creates a new array, concatenating the former to the latter.
VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len)
Destructively appends multiple elements at the end of the array.
void rb_ary_modify(VALUE ary)
Declares that the array is about to be modified.
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Replaces the contents of the former object with the contents of the latter.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_to_ary(VALUE obj)
Force converts an object to an array.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_resize(VALUE ary, long len)
Expands or shrinks the passed array to the passed length.
VALUE rb_ary_pop(VALUE ary)
Destructively deletes an element from the end of the passed array and returns what was deleted.
VALUE rb_ary_hidden_new(long capa)
Allocates a hidden (no class) empty array.
VALUE rb_ary_clear(VALUE ary)
Destructively removes everything form an array.
VALUE rb_ary_subseq(VALUE ary, long beg, long len)
Obtains a part of the passed array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_freeze(VALUE obj)
Freeze an array, preventing further modifications.
VALUE rb_ary_to_s(VALUE ary)
Converts an array into a human-readable string.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
VALUE rb_ary_sort_bang(VALUE ary)
Destructively sorts the passed array in-place, according to each elements' <=> result.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
void rb_mem_clear(VALUE *buf, long len)
Fills the memory region with a series of RUBY_Qnil.
VALUE rb_ary_delete(VALUE ary, VALUE elem)
Destructively removes elements from the passed array, so that there would be no elements inside that ...
VALUE rb_ary_join(VALUE ary, VALUE sep)
Recursively stringises the elements of the passed array, flattens that result, then joins the sequenc...
void rb_ary_store(VALUE ary, long key, VALUE val)
Destructively stores the passed value to the passed array's passed index.
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
Definition enumerator.h:208
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
Definition enumerator.h:242
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
Definition error.h:35
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:284
VALUE rb_output_fs
The field separator character for outputs, or the $,.
Definition io.c:206
VALUE rb_int_positive_pow(long x, unsigned long y)
Raises the passed x to the power of y.
Definition numeric.c:4766
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Deconstructs a numerical range.
Definition range.c:1945
size_t rb_set_size(VALUE set)
Returns the number of elements in the set.
Definition set.c:2388
VALUE rb_set_clear(VALUE set)
Removes all entries from set.
Definition set.c:2376
bool rb_set_delete(VALUE set, VALUE element)
Removes the element from from set.
Definition set.c:2382
bool rb_set_add(VALUE set, VALUE element)
Adds element to set.
Definition set.c:2370
void rb_set_foreach(VALUE set, int(*func)(VALUE element, VALUE arg), VALUE arg)
Iterates over a set.
Definition set.c:2346
bool rb_set_lookup(VALUE set, VALUE element)
Whether the set contains the given element.
Definition set.c:2364
VALUE rb_set_new_capa(size_t capa)
Identical to rb_set_new(), except it additionally specifies how many elements it is expected to conta...
Definition set.c:2358
#define rb_hash_uint(h, i)
Just another name of st_hash_uint.
Definition string.h:967
#define rb_hash_end(h)
Just another name of st_hash_end.
Definition string.h:970
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
Definition string.h:1523
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
Definition string.h:1557
#define rb_usascii_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "US ASCII" encoding.
Definition string.h:1592
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
Definition string.c:3879
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition string.c:3500
st_index_t rb_hash_start(st_index_t i)
Starts a series of hashing.
Definition random.c:1714
int rb_str_cmp(VALUE lhs, VALUE rhs)
Compares two strings, as in strcmp(3).
Definition string.c:4329
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition string.c:3047
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
Definition string.c:1769
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
Definition string.c:1902
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
VALUE rb_exec_recursive_paired(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h)
Identical to rb_exec_recursive(), except it checks for the recursion on the ordered pair of { g,...
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition vm_method.c:3693
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
int capa
Designed capacity of the buffer.
Definition io.h:11
int len
Length of the buffer.
Definition io.h:8
#define RB_OBJ_SET_SHAREABLE(obj)
Wrapper of rb_obj_set_shareable().
Definition ractor.h:290
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
Definition ractor.h:255
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
Reentrant implementation of quick sort.
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition iterator.h:58
VALUE rb_yield_values(int n,...)
Identical to rb_yield(), except it takes variadic number of parameters and pass them to the block.
Definition vm_eval.c:1401
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
Definition vm_eval.c:1423
VALUE rb_yield(VALUE val)
Yields the block.
Definition vm_eval.c:1378
#define RBIMPL_ATTR_MAYBE_UNUSED()
Wraps (or simulates) [[maybe_unused]]
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:372
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
Definition memory.h:360
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:167
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
Definition memory.h:384
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
#define RARRAY_LEN
Just another name of rb_array_len.
Definition rarray.h:50
#define RARRAY(obj)
Convenient casting macro.
Definition rarray.h:44
static void RARRAY_ASET(VALUE ary, long i, VALUE v)
Assigns an object in an array.
Definition rarray.h:385
#define RARRAY_PTR_USE(ary, ptr_name, expr)
Declares a section of code where raw pointers are used.
Definition rarray.h:347
static VALUE * RARRAY_PTR(VALUE ary)
Wild use of a C pointer.
Definition rarray.h:365
@ RARRAY_EMBED_LEN_SHIFT
Where RARRAY_EMBED_LEN_MASK resides.
Definition rarray.h:123
#define RARRAY_AREF(a, i)
Definition rarray.h:402
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition rarray.h:51
#define RBASIC(obj)
Convenient casting macro.
Definition rbasic.h:40
void(* RUBY_DATA_FUNC)(void *)
This is the type of callbacks registered to RData.
Definition rdata.h:69
#define StringValue(v)
Ensures that the parameter object is a String.
Definition rstring.h:66
#define RTYPEDDATA_DATA(v)
Convenient getter macro.
Definition rtypeddata.h:106
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
Definition rtypeddata.h:557
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
Definition scan_args.h:78
#define RTEST
This is an old name of RB_TEST.
Ruby's array.
Definition rarray.h:127
struct RBasic basic
Basic part, including flags and class.
Definition rarray.h:130
union RArray::@55 as
Array's specific fields.
const VALUE shared_root
Parent of the array.
Definition rarray.h:165
struct RArray::@55::@56 heap
Arrays that use separated memory region for elements use this pattern.
const VALUE ary[1]
Embedded elements.
Definition rarray.h:187
long capa
Capacity of *ptr.
Definition rarray.h:152
long len
Number of elements of the array.
Definition rarray.h:142
union RArray::@55::@56::@57 aux
Auxiliary info.
const VALUE * ptr
Pointer to the C array that holds the elements of the array.
Definition rarray.h:174
VALUE flags
Per-object flags.
Definition rbasic.h:81
This is the struct that holds necessary info for a struct.
Definition rtypeddata.h:242
const char * wrap_struct_name
Name of structs of this kind.
Definition rtypeddata.h:249
Definition st.h:79
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition value.h:63
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition value_type.h:264
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition value_type.h:376