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