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