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