Ruby: array.c Source File

Ruby 3.2.5p208 (2024-07-26 revision 31d0f1a2e7dbfb60731d1f05b868e1d578cda493)

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