Ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a25176072e02db9254f0e0c84c805cd)
array.c
Go to the documentation of this file.
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#include "ruby/encoding.h"
14#include "ruby/util.h"
15#include "ruby/st.h"
16#include "probes.h"
17#include "id.h"
18#include "debug_counter.h"
19#include "transient_heap.h"
20#include "internal.h"
21
22#if !ARRAY_DEBUG
23# define NDEBUG
24#endif
25#include "ruby_assert.h"
26
28
29/* for OPTIMIZED_CMP: */
30#define id_cmp idCmp
31
32#define ARY_DEFAULT_SIZE 16
33#define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
34#define SMALL_ARRAY_LEN 16
35
36static int
37should_be_T_ARRAY(VALUE ary)
38{
39 return RB_TYPE_P(ary, T_ARRAY);
40}
41
42static int
43should_not_be_shared_and_embedded(VALUE ary)
44{
45 return !FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG);
46}
47
48#define ARY_SHARED_P(ary) \
49 (assert(should_be_T_ARRAY((VALUE)(ary))), \
50 assert(should_not_be_shared_and_embedded((VALUE)ary)), \
51 FL_TEST_RAW((ary),ELTS_SHARED)!=0)
52
53#define ARY_EMBED_P(ary) \
54 (assert(should_be_T_ARRAY((VALUE)(ary))), \
55 assert(should_not_be_shared_and_embedded((VALUE)ary)), \
56 FL_TEST_RAW((ary), RARRAY_EMBED_FLAG) != 0)
57
58#define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
59#define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
60#define ARY_HEAP_CAPA(a) (assert(!ARY_EMBED_P(a)), assert(!ARY_SHARED_ROOT_P(a)), \
61 RARRAY(a)->as.heap.aux.capa)
62
63#define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
64#define ARY_EMBED_LEN(a) \
65 (assert(ARY_EMBED_P(a)), \
66 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
67 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
68#define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE))
69
70#define ARY_OWNS_HEAP_P(a) (assert(should_be_T_ARRAY((VALUE)(a))), \
71 !FL_TEST_RAW((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
72
73#define FL_SET_EMBED(a) do { \
74 assert(!ARY_SHARED_P(a)); \
75 FL_SET((a), RARRAY_EMBED_FLAG); \
76 RARY_TRANSIENT_UNSET(a); \
77 ary_verify(a); \
78} while (0)
79
80#define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
81#define FL_SET_SHARED(ary) do { \
82 assert(!ARY_EMBED_P(ary)); \
83 FL_SET((ary), ELTS_SHARED); \
84} while (0)
85#define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
86
87#define ARY_SET_PTR(ary, p) do { \
88 assert(!ARY_EMBED_P(ary)); \
89 assert(!OBJ_FROZEN(ary)); \
90 RARRAY(ary)->as.heap.ptr = (p); \
91} while (0)
92#define ARY_SET_EMBED_LEN(ary, n) do { \
93 long tmp_n = (n); \
94 assert(ARY_EMBED_P(ary)); \
95 assert(!OBJ_FROZEN(ary)); \
96 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
97 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
98} while (0)
99#define ARY_SET_HEAP_LEN(ary, n) do { \
100 assert(!ARY_EMBED_P(ary)); \
101 RARRAY(ary)->as.heap.len = (n); \
102} while (0)
103#define ARY_SET_LEN(ary, n) do { \
104 if (ARY_EMBED_P(ary)) { \
105 ARY_SET_EMBED_LEN((ary), (n)); \
106 } \
107 else { \
108 ARY_SET_HEAP_LEN((ary), (n)); \
109 } \
110 assert(RARRAY_LEN(ary) == (n)); \
111} while (0)
112#define ARY_INCREASE_PTR(ary, n) do { \
113 assert(!ARY_EMBED_P(ary)); \
114 assert(!OBJ_FROZEN(ary)); \
115 RARRAY(ary)->as.heap.ptr += (n); \
116} while (0)
117#define ARY_INCREASE_LEN(ary, n) do { \
118 assert(!OBJ_FROZEN(ary)); \
119 if (ARY_EMBED_P(ary)) { \
120 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
121 } \
122 else { \
123 RARRAY(ary)->as.heap.len += (n); \
124 } \
125} while (0)
126
127#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
128 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
129#define ARY_SET_CAPA(ary, n) do { \
130 assert(!ARY_EMBED_P(ary)); \
131 assert(!ARY_SHARED_P(ary)); \
132 assert(!OBJ_FROZEN(ary)); \
133 RARRAY(ary)->as.heap.aux.capa = (n); \
134} while (0)
135
136#define ARY_SHARED_ROOT(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared_root)
137#define ARY_SET_SHARED(ary, value) do { \
138 const VALUE _ary_ = (ary); \
139 const VALUE _value_ = (value); \
140 assert(!ARY_EMBED_P(_ary_)); \
141 assert(ARY_SHARED_P(_ary_)); \
142 assert(ARY_SHARED_ROOT_P(_value_)); \
143 RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared_root, _value_); \
144} while (0)
145#define RARRAY_SHARED_ROOT_FLAG FL_USER5
146#define ARY_SHARED_ROOT_P(ary) (assert(should_be_T_ARRAY((VALUE)(ary))), \
147 FL_TEST_RAW((ary), RARRAY_SHARED_ROOT_FLAG))
148#define ARY_SHARED_ROOT_REFCNT(ary) \
149 (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
150#define ARY_SHARED_ROOT_OCCUPIED(ary) (ARY_SHARED_ROOT_REFCNT(ary) == 1)
151#define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \
152 assert(ARY_SHARED_ROOT_P(ary)); \
153 RARRAY(ary)->as.heap.aux.capa = (value); \
154} while (0)
155#define FL_SET_SHARED_ROOT(ary) do { \
156 assert(!ARY_EMBED_P(ary)); \
157 assert(!RARRAY_TRANSIENT_P(ary)); \
158 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
159} while (0)
160
161static inline void
162ARY_SET(VALUE a, long i, VALUE v)
163{
164 assert(!ARY_SHARED_P(a));
165 assert(!OBJ_FROZEN(a));
166
167 RARRAY_ASET(a, i, v);
168}
169#undef RARRAY_ASET
170
171
172#if ARRAY_DEBUG
173#define ary_verify(ary) ary_verify_(ary, __FILE__, __LINE__)
174
175static VALUE
176ary_verify_(VALUE ary, const char *file, int line)
177{
178 assert(RB_TYPE_P(ary, T_ARRAY));
179
180 if (FL_TEST(ary, ELTS_SHARED)) {
181 VALUE root = RARRAY(ary)->as.heap.aux.shared_root;
182 const VALUE *ptr = ARY_HEAP_PTR(ary);
183 const VALUE *root_ptr = RARRAY_CONST_PTR_TRANSIENT(root);
184 long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root);
186 assert(root_ptr <= ptr && ptr + len <= root_ptr + root_len);
187 ary_verify(root);
188 }
189 else if (ARY_EMBED_P(ary)) {
191 assert(!ARY_SHARED_P(ary));
193 }
194 else {
195#if 1
197 long i, len = RARRAY_LEN(ary);
198 volatile VALUE v;
199 if (len > 1) len = 1; /* check only HEAD */
200 for (i=0; i<len; i++) {
201 v = ptr[i]; /* access check */
202 }
203 v = v;
204#endif
205 }
206
207 if (RARRAY_TRANSIENT_P(ary)) {
209 }
210
212
213 return ary;
214}
215
216void
217rb_ary_verify(VALUE ary)
218{
219 ary_verify(ary);
220}
221#else
222#define ary_verify(ary) ((void)0)
223#endif
224
225VALUE *
227{
228#if ARRAY_DEBUG
230#endif
231 return (VALUE *)RARRAY_CONST_PTR_TRANSIENT(ary);
232}
233
234void
236{
237#if ARRAY_DEBUG
239#endif
240}
241
242void
244{
245 while (size--) {
246 *mem++ = Qnil;
247 }
248}
249
250static void
251ary_mem_clear(VALUE ary, long beg, long size)
252{
254 rb_mem_clear(ptr + beg, size);
255 });
256}
257
258static inline void
259memfill(register VALUE *mem, register long size, register VALUE val)
260{
261 while (size--) {
262 *mem++ = val;
263 }
264}
265
266static void
267ary_memfill(VALUE ary, long beg, long size, VALUE val)
268{
270 memfill(ptr + beg, size, val);
271 RB_OBJ_WRITTEN(ary, Qundef, val);
272 });
273}
274
275static void
276ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
277{
278 assert(!ARY_SHARED_P(buff_owner_ary));
279
280 if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
281 rb_gc_writebarrier_remember(buff_owner_ary);
283 MEMCPY(ptr+beg, argv, VALUE, argc);
284 });
285 }
286 else {
287 int i;
289 for (i=0; i<argc; i++) {
290 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
291 }
292 });
293 }
294}
295
296static void
297ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
298{
299 ary_memcpy0(ary, beg, argc, argv, ary);
300}
301
302static VALUE *
303ary_heap_alloc(VALUE ary, size_t capa)
304{
305 VALUE *ptr = rb_transient_heap_alloc(ary, sizeof(VALUE) * capa);
306
307 if (ptr != NULL) {
309 }
310 else {
312 ptr = ALLOC_N(VALUE, capa);
313 }
314
315 return ptr;
316}
317
318static void
319ary_heap_free_ptr(VALUE ary, const VALUE *ptr, long size)
320{
321 if (RARRAY_TRANSIENT_P(ary)) {
322 /* ignore it */
323 }
324 else {
325 ruby_sized_xfree((void *)ptr, size);
326 }
327}
328
329static void
330ary_heap_free(VALUE ary)
331{
332 if (RARRAY_TRANSIENT_P(ary)) {
334 }
335 else {
336 ary_heap_free_ptr(ary, ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
337 }
338}
339
340static void
341ary_heap_realloc(VALUE ary, size_t new_capa)
342{
343 size_t old_capa = ARY_HEAP_CAPA(ary);
344
345 if (RARRAY_TRANSIENT_P(ary)) {
346 if (new_capa <= old_capa) {
347 /* do nothing */
348 }
349 else {
350 VALUE *new_ptr = rb_transient_heap_alloc(ary, sizeof(VALUE) * new_capa);
351
352 if (new_ptr == NULL) {
353 new_ptr = ALLOC_N(VALUE, new_capa);
355 }
356
357 MEMCPY(new_ptr, ARY_HEAP_PTR(ary), VALUE, old_capa);
358 ARY_SET_PTR(ary, new_ptr);
359 }
360 }
361 else {
362 SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, old_capa);
363 }
364 ary_verify(ary);
365}
366
367#if USE_TRANSIENT_HEAP
368static inline void
369rb_ary_transient_heap_evacuate_(VALUE ary, int transient, int promote)
370{
371 if (transient) {
372 VALUE *new_ptr;
373 const VALUE *old_ptr = ARY_HEAP_PTR(ary);
374 long capa = ARY_HEAP_CAPA(ary);
375 long len = ARY_HEAP_LEN(ary);
376
377 if (ARY_SHARED_ROOT_P(ary)) {
378 capa = len;
379 }
380
383 assert(!ARY_PTR_USING_P(ary));
384
385 if (promote) {
386 new_ptr = ALLOC_N(VALUE, capa);
388 }
389 else {
390 new_ptr = ary_heap_alloc(ary, capa);
391 }
392
393 MEMCPY(new_ptr, old_ptr, VALUE, capa);
394 /* do not use ARY_SET_PTR() because they assert !frozen */
395 RARRAY(ary)->as.heap.ptr = new_ptr;
396 }
397
398 ary_verify(ary);
399}
400
401void
403{
404 rb_ary_transient_heap_evacuate_(ary, RARRAY_TRANSIENT_P(ary), promote);
405}
406
407void
409{
411 rb_ary_transient_heap_evacuate_(ary, TRUE, TRUE);
412}
413#else
414void
416{
417 /* do nothing */
418}
419#endif
420
421static void
422ary_resize_capa(VALUE ary, long capacity)
423{
424 assert(RARRAY_LEN(ary) <= capacity);
425 assert(!OBJ_FROZEN(ary));
426 assert(!ARY_SHARED_P(ary));
427
428 if (capacity > RARRAY_EMBED_LEN_MAX) {
429 if (ARY_EMBED_P(ary)) {
430 long len = ARY_EMBED_LEN(ary);
431 VALUE *ptr = ary_heap_alloc(ary, capacity);
432
434 FL_UNSET_EMBED(ary);
435 ARY_SET_PTR(ary, ptr);
436 ARY_SET_HEAP_LEN(ary, len);
437 }
438 else {
439 ary_heap_realloc(ary, capacity);
440 }
441 ARY_SET_CAPA(ary, capacity);
442 }
443 else {
444 if (!ARY_EMBED_P(ary)) {
445 long len = ARY_HEAP_LEN(ary);
446 long old_capa = ARY_HEAP_CAPA(ary);
447 const VALUE *ptr = ARY_HEAP_PTR(ary);
448
449 if (len > capacity) len = capacity;
450 MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
451 ary_heap_free_ptr(ary, ptr, old_capa);
452
453 FL_SET_EMBED(ary);
454 ARY_SET_LEN(ary, len);
455 }
456 }
457
458 ary_verify(ary);
459}
460
461static inline void
462ary_shrink_capa(VALUE ary)
463{
464 long capacity = ARY_HEAP_LEN(ary);
465 long old_capa = ARY_HEAP_CAPA(ary);
466 assert(!ARY_SHARED_P(ary));
467 assert(old_capa >= capacity);
468 if (old_capa > capacity) ary_heap_realloc(ary, capacity);
469
470 ary_verify(ary);
471}
472
473static void
474ary_double_capa(VALUE ary, long min)
475{
476 long new_capa = ARY_CAPA(ary) / 2;
477
478 if (new_capa < ARY_DEFAULT_SIZE) {
479 new_capa = ARY_DEFAULT_SIZE;
480 }
481 if (new_capa >= ARY_MAX_SIZE - min) {
482 new_capa = (ARY_MAX_SIZE - min) / 2;
483 }
484 new_capa += min;
485 ary_resize_capa(ary, new_capa);
486
487 ary_verify(ary);
488}
489
490static void
491rb_ary_decrement_share(VALUE shared_root)
492{
493 if (shared_root) {
494 long num = ARY_SHARED_ROOT_REFCNT(shared_root) - 1;
495 if (num == 0) {
496 rb_ary_free(shared_root);
497 rb_gc_force_recycle(shared_root);
498 }
499 else if (num > 0) {
500 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num);
501 }
502 }
503}
504
505static void
506rb_ary_unshare(VALUE ary)
507{
508 VALUE shared_root = RARRAY(ary)->as.heap.aux.shared_root;
509 rb_ary_decrement_share(shared_root);
510 FL_UNSET_SHARED(ary);
511}
512
513static inline void
514rb_ary_unshare_safe(VALUE ary)
515{
516 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
517 rb_ary_unshare(ary);
518 }
519}
520
521static VALUE
522rb_ary_increment_share(VALUE shared_root)
523{
524 long num = ARY_SHARED_ROOT_REFCNT(shared_root);
525 if (num >= 0) {
526 ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
527 }
528 return shared_root;
529}
530
531static void
532rb_ary_set_shared(VALUE ary, VALUE shared_root)
533{
534 rb_ary_increment_share(shared_root);
535 FL_SET_SHARED(ary);
536 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
537 ARY_SET_SHARED(ary, shared_root);
538}
539
540static inline void
541rb_ary_modify_check(VALUE ary)
542{
543 rb_check_frozen(ary);
544 ary_verify(ary);
545}
546
547void
549{
550 rb_ary_modify_check(ary);
551 if (ARY_SHARED_P(ary)) {
552 long shared_len, len = RARRAY_LEN(ary);
553 VALUE shared_root = ARY_SHARED_ROOT(ary);
554
555 ary_verify(shared_root);
556
557 if (len <= RARRAY_EMBED_LEN_MAX) {
558 const VALUE *ptr = ARY_HEAP_PTR(ary);
559 FL_UNSET_SHARED(ary);
560 FL_SET_EMBED(ary);
562 rb_ary_decrement_share(shared_root);
564 }
565 else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
566 long shift = RARRAY_CONST_PTR_TRANSIENT(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root);
567 FL_UNSET_SHARED(ary);
568 ARY_SET_PTR(ary, RARRAY_CONST_PTR_TRANSIENT(shared_root));
569 ARY_SET_CAPA(ary, shared_len);
571 MEMMOVE(ptr, ptr+shift, VALUE, len);
572 });
573 FL_SET_EMBED(shared_root);
574 rb_ary_decrement_share(shared_root);
575 }
576 else {
577 VALUE *ptr = ary_heap_alloc(ary, len);
579 rb_ary_unshare(ary);
580 ARY_SET_CAPA(ary, len);
581 ARY_SET_PTR(ary, ptr);
582 }
583
585 }
586 ary_verify(ary);
587}
588
589static VALUE
590ary_ensure_room_for_push(VALUE ary, long add_len)
591{
592 long old_len = RARRAY_LEN(ary);
593 long new_len = old_len + add_len;
594 long capa;
595
596 if (old_len > ARY_MAX_SIZE - add_len) {
597 rb_raise(rb_eIndexError, "index %ld too big", new_len);
598 }
599 if (ARY_SHARED_P(ary)) {
600 if (new_len > RARRAY_EMBED_LEN_MAX) {
601 VALUE shared_root = ARY_SHARED_ROOT(ary);
602 if (ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
603 if (ARY_HEAP_PTR(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root) + new_len <= RARRAY_LEN(shared_root)) {
604 rb_ary_modify_check(ary);
605
606 ary_verify(ary);
607 ary_verify(shared_root);
608 return shared_root;
609 }
610 else {
611 /* if array is shared, then it is likely it participate in push/shift pattern */
612 rb_ary_modify(ary);
613 capa = ARY_CAPA(ary);
614 if (new_len > capa - (capa >> 6)) {
615 ary_double_capa(ary, new_len);
616 }
617 ary_verify(ary);
618 return ary;
619 }
620 }
621 }
622 ary_verify(ary);
623 rb_ary_modify(ary);
624 }
625 else {
626 rb_ary_modify_check(ary);
627 }
628 capa = ARY_CAPA(ary);
629 if (new_len > capa) {
630 ary_double_capa(ary, new_len);
631 }
632
633 ary_verify(ary);
634 return ary;
635}
636
637/*
638 * call-seq:
639 * ary.freeze -> ary
640 *
641 * Calls Object#freeze on +ary+ to prevent any further
642 * modification. A RuntimeError will be raised if a modification
643 * attempt is made.
644 *
645 */
646
647VALUE
649{
650 return rb_obj_freeze(ary);
651}
652
653/* This can be used to take a snapshot of an array (with
654 e.g. rb_ary_replace) and check later whether the array has been
655 modified from the snapshot. The snapshot is cheap, though if
656 something does modify the array it will pay the cost of copying
657 it. If Array#pop or Array#shift has been called, the array will
658 be still shared with the snapshot, but the array length will
659 differ. */
660VALUE
662{
663 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
664 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
665 RARRAY(ary1)->as.heap.aux.shared_root == RARRAY(ary2)->as.heap.aux.shared_root &&
666 RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
667 return Qtrue;
668 }
669 return Qfalse;
670}
671
672static VALUE
673ary_alloc(VALUE klass)
674{
676 /* Created array is:
677 * FL_SET_EMBED((VALUE)ary);
678 * ARY_SET_EMBED_LEN((VALUE)ary, 0);
679 */
680 return (VALUE)ary;
681}
682
683static VALUE
684empty_ary_alloc(VALUE klass)
685{
686 RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
687 return ary_alloc(klass);
688}
689
690static VALUE
691ary_new(VALUE klass, long capa)
692{
693 VALUE ary,*ptr;
694
695 if (capa < 0) {
696 rb_raise(rb_eArgError, "negative array size (or size too big)");
697 }
698 if (capa > ARY_MAX_SIZE) {
699 rb_raise(rb_eArgError, "array size too big");
700 }
701
702 RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
703
704 ary = ary_alloc(klass);
705 if (capa > RARRAY_EMBED_LEN_MAX) {
706 ptr = ary_heap_alloc(ary, capa);
707 FL_UNSET_EMBED(ary);
708 ARY_SET_PTR(ary, ptr);
709 ARY_SET_CAPA(ary, capa);
710 ARY_SET_HEAP_LEN(ary, 0);
711 }
712
713 return ary;
714}
715
716VALUE
718{
719 return ary_new(rb_cArray, capa);
720}
721
722VALUE
724{
726}
727
729(rb_ary_new_from_args)(long n, ...)
730{
731 va_list ar;
732 VALUE ary;
733 long i;
734
735 ary = rb_ary_new2(n);
736
737 va_start(ar, n);
738 for (i=0; i<n; i++) {
739 ARY_SET(ary, i, va_arg(ar, VALUE));
740 }
741 va_end(ar);
742
743 ARY_SET_LEN(ary, n);
744 return ary;
745}
746
749{
750 VALUE ary;
751
752 ary = ary_new(klass, n);
753 if (n > 0 && elts) {
754 ary_memcpy(ary, 0, n, elts);
755 ARY_SET_LEN(ary, n);
756 }
757
758 return ary;
759}
760
761VALUE
763{
765}
766
767VALUE
769{
770 VALUE ary = ary_new(0, capa);
772 return ary;
773}
774
775VALUE
777{
778 VALUE ary = ary_new(0, capa);
779 ary_memfill(ary, 0, capa, Qnil);
780 ARY_SET_LEN(ary, capa);
782 return ary;
783}
784
785void
787{
788 if (ARY_OWNS_HEAP_P(ary)) {
789 if (USE_DEBUG_COUNTER &&
790 !ARY_SHARED_ROOT_P(ary) &&
791 ARY_HEAP_CAPA(ary) > RARRAY_LEN(ary)) {
792 RB_DEBUG_COUNTER_INC(obj_ary_extracapa);
793 }
794
795 if (RARRAY_TRANSIENT_P(ary)) {
796 RB_DEBUG_COUNTER_INC(obj_ary_transient);
797 }
798 else {
799 RB_DEBUG_COUNTER_INC(obj_ary_ptr);
800 ary_heap_free(ary);
801 }
802 }
803 else {
804 RB_DEBUG_COUNTER_INC(obj_ary_embed);
805 }
806
807 if (ARY_SHARED_P(ary)) {
808 RB_DEBUG_COUNTER_INC(obj_ary_shared);
809 }
811 RB_DEBUG_COUNTER_INC(obj_ary_shared_root_occupied);
812 }
813}
814
817{
818 if (ARY_OWNS_HEAP_P(ary)) {
819 return ARY_CAPA(ary) * sizeof(VALUE);
820 }
821 else {
822 return 0;
823 }
824}
825
826static inline void
827ary_discard(VALUE ary)
828{
829 rb_ary_free(ary);
830 RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
832}
833
834static VALUE
835ary_make_shared(VALUE ary)
836{
837 assert(!ARY_EMBED_P(ary));
838 ary_verify(ary);
839
840 if (ARY_SHARED_P(ary)) {
841 return ARY_SHARED_ROOT(ary);
842 }
843 else if (ARY_SHARED_ROOT_P(ary)) {
844 return ary;
845 }
846 else if (OBJ_FROZEN(ary)) {
848 ary_shrink_capa(ary);
851 return ary;
852 }
853 else {
854 long capa = ARY_CAPA(ary), len = RARRAY_LEN(ary);
855 const VALUE *ptr;
857
859 ptr = ARY_HEAP_PTR(ary);
860
861 FL_UNSET_EMBED(shared);
862 ARY_SET_LEN((VALUE)shared, capa);
863 ARY_SET_PTR((VALUE)shared, ptr);
864 ary_mem_clear((VALUE)shared, len, capa - len);
865 FL_SET_SHARED_ROOT(shared);
867 FL_SET_SHARED(ary);
868 RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
869 ARY_SET_SHARED(ary, (VALUE)shared);
870 OBJ_FREEZE(shared);
871
872 ary_verify((VALUE)shared);
873 ary_verify(ary);
874
875 return (VALUE)shared;
876 }
877}
878
879static VALUE
880ary_make_substitution(VALUE ary)
881{
882 long len = RARRAY_LEN(ary);
883
884 if (len <= RARRAY_EMBED_LEN_MAX) {
885 VALUE subst = rb_ary_new2(len);
886 ary_memcpy(subst, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary));
887 ARY_SET_EMBED_LEN(subst, len);
888 return subst;
889 }
890 else {
891 return rb_ary_increment_share(ary_make_shared(ary));
892 }
893}
894
895VALUE
897{
898 return rb_ary_new3(2, car, cdr);
899}
900
901VALUE
903{
904 return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
905}
906#define to_ary rb_to_array_type
907
908VALUE
910{
911 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
912}
913
916{
917 return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
918}
919
920/*
921 * call-seq:
922 * Array.try_convert(obj) -> array or nil
923 *
924 * Tries to convert +obj+ into an array, using the +to_ary+ method. Returns
925 * the converted array or +nil+ if +obj+ cannot be converted.
926 * This method can be used to check if an argument is an array.
927 *
928 * Array.try_convert([1]) #=> [1]
929 * Array.try_convert("1") #=> nil
930 *
931 * if tmp = Array.try_convert(arg)
932 * # the argument is an array
933 * elsif tmp = String.try_convert(arg)
934 * # the argument is a string
935 * end
936 *
937 */
938
939static VALUE
940rb_ary_s_try_convert(VALUE dummy, VALUE ary)
941{
942 return rb_check_array_type(ary);
943}
944
945/*
946 * call-seq:
947 * Array.new(size=0, default=nil)
948 * Array.new(array)
949 * Array.new(size) {|index| block }
950 *
951 * Returns a new array.
952 *
953 * In the first form, if no arguments are sent, the new array will be empty.
954 * When a +size+ and an optional +default+ are sent, an array is created with
955 * +size+ copies of +default+. Take notice that all elements will reference the
956 * same object +default+.
957 *
958 * The second form creates a copy of the array passed as a parameter (the
959 * array is generated by calling to_ary on the parameter).
960 *
961 * first_array = ["Matz", "Guido"]
962 *
963 * second_array = Array.new(first_array) #=> ["Matz", "Guido"]
964 *
965 * first_array.equal? second_array #=> false
966 *
967 * In the last form, an array of the given size is created. Each element in
968 * this array is created by passing the element's index to the given block
969 * and storing the return value.
970 *
971 * Array.new(3) {|index| index ** 2}
972 * # => [0, 1, 4]
973 *
974 * == Common gotchas
975 *
976 * When sending the second parameter, the same object will be used as the
977 * value for all the array elements:
978 *
979 * a = Array.new(2, Hash.new)
980 * # => [{}, {}]
981 *
982 * a[0]['cat'] = 'feline'
983 * a # => [{"cat"=>"feline"}, {"cat"=>"feline"}]
984 *
985 * a[1]['cat'] = 'Felix'
986 * a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]
987 *
988 * Since all the Array elements store the same hash, changes to one of them
989 * will affect them all.
990 *
991 * If multiple copies are what you want, you should use the block
992 * version which uses the result of that block each time an element
993 * of the array needs to be initialized:
994 *
995 * a = Array.new(2) {Hash.new}
996 * a[0]['cat'] = 'feline'
997 * a # => [{"cat"=>"feline"}, {}]
998 *
999 */
1000
1001static VALUE
1002rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
1003{
1004 long len;
1005 VALUE size, val;
1006
1007 rb_ary_modify(ary);
1008 if (argc == 0) {
1009 if (ARY_OWNS_HEAP_P(ary) && ARY_HEAP_PTR(ary) != NULL) {
1010 ary_heap_free(ary);
1011 }
1012 rb_ary_unshare_safe(ary);
1013 FL_SET_EMBED(ary);
1014 ARY_SET_EMBED_LEN(ary, 0);
1015 if (rb_block_given_p()) {
1016 rb_warning("given block not used");
1017 }
1018 return ary;
1019 }
1020 rb_scan_args(argc, argv, "02", &size, &val);
1021 if (argc == 1 && !FIXNUM_P(size)) {
1023 if (!NIL_P(val)) {
1024 rb_ary_replace(ary, val);
1025 return ary;
1026 }
1027 }
1028
1029 len = NUM2LONG(size);
1030 /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
1031 if (len < 0) {
1032 rb_raise(rb_eArgError, "negative array size");
1033 }
1034 if (len > ARY_MAX_SIZE) {
1035 rb_raise(rb_eArgError, "array size too big");
1036 }
1037 /* recheck after argument conversion */
1038 rb_ary_modify(ary);
1039 ary_resize_capa(ary, len);
1040 if (rb_block_given_p()) {
1041 long i;
1042
1043 if (argc == 2) {
1044 rb_warn("block supersedes default value argument");
1045 }
1046 for (i=0; i<len; i++) {
1047 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
1048 ARY_SET_LEN(ary, i + 1);
1049 }
1050 }
1051 else {
1052 ary_memfill(ary, 0, len, val);
1053 ARY_SET_LEN(ary, len);
1054 }
1055 return ary;
1056}
1057
1058/*
1059 * Returns a new array populated with the given objects.
1060 *
1061 * Array.[]( 1, 'a', /^A/) # => [1, "a", /^A/]
1062 * Array[ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1063 * [ 1, 'a', /^A/ ] # => [1, "a", /^A/]
1064 */
1065
1066static VALUE
1067rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
1068{
1069 VALUE ary = ary_new(klass, argc);
1070 if (argc > 0 && argv) {
1071 ary_memcpy(ary, 0, argc, argv);
1072 ARY_SET_LEN(ary, argc);
1073 }
1074
1075 return ary;
1076}
1077
1078void
1079rb_ary_store(VALUE ary, long idx, VALUE val)
1080{
1081 long len = RARRAY_LEN(ary);
1082
1083 if (idx < 0) {
1084 idx += len;
1085 if (idx < 0) {
1086 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1087 idx - len, -len);
1088 }
1089 }
1090 else if (idx >= ARY_MAX_SIZE) {
1091 rb_raise(rb_eIndexError, "index %ld too big", idx);
1092 }
1093
1094 rb_ary_modify(ary);
1095 if (idx >= ARY_CAPA(ary)) {
1096 ary_double_capa(ary, idx);
1097 }
1098 if (idx > len) {
1099 ary_mem_clear(ary, len, idx - len + 1);
1100 }
1101
1102 if (idx >= len) {
1103 ARY_SET_LEN(ary, idx + 1);
1104 }
1105 ARY_SET(ary, idx, val);
1106}
1107
1108static VALUE
1109ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
1110{
1111 assert(offset >= 0);
1112 assert(len >= 0);
1113 assert(offset+len <= RARRAY_LEN(ary));
1114
1115 if (len <= RARRAY_EMBED_LEN_MAX) {
1116 VALUE result = ary_alloc(klass);
1117 ary_memcpy(result, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary) + offset);
1118 ARY_SET_EMBED_LEN(result, len);
1119 return result;
1120 }
1121 else {
1122 VALUE shared, result = ary_alloc(klass);
1123 FL_UNSET_EMBED(result);
1124
1125 shared = ary_make_shared(ary);
1127 ARY_SET_LEN(result, RARRAY_LEN(ary));
1128 rb_ary_set_shared(result, shared);
1129
1130 ARY_INCREASE_PTR(result, offset);
1131 ARY_SET_LEN(result, len);
1132
1133 ary_verify(shared);
1134 ary_verify(result);
1135 return result;
1136 }
1137}
1138
1139static VALUE
1140ary_make_shared_copy(VALUE ary)
1141{
1142 return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary));
1143}
1144
1146{
1148 ARY_TAKE_LAST = 1
1150
1151static VALUE
1152ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
1153{
1154 long n;
1155 long len;
1156 long offset = 0;
1157
1158 argc = rb_check_arity(argc, 0, 1);
1159 /* the case optional argument is omitted should be handled in
1160 * callers of this function. if another arity case is added,
1161 * this arity check needs to rewrite. */
1163
1164 n = NUM2LONG(argv[0]);
1165 len = RARRAY_LEN(ary);
1166 if (n > len) {
1167 n = len;
1168 }
1169 else if (n < 0) {
1170 rb_raise(rb_eArgError, "negative array size");
1171 }
1172 if (last) {
1173 offset = len - n;
1174 }
1175 return ary_make_partial(ary, rb_cArray, offset, n);
1176}
1177
1178/*
1179 * call-seq:
1180 * ary << obj -> ary
1181 *
1182 * Append---Pushes the given object on to the end of this array. This
1183 * expression returns the array itself, so several appends
1184 * may be chained together.
1185 *
1186 * a = [ 1, 2 ]
1187 * a << "c" << "d" << [ 3, 4 ]
1188 * #=> [ 1, 2, "c", "d", [ 3, 4 ] ]
1189 * a
1190 * #=> [ 1, 2, "c", "d", [ 3, 4 ] ]
1191 *
1192 */
1193
1194VALUE
1196{
1197 long idx = RARRAY_LEN((ary_verify(ary), ary));
1198 VALUE target_ary = ary_ensure_room_for_push(ary, 1);
1200 RB_OBJ_WRITE(target_ary, &ptr[idx], item);
1201 });
1202 ARY_SET_LEN(ary, idx + 1);
1203 ary_verify(ary);
1204 return ary;
1205}
1206
1207VALUE
1208rb_ary_cat(VALUE ary, const VALUE *argv, long len)
1209{
1210 long oldlen = RARRAY_LEN(ary);
1211 VALUE target_ary = ary_ensure_room_for_push(ary, len);
1212 ary_memcpy0(ary, oldlen, len, argv, target_ary);
1213 ARY_SET_LEN(ary, oldlen + len);
1214 return ary;
1215}
1216
1217/*
1218 * call-seq:
1219 * ary.push(obj, ...) -> ary
1220 * ary.append(obj, ...) -> ary
1221 *
1222 * Append --- Pushes the given object(s) on to the end of this array. This
1223 * expression returns the array itself, so several appends
1224 * may be chained together. See also Array#pop for the opposite
1225 * effect.
1226 *
1227 * a = [ "a", "b", "c" ]
1228 * a.push("d", "e", "f")
1229 * #=> ["a", "b", "c", "d", "e", "f"]
1230 * [1, 2, 3].push(4).push(5)
1231 * #=> [1, 2, 3, 4, 5]
1232 */
1233
1234static VALUE
1235rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
1236{
1237 return rb_ary_cat(ary, argv, argc);
1238}
1239
1240VALUE
1242{
1243 long n;
1244 rb_ary_modify_check(ary);
1245 n = RARRAY_LEN(ary);
1246 if (n == 0) return Qnil;
1247 if (ARY_OWNS_HEAP_P(ary) &&
1248 n * 3 < ARY_CAPA(ary) &&
1250 {
1251 ary_resize_capa(ary, n * 2);
1252 }
1253 --n;
1254 ARY_SET_LEN(ary, n);
1255 ary_verify(ary);
1256 return RARRAY_AREF(ary, n);
1257}
1258
1259/*
1260 * call-seq:
1261 * ary.pop -> obj or nil
1262 * ary.pop(n) -> new_ary
1263 *
1264 * Removes the last element from +self+ and returns it, or
1265 * +nil+ if the array is empty.
1266 *
1267 * If a number +n+ is given, returns an array of the last +n+ elements
1268 * (or less) just like <code>array.slice!(-n, n)</code> does. See also
1269 * Array#push for the opposite effect.
1270 *
1271 * a = [ "a", "b", "c", "d" ]
1272 * a.pop #=> "d"
1273 * a.pop(2) #=> ["b", "c"]
1274 * a #=> ["a"]
1275 */
1276
1277static VALUE
1278rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
1279{
1280 VALUE result;
1281
1282 if (argc == 0) {
1283 return rb_ary_pop(ary);
1284 }
1285
1286 rb_ary_modify_check(ary);
1287 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1288 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
1289 ary_verify(ary);
1290 return result;
1291}
1292
1293VALUE
1295{
1296 VALUE top;
1297 long len = RARRAY_LEN(ary);
1298
1299 rb_ary_modify_check(ary);
1300 if (len == 0) return Qnil;
1301 top = RARRAY_AREF(ary, 0);
1302 if (!ARY_SHARED_P(ary)) {
1303 if (len < ARY_DEFAULT_SIZE) {
1305 MEMMOVE(ptr, ptr+1, VALUE, len-1);
1306 }); /* WB: no new reference */
1307 ARY_INCREASE_LEN(ary, -1);
1308 ary_verify(ary);
1309 return top;
1310 }
1311 assert(!ARY_EMBED_P(ary)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
1312
1313 ARY_SET(ary, 0, Qnil);
1314 ary_make_shared(ary);
1315 }
1318 }
1319 ARY_INCREASE_PTR(ary, 1); /* shift ptr */
1320 ARY_INCREASE_LEN(ary, -1);
1321
1322 ary_verify(ary);
1323
1324 return top;
1325}
1326
1327/*
1328 * call-seq:
1329 * ary.shift -> obj or nil
1330 * ary.shift(n) -> new_ary
1331 *
1332 * Removes the first element of +self+ and returns it (shifting all
1333 * other elements down by one). Returns +nil+ if the array
1334 * is empty.
1335 *
1336 * If a number +n+ is given, returns an array of the first +n+ elements
1337 * (or less) just like <code>array.slice!(0, n)</code> does. With +ary+
1338 * containing only the remainder elements, not including what was shifted to
1339 * +new_ary+. See also Array#unshift for the opposite effect.
1340 *
1341 * args = [ "-m", "-q", "filename" ]
1342 * args.shift #=> "-m"
1343 * args #=> ["-q", "filename"]
1344 *
1345 * args = [ "-m", "-q", "filename" ]
1346 * args.shift(2) #=> ["-m", "-q"]
1347 * args #=> ["filename"]
1348 */
1349
1350static VALUE
1351rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
1352{
1353 VALUE result;
1354 long n;
1355
1356 if (argc == 0) {
1357 return rb_ary_shift(ary);
1358 }
1359
1360 rb_ary_modify_check(ary);
1361 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1362 n = RARRAY_LEN(result);
1363 rb_ary_behead(ary,n);
1364
1365 return result;
1366}
1367
1370{
1371 if (n<=0) return ary;
1372
1373 rb_ary_modify_check(ary);
1374 if (ARY_SHARED_P(ary)) {
1376 setup_occupied_shared:
1377 ary_mem_clear(ary, 0, n);
1378 }
1379 ARY_INCREASE_PTR(ary, n);
1380 }
1381 else {
1382 if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
1384 MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n);
1385 }); /* WB: no new reference */
1386 }
1387 else {
1388 ary_make_shared(ary);
1389 goto setup_occupied_shared;
1390 }
1391 }
1392 ARY_INCREASE_LEN(ary, -n);
1393
1394 ary_verify(ary);
1395 return ary;
1396}
1397
1398static VALUE
1399ary_ensure_room_for_unshift(VALUE ary, int argc)
1400{
1401 long len = RARRAY_LEN(ary);
1402 long new_len = len + argc;
1403 long capa;
1404 const VALUE *head, *sharedp;
1405
1406 if (len > ARY_MAX_SIZE - argc) {
1407 rb_raise(rb_eIndexError, "index %ld too big", new_len);
1408 }
1409
1410 if (ARY_SHARED_P(ary)) {
1411 VALUE shared_root = ARY_SHARED_ROOT(ary);
1412 capa = RARRAY_LEN(shared_root);
1413 if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && capa > new_len) {
1414 rb_ary_modify_check(ary);
1415 head = RARRAY_CONST_PTR_TRANSIENT(ary);
1416 sharedp = RARRAY_CONST_PTR_TRANSIENT(shared_root);
1417 goto makeroom_if_need;
1418 }
1419 }
1420
1421 rb_ary_modify(ary);
1422 capa = ARY_CAPA(ary);
1423 if (capa - (capa >> 6) <= new_len) {
1424 ary_double_capa(ary, new_len);
1425 }
1426
1427 /* use shared array for big "queues" */
1428 if (new_len > ARY_DEFAULT_SIZE * 4) {
1429 ary_verify(ary);
1430
1431 /* make a room for unshifted items */
1432 capa = ARY_CAPA(ary);
1433 ary_make_shared(ary);
1434
1435 head = sharedp = RARRAY_CONST_PTR_TRANSIENT(ary);
1436 goto makeroom;
1437 makeroom_if_need:
1438 if (head - sharedp < argc) {
1439 long room;
1440 makeroom:
1441 room = capa - new_len;
1442 room -= room >> 4;
1443 MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
1444 head = sharedp + argc + room;
1445 }
1446 ARY_SET_PTR(ary, head - argc);
1448
1449 ary_verify(ary);
1450 return ARY_SHARED_ROOT(ary);
1451 }
1452 else {
1453 /* sliding items */
1455 MEMMOVE(ptr + argc, ptr, VALUE, len);
1456 });
1457
1458 ary_verify(ary);
1459 return ary;
1460 }
1461}
1462
1463/*
1464 * call-seq:
1465 * ary.unshift(obj, ...) -> ary
1466 * ary.prepend(obj, ...) -> ary
1467 *
1468 * Prepends objects to the front of +self+, moving other elements upwards.
1469 * See also Array#shift for the opposite effect.
1470 *
1471 * a = [ "b", "c", "d" ]
1472 * a.unshift("a") #=> ["a", "b", "c", "d"]
1473 * a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"]
1474 */
1475
1476static VALUE
1477rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1478{
1479 long len = RARRAY_LEN(ary);
1480 VALUE target_ary;
1481
1482 if (argc == 0) {
1483 rb_ary_modify_check(ary);
1484 return ary;
1485 }
1486
1487 target_ary = ary_ensure_room_for_unshift(ary, argc);
1488 ary_memcpy0(ary, 0, argc, argv, target_ary);
1489 ARY_SET_LEN(ary, len + argc);
1490 return ary;
1491}
1492
1493VALUE
1495{
1496 return rb_ary_unshift_m(1,&item,ary);
1497}
1498
1499/* faster version - use this if you don't need to treat negative offset */
1500static inline VALUE
1501rb_ary_elt(VALUE ary, long offset)
1502{
1503 long len = RARRAY_LEN(ary);
1504 if (len == 0) return Qnil;
1505 if (offset < 0 || len <= offset) {
1506 return Qnil;
1507 }
1508 return RARRAY_AREF(ary, offset);
1509}
1510
1511VALUE
1512rb_ary_entry(VALUE ary, long offset)
1513{
1514 return rb_ary_entry_internal(ary, offset);
1515}
1516
1517VALUE
1518rb_ary_subseq(VALUE ary, long beg, long len)
1519{
1520 VALUE klass;
1521 long alen = RARRAY_LEN(ary);
1522
1523 if (beg > alen) return Qnil;
1524 if (beg < 0 || len < 0) return Qnil;
1525
1526 if (alen < len || alen < beg + len) {
1527 len = alen - beg;
1528 }
1529 klass = rb_obj_class(ary);
1530 if (len == 0) return ary_new(klass, 0);
1531
1532 return ary_make_partial(ary, klass, beg, len);
1533}
1534
1535static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
1536
1537/*
1538 * call-seq:
1539 * ary[index] -> obj or nil
1540 * ary[start, length] -> new_ary or nil
1541 * ary[range] -> new_ary or nil
1542 * ary.slice(index) -> obj or nil
1543 * ary.slice(start, length) -> new_ary or nil
1544 * ary.slice(range) -> new_ary or nil
1545 *
1546 * Element Reference --- Returns the element at +index+, or returns a
1547 * subarray starting at the +start+ index and continuing for +length+
1548 * elements, or returns a subarray specified by +range+ of indices.
1549 *
1550 * Negative indices count backward from the end of the array (-1 is the last
1551 * element). For +start+ and +range+ cases the starting index is just before
1552 * an element. Additionally, an empty array is returned when the starting
1553 * index for an element range is at the end of the array.
1554 *
1555 * Returns +nil+ if the index (or starting index) are out of range.
1556 *
1557 * a = [ "a", "b", "c", "d", "e" ]
1558 * a[2] + a[0] + a[1] #=> "cab"
1559 * a[6] #=> nil
1560 * a[1, 2] #=> [ "b", "c" ]
1561 * a[1..3] #=> [ "b", "c", "d" ]
1562 * a[4..7] #=> [ "e" ]
1563 * a[6..10] #=> nil
1564 * a[-3, 3] #=> [ "c", "d", "e" ]
1565 * # special cases
1566 * a[5] #=> nil
1567 * a[6, 1] #=> nil
1568 * a[5, 1] #=> []
1569 * a[5..10] #=> []
1570 *
1571 */
1572
1573VALUE
1575{
1576 rb_check_arity(argc, 1, 2);
1577 if (argc == 2) {
1578 return rb_ary_aref2(ary, argv[0], argv[1]);
1579 }
1580 return rb_ary_aref1(ary, argv[0]);
1581}
1582
1583VALUE
1584rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
1585{
1586 long beg = NUM2LONG(b);
1587 long len = NUM2LONG(e);
1588 if (beg < 0) {
1589 beg += RARRAY_LEN(ary);
1590 }
1591 return rb_ary_subseq(ary, beg, len);
1592}
1593
1596{
1597 long beg, len;
1598
1599 /* special case - speeding up */
1600 if (FIXNUM_P(arg)) {
1601 return rb_ary_entry(ary, FIX2LONG(arg));
1602 }
1603 /* check if idx is Range */
1604 switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
1605 case Qfalse:
1606 break;
1607 case Qnil:
1608 return Qnil;
1609 default:
1610 return rb_ary_subseq(ary, beg, len);
1611 }
1612 return rb_ary_entry(ary, NUM2LONG(arg));
1613}
1614
1615/*
1616 * call-seq:
1617 * ary.at(index) -> obj or nil
1618 *
1619 * Returns the element at +index+. A negative index counts from the end of
1620 * +self+. Returns +nil+ if the index is out of range. See also
1621 * Array#[].
1622 *
1623 * a = [ "a", "b", "c", "d", "e" ]
1624 * a.at(0) #=> "a"
1625 * a.at(-1) #=> "e"
1626 */
1627
1628VALUE
1630{
1631 return rb_ary_entry(ary, NUM2LONG(pos));
1632}
1633
1634/*
1635 * call-seq:
1636 * ary.first -> obj or nil
1637 * ary.first(n) -> new_ary
1638 *
1639 * Returns the first element, or the first +n+ elements, of the array.
1640 * If the array is empty, the first form returns +nil+, and the
1641 * second form returns an empty array. See also Array#last for
1642 * the opposite effect.
1643 *
1644 * a = [ "q", "r", "s", "t" ]
1645 * a.first #=> "q"
1646 * a.first(2) #=> ["q", "r"]
1647 */
1648
1649static VALUE
1650rb_ary_first(int argc, VALUE *argv, VALUE ary)
1651{
1652 if (argc == 0) {
1653 if (RARRAY_LEN(ary) == 0) return Qnil;
1654 return RARRAY_AREF(ary, 0);
1655 }
1656 else {
1657 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1658 }
1659}
1660
1661/*
1662 * call-seq:
1663 * ary.last -> obj or nil
1664 * ary.last(n) -> new_ary
1665 *
1666 * Returns the last element(s) of +self+. If the array is empty,
1667 * the first form returns +nil+.
1668 *
1669 * See also Array#first for the opposite effect.
1670 *
1671 * a = [ "w", "x", "y", "z" ]
1672 * a.last #=> "z"
1673 * a.last(2) #=> ["y", "z"]
1674 */
1675
1676VALUE
1678{
1679 if (argc == 0) {
1680 long len = RARRAY_LEN(ary);
1681 if (len == 0) return Qnil;
1682 return RARRAY_AREF(ary, len-1);
1683 }
1684 else {
1685 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1686 }
1687}
1688
1689/*
1690 * call-seq:
1691 * ary.fetch(index) -> obj
1692 * ary.fetch(index, default) -> obj
1693 * ary.fetch(index) {|index| block} -> obj
1694 *
1695 * Tries to return the element at position +index+, but throws an IndexError
1696 * exception if the referenced +index+ lies outside of the array bounds. This
1697 * error can be prevented by supplying a second argument, which will act as a
1698 * +default+ value.
1699 *
1700 * Alternatively, if a block is given it will only be executed when an
1701 * invalid +index+ is referenced.
1702 *
1703 * Negative values of +index+ count from the end of the array.
1704 *
1705 * a = [ 11, 22, 33, 44 ]
1706 * a.fetch(1) #=> 22
1707 * a.fetch(-1) #=> 44
1708 * a.fetch(4, 'cat') #=> "cat"
1709 * a.fetch(100) {|i| puts "#{i} is out of bounds"}
1710 * #=> "100 is out of bounds"
1711 */
1712
1713static VALUE
1714rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
1715{
1716 VALUE pos, ifnone;
1717 long block_given;
1718 long idx;
1719
1720 rb_scan_args(argc, argv, "11", &pos, &ifnone);
1721 block_given = rb_block_given_p();
1722 if (block_given && argc == 2) {
1723 rb_warn("block supersedes default value argument");
1724 }
1725 idx = NUM2LONG(pos);
1726
1727 if (idx < 0) {
1728 idx += RARRAY_LEN(ary);
1729 }
1730 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
1731 if (block_given) return rb_yield(pos);
1732 if (argc == 1) {
1733 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
1734 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
1735 }
1736 return ifnone;
1737 }
1738 return RARRAY_AREF(ary, idx);
1739}
1740
1741/*
1742 * call-seq:
1743 * ary.find_index(obj) -> int or nil
1744 * ary.find_index {|item| block} -> int or nil
1745 * ary.find_index -> Enumerator
1746 * ary.index(obj) -> int or nil
1747 * ary.index {|item| block} -> int or nil
1748 * ary.index -> Enumerator
1749 *
1750 * Returns the _index_ of the first object in +ary+ such that the object is
1751 * <code>==</code> to +obj+.
1752 *
1753 * If a block is given instead of an argument, returns the _index_ of the
1754 * first object for which the block returns +true+. Returns +nil+ if no
1755 * match is found.
1756 *
1757 * See also Array#rindex.
1758 *
1759 * An Enumerator is returned if neither a block nor argument is given.
1760 *
1761 * a = [ "a", "b", "c" ]
1762 * a.index("b") #=> 1
1763 * a.index("z") #=> nil
1764 * a.index {|x| x == "b"} #=> 1
1765 */
1766
1767static VALUE
1768rb_ary_index(int argc, VALUE *argv, VALUE ary)
1769{
1770 VALUE val;
1771 long i;
1772
1773 if (argc == 0) {
1774 RETURN_ENUMERATOR(ary, 0, 0);
1775 for (i=0; i<RARRAY_LEN(ary); i++) {
1776 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
1777 return LONG2NUM(i);
1778 }
1779 }
1780 return Qnil;
1781 }
1782 rb_check_arity(argc, 0, 1);
1783 val = argv[0];
1784 if (rb_block_given_p())
1785 rb_warn("given block not used");
1786 for (i=0; i<RARRAY_LEN(ary); i++) {
1787 VALUE e = RARRAY_AREF(ary, i);
1788 if (rb_equal(e, val)) {
1789 return LONG2NUM(i);
1790 }
1791 }
1792 return Qnil;
1793}
1794
1795/*
1796 * call-seq:
1797 * ary.rindex(obj) -> int or nil
1798 * ary.rindex {|item| block} -> int or nil
1799 * ary.rindex -> Enumerator
1800 *
1801 * Returns the _index_ of the last object in +self+ <code>==</code> to +obj+.
1802 *
1803 * If a block is given instead of an argument, returns the _index_ of the
1804 * first object for which the block returns +true+, starting from the last
1805 * object.
1806 *
1807 * Returns +nil+ if no match is found.
1808 *
1809 * See also Array#index.
1810 *
1811 * If neither block nor argument is given, an Enumerator is returned instead.
1812 *
1813 * a = [ "a", "b", "b", "b", "c" ]
1814 * a.rindex("b") #=> 3
1815 * a.rindex("z") #=> nil
1816 * a.rindex {|x| x == "b"} #=> 3
1817 */
1818
1819static VALUE
1820rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
1821{
1822 VALUE val;
1823 long i = RARRAY_LEN(ary), len;
1824
1825 if (argc == 0) {
1826 RETURN_ENUMERATOR(ary, 0, 0);
1827 while (i--) {
1828 if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
1829 return LONG2NUM(i);
1830 if (i > (len = RARRAY_LEN(ary))) {
1831 i = len;
1832 }
1833 }
1834 return Qnil;
1835 }
1836 rb_check_arity(argc, 0, 1);
1837 val = argv[0];
1838 if (rb_block_given_p())
1839 rb_warn("given block not used");
1840 while (i--) {
1841 VALUE e = RARRAY_AREF(ary, i);
1842 if (rb_equal(e, val)) {
1843 return LONG2NUM(i);
1844 }
1845 if (i > RARRAY_LEN(ary)) {
1846 break;
1847 }
1848 }
1849 return Qnil;
1850}
1851
1852VALUE
1854{
1856
1857 if (!NIL_P(tmp)) return tmp;
1858 return rb_ary_new3(1, obj);
1859}
1860
1861static void
1862rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
1863{
1864 long olen;
1865 long rofs;
1866
1867 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
1868 olen = RARRAY_LEN(ary);
1869 if (beg < 0) {
1870 beg += olen;
1871 if (beg < 0) {
1872 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1873 beg - olen, -olen);
1874 }
1875 }
1876 if (olen < len || olen < beg + len) {
1877 len = olen - beg;
1878 }
1879
1880 {
1881 const VALUE *optr = RARRAY_CONST_PTR_TRANSIENT(ary);
1882 rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
1883 }
1884
1885 if (beg >= olen) {
1886 VALUE target_ary;
1887 if (beg > ARY_MAX_SIZE - rlen) {
1888 rb_raise(rb_eIndexError, "index %ld too big", beg);
1889 }
1890 target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
1891 len = beg + rlen;
1892 ary_mem_clear(ary, olen, beg - olen);
1893 if (rlen > 0) {
1894 if (rofs != -1) rptr = RARRAY_CONST_PTR_TRANSIENT(ary) + rofs;
1895 ary_memcpy0(ary, beg, rlen, rptr, target_ary);
1896 }
1897 ARY_SET_LEN(ary, len);
1898 }
1899 else {
1900 long alen;
1901
1902 if (olen - len > ARY_MAX_SIZE - rlen) {
1903 rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
1904 }
1905 rb_ary_modify(ary);
1906 alen = olen + rlen - len;
1907 if (alen >= ARY_CAPA(ary)) {
1908 ary_double_capa(ary, alen);
1909 }
1910
1911 if (len != rlen) {
1913 MEMMOVE(ptr + beg + rlen, ptr + beg + len,
1914 VALUE, olen - (beg + len)));
1915 ARY_SET_LEN(ary, alen);
1916 }
1917 if (rlen > 0) {
1918 if (rofs != -1) rptr = RARRAY_CONST_PTR_TRANSIENT(ary) + rofs;
1919 /* give up wb-protected ary */
1920 RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary);
1921
1922 /* do not use RARRAY_PTR() because it can causes GC.
1923 * ary can contain T_NONE object because it is not cleared.
1924 */
1926 MEMMOVE(ptr + beg, rptr, VALUE, rlen));
1927 }
1928 }
1929}
1930
1931void
1933{
1934 long capa;
1935
1936 rb_ary_modify_check(ary);
1937 if (ARY_SHARED_P(ary)) {
1938 rb_raise(rb_eRuntimeError, "can't set length of shared ");
1939 }
1940 if (len > (capa = (long)ARY_CAPA(ary))) {
1941 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
1942 }
1943 ARY_SET_LEN(ary, len);
1944}
1945
1954VALUE
1956{
1957 long olen;
1958
1959 rb_ary_modify(ary);
1960 olen = RARRAY_LEN(ary);
1961 if (len == olen) return ary;
1962 if (len > ARY_MAX_SIZE) {
1963 rb_raise(rb_eIndexError, "index %ld too big", len);
1964 }
1965 if (len > olen) {
1966 if (len >= ARY_CAPA(ary)) {
1967 ary_double_capa(ary, len);
1968 }
1969 ary_mem_clear(ary, olen, len - olen);
1970 ARY_SET_LEN(ary, len);
1971 }
1972 else if (ARY_EMBED_P(ary)) {
1973 ARY_SET_EMBED_LEN(ary, len);
1974 }
1975 else if (len <= RARRAY_EMBED_LEN_MAX) {
1977 MEMCPY(tmp, ARY_HEAP_PTR(ary), VALUE, len);
1978 ary_discard(ary);
1979 MEMCPY((VALUE *)ARY_EMBED_PTR(ary), tmp, VALUE, len); /* WB: no new reference */
1980 ARY_SET_EMBED_LEN(ary, len);
1981 }
1982 else {
1983 if (olen > len + ARY_DEFAULT_SIZE) {
1984 ary_heap_realloc(ary, len);
1985 ARY_SET_CAPA(ary, len);
1986 }
1987 ARY_SET_HEAP_LEN(ary, len);
1988 }
1989 ary_verify(ary);
1990 return ary;
1991}
1992
1993/*
1994 * call-seq:
1995 * ary[index] = obj -> obj
1996 * ary[start, length] = obj or other_ary or nil -> obj or other_ary or nil
1997 * ary[range] = obj or other_ary or nil -> obj or other_ary or nil
1998 *
1999 * Element Assignment --- Sets the element at +index+, or replaces a subarray
2000 * from the +start+ index for +length+ elements, or replaces a subarray
2001 * specified by the +range+ of indices.
2002 *
2003 * If indices are greater than the current capacity of the array, the array
2004 * grows automatically. Elements are inserted into the array at +start+ if
2005 * +length+ is zero.
2006 *
2007 * Negative indices will count backward from the end of the array. For
2008 * +start+ and +range+ cases the starting index is just before an element.
2009 *
2010 * An IndexError is raised if a negative index points past the beginning of
2011 * the array.
2012 *
2013 * See also Array#push, and Array#unshift.
2014 *
2015 * a = Array.new
2016 * a[4] = "4"; #=> [nil, nil, nil, nil, "4"]
2017 * a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
2018 * a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"]
2019 * a[0, 2] = "?" #=> ["?", 2, nil, "4"]
2020 * a[0..2] = "A" #=> ["A", "4"]
2021 * a[-1] = "Z" #=> ["A", "Z"]
2022 * a[1..-1] = nil #=> ["A", nil]
2023 * a[1..-1] = [] #=> ["A"]
2024 * a[0, 0] = [ 1, 2 ] #=> [1, 2, "A"]
2025 * a[3, 0] = "B" #=> [1, 2, "A", "B"]
2026 */
2027
2028static VALUE
2029rb_ary_aset(int argc, VALUE *argv, VALUE ary)
2030{
2031 long offset, beg, len;
2032 VALUE rpl;
2033
2034 if (argc == 3) {
2035 rb_ary_modify_check(ary);
2036 beg = NUM2LONG(argv[0]);
2037 len = NUM2LONG(argv[1]);
2038 goto range;
2039 }
2040 rb_check_arity(argc, 2, 2);
2041 rb_ary_modify_check(ary);
2042 if (FIXNUM_P(argv[0])) {
2043 offset = FIX2LONG(argv[0]);
2044 goto fixnum;
2045 }
2046 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
2047 /* check if idx is Range */
2048 range:
2049 rpl = rb_ary_to_ary(argv[argc-1]);
2050 rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR_TRANSIENT(rpl), RARRAY_LEN(rpl));
2051 RB_GC_GUARD(rpl);
2052 return argv[argc-1];
2053 }
2054
2055 offset = NUM2LONG(argv[0]);
2056fixnum:
2057 rb_ary_store(ary, offset, argv[1]);
2058 return argv[1];
2059}
2060
2061/*
2062 * call-seq:
2063 * ary.insert(index, obj...) -> ary
2064 *
2065 * Inserts the given values before the element with the given +index+.
2066 *
2067 * Negative indices count backwards from the end of the array, where +-1+ is
2068 * the last element. If a negative index is used, the given values will be
2069 * inserted after that element, so using an index of +-1+ will insert the
2070 * values at the end of the array.
2071 *
2072 * a = %w{ a b c d }
2073 * a.insert(2, 99) #=> ["a", "b", 99, "c", "d"]
2074 * a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
2075 */
2076
2077static VALUE
2078rb_ary_insert(int argc, VALUE *argv, VALUE ary)
2079{
2080 long pos;
2081
2083 rb_ary_modify_check(ary);
2084 pos = NUM2LONG(argv[0]);
2085 if (argc == 1) return ary;
2086 if (pos == -1) {
2087 pos = RARRAY_LEN(ary);
2088 }
2089 else if (pos < 0) {
2090 long minpos = -RARRAY_LEN(ary) - 1;
2091 if (pos < minpos) {
2092 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
2093 pos, minpos);
2094 }
2095 pos++;
2096 }
2097 rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
2098 return ary;
2099}
2100
2101static VALUE
2102rb_ary_length(VALUE ary);
2103
2104static VALUE
2105ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
2106{
2107 return rb_ary_length(ary);
2108}
2109
2110/*
2111 * call-seq:
2112 * ary.each {|item| block} -> ary
2113 * ary.each -> Enumerator
2114 *
2115 * Calls the given block once for each element in +self+, passing that element
2116 * as a parameter. Returns the array itself.
2117 *
2118 * If no block is given, an Enumerator is returned.
2119 *
2120 * a = [ "a", "b", "c" ]
2121 * a.each {|x| print x, " -- " }
2122 *
2123 * produces:
2124 *
2125 * a -- b -- c --
2126 */
2127
2128VALUE
2130{
2131 long i;
2132 ary_verify(ary);
2133 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2134 for (i=0; i<RARRAY_LEN(ary); i++) {
2135 rb_yield(RARRAY_AREF(ary, i));
2136 }
2137 return ary;
2138}
2139
2140/*
2141 * call-seq:
2142 * ary.each_index {|index| block} -> ary
2143 * ary.each_index -> Enumerator
2144 *
2145 * Same as Array#each, but passes the +index+ of the element instead of the
2146 * element itself.
2147 *
2148 * An Enumerator is returned if no block is given.
2149 *
2150 * a = [ "a", "b", "c" ]
2151 * a.each_index {|x| print x, " -- " }
2152 *
2153 * produces:
2154 *
2155 * 0 -- 1 -- 2 --
2156 */
2157
2158static VALUE
2159rb_ary_each_index(VALUE ary)
2160{
2161 long i;
2162 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2163
2164 for (i=0; i<RARRAY_LEN(ary); i++) {
2166 }
2167 return ary;
2168}
2169
2170/*
2171 * call-seq:
2172 * ary.reverse_each {|item| block} -> ary
2173 * ary.reverse_each -> Enumerator
2174 *
2175 * Same as Array#each, but traverses +self+ in reverse order.
2176 *
2177 * a = [ "a", "b", "c" ]
2178 * a.reverse_each {|x| print x, " " }
2179 *
2180 * produces:
2181 *
2182 * c b a
2183 */
2184
2185static VALUE
2186rb_ary_reverse_each(VALUE ary)
2187{
2188 long len;
2189
2190 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
2191 len = RARRAY_LEN(ary);
2192 while (len--) {
2193 long nlen;
2194 rb_yield(RARRAY_AREF(ary, len));
2195 nlen = RARRAY_LEN(ary);
2196 if (nlen < len) {
2197 len = nlen;
2198 }
2199 }
2200 return ary;
2201}
2202
2203/*
2204 * call-seq:
2205 * ary.length -> int
2206 *
2207 * Returns the number of elements in +self+. May be zero.
2208 *
2209 * [ 1, 2, 3, 4, 5 ].length #=> 5
2210 * [].length #=> 0
2211 */
2212
2213static VALUE
2214rb_ary_length(VALUE ary)
2215{
2216 long len = RARRAY_LEN(ary);
2217 return LONG2NUM(len);
2218}
2219
2220/*
2221 * call-seq:
2222 * ary.empty? -> true or false
2223 *
2224 * Returns +true+ if +self+ contains no elements.
2225 *
2226 * [].empty? #=> true
2227 */
2228
2229static VALUE
2230rb_ary_empty_p(VALUE ary)
2231{
2232 if (RARRAY_LEN(ary) == 0)
2233 return Qtrue;
2234 return Qfalse;
2235}
2236
2237VALUE
2239{
2240 long len = RARRAY_LEN(ary);
2242 ary_memcpy(dup, 0, len, RARRAY_CONST_PTR_TRANSIENT(ary));
2244
2245 ary_verify(ary);
2246 ary_verify(dup);
2247 return dup;
2248}
2249
2250VALUE
2252{
2253 return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
2254}
2255
2256extern VALUE rb_output_fs;
2257
2258static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
2259
2260static VALUE
2261recursive_join(VALUE obj, VALUE argp, int recur)
2262{
2263 VALUE *arg = (VALUE *)argp;
2264 VALUE ary = arg[0];
2265 VALUE sep = arg[1];
2266 VALUE result = arg[2];
2267 int *first = (int *)arg[3];
2268
2269 if (recur) {
2270 rb_raise(rb_eArgError, "recursive array join");
2271 }
2272 else {
2273 ary_join_1(obj, ary, sep, 0, result, first);
2274 }
2275 return Qnil;
2276}
2277
2278static void
2279ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
2280{
2281 long i;
2282 VALUE val;
2283
2284 if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
2285 for (i=0; i<max; i++) {
2286 val = RARRAY_AREF(ary, i);
2287 if (i > 0 && !NIL_P(sep))
2288 rb_str_buf_append(result, sep);
2289 rb_str_buf_append(result, val);
2290 }
2291}
2292
2293static void
2294ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
2295{
2296 VALUE val, tmp;
2297
2298 for (; i<RARRAY_LEN(ary); i++) {
2299 if (i > 0 && !NIL_P(sep))
2300 rb_str_buf_append(result, sep);
2301
2302 val = RARRAY_AREF(ary, i);
2303 if (RB_TYPE_P(val, T_STRING)) {
2304 str_join:
2305 rb_str_buf_append(result, val);
2306 if (*first) {
2307 rb_enc_copy(result, val);
2308 *first = FALSE;
2309 }
2310 }
2311 else if (RB_TYPE_P(val, T_ARRAY)) {
2312 obj = val;
2313 ary_join:
2314 if (val == ary) {
2315 rb_raise(rb_eArgError, "recursive array join");
2316 }
2317 else {
2318 VALUE args[4];
2319
2320 *first = FALSE;
2321 args[0] = val;
2322 args[1] = sep;
2323 args[2] = result;
2324 args[3] = (VALUE)first;
2325 rb_exec_recursive(recursive_join, obj, (VALUE)args);
2326 }
2327 }
2328 else {
2329 tmp = rb_check_string_type(val);
2330 if (!NIL_P(tmp)) {
2331 val = tmp;
2332 goto str_join;
2333 }
2334 tmp = rb_check_array_type(val);
2335 if (!NIL_P(tmp)) {
2336 obj = val;
2337 val = tmp;
2338 goto ary_join;
2339 }
2340 val = rb_obj_as_string(val);
2341 goto str_join;
2342 }
2343 }
2344}
2345
2346VALUE
2348{
2349 long len = 1, i;
2350 VALUE val, tmp, result;
2351
2352 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
2353
2354 if (!NIL_P(sep)) {
2355 StringValue(sep);
2356 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
2357 }
2358 for (i=0; i<RARRAY_LEN(ary); i++) {
2359 val = RARRAY_AREF(ary, i);
2360 tmp = rb_check_string_type(val);
2361
2362 if (NIL_P(tmp) || tmp != val) {
2363 int first;
2364 result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10);
2366 ary_join_0(ary, sep, i, result);
2367 first = i == 0;
2368 ary_join_1(ary, ary, sep, i, result, &first);
2369 return result;
2370 }
2371
2372 len += RSTRING_LEN(tmp);
2373 }
2374
2375 result = rb_str_new(0, len);
2376 rb_str_set_len(result, 0);
2377
2378 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
2379
2380 return result;
2381}
2382
2383/*
2384 * call-seq:
2385 * ary.join(separator=$,) -> str
2386 *
2387 * Returns a string created by converting each element of the array to
2388 * a string, separated by the given +separator+.
2389 * If the +separator+ is +nil+, it uses current <code>$,</code>.
2390 * If both the +separator+ and <code>$,</code> are +nil+,
2391 * it uses an empty string.
2392 *
2393 * [ "a", "b", "c" ].join #=> "abc"
2394 * [ "a", "b", "c" ].join("-") #=> "a-b-c"
2395 *
2396 * For nested arrays, join is applied recursively:
2397 *
2398 * [ "a", [1, 2, [:x, :y]], "b" ].join("-") #=> "a-1-2-x-y-b"
2399 */
2400
2401static VALUE
2402rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
2403{
2404 VALUE sep;
2405
2406 if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
2407 sep = rb_output_fs;
2408 if (!NIL_P(sep)) {
2409 rb_warn("$, is set to non-nil value");
2410 }
2411 }
2412
2413 return rb_ary_join(ary, sep);
2414}
2415
2416static VALUE
2417inspect_ary(VALUE ary, VALUE dummy, int recur)
2418{
2419 long i;
2420 VALUE s, str;
2421
2422 if (recur) return rb_usascii_str_new_cstr("[...]");
2423 str = rb_str_buf_new2("[");
2424 for (i=0; i<RARRAY_LEN(ary); i++) {
2425 s = rb_inspect(RARRAY_AREF(ary, i));
2426 if (i > 0) rb_str_buf_cat2(str, ", ");
2427 else rb_enc_copy(str, s);
2429 }
2430 rb_str_buf_cat2(str, "]");
2431 return str;
2432}
2433
2434/*
2435 * call-seq:
2436 * ary.inspect -> string
2437 * ary.to_s -> string
2438 *
2439 * Creates a string representation of +self+, by calling #inspect
2440 * on each element.
2441 *
2442 * [ "a", "b", "c" ].to_s #=> "[\"a\", \"b\", \"c\"]"
2443 */
2444
2445static VALUE
2446rb_ary_inspect(VALUE ary)
2447{
2448 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
2449 return rb_exec_recursive(inspect_ary, ary, 0);
2450}
2451
2452VALUE
2454{
2455 return rb_ary_inspect(ary);
2456}
2457
2458/*
2459 * call-seq:
2460 * ary.to_a -> ary
2461 *
2462 * Returns +self+.
2463 *
2464 * If called on a subclass of Array, converts the receiver to an Array object.
2465 */
2466
2467static VALUE
2468rb_ary_to_a(VALUE ary)
2469{
2470 if (rb_obj_class(ary) != rb_cArray) {
2472 rb_ary_replace(dup, ary);
2473 return dup;
2474 }
2475 return ary;
2476}
2477
2478/*
2479 * call-seq:
2480 * ary.to_h -> hash
2481 * ary.to_h {|item| block } -> hash
2482 *
2483 * Returns the result of interpreting <i>ary</i> as an array of
2484 * <tt>[key, value]</tt> pairs.
2485 *
2486 * [[:foo, :bar], [1, 2]].to_h
2487 * # => {:foo => :bar, 1 => 2}
2488 *
2489 * If a block is given, the results of the block on each element of
2490 * the array will be used as pairs.
2491 *
2492 * ["foo", "bar"].to_h {|s| [s.ord, s]}
2493 * # => {102=>"foo", 98=>"bar"}
2494 */
2495
2496static VALUE
2497rb_ary_to_h(VALUE ary)
2498{
2499 long i;
2501 int block_given = rb_block_given_p();
2502
2503 for (i=0; i<RARRAY_LEN(ary); i++) {
2504 const VALUE e = rb_ary_elt(ary, i);
2505 const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
2506 const VALUE key_value_pair = rb_check_array_type(elt);
2507 if (NIL_P(key_value_pair)) {
2508 rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
2509 rb_obj_class(elt), i);
2510 }
2511 if (RARRAY_LEN(key_value_pair) != 2) {
2512 rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
2513 i, RARRAY_LEN(key_value_pair));
2514 }
2515 rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
2516 }
2517 return hash;
2518}
2519
2520/*
2521 * call-seq:
2522 * ary.to_ary -> ary
2523 *
2524 * Returns +self+.
2525 */
2526
2527static VALUE
2528rb_ary_to_ary_m(VALUE ary)
2529{
2530 return ary;
2531}
2532
2533static void
2534ary_reverse(VALUE *p1, VALUE *p2)
2535{
2536 while (p1 < p2) {
2537 VALUE tmp = *p1;
2538 *p1++ = *p2;
2539 *p2-- = tmp;
2540 }
2541}
2542
2543VALUE
2545{
2546 VALUE *p2;
2547 long len = RARRAY_LEN(ary);
2548
2549 rb_ary_modify(ary);
2550 if (len > 1) {
2551 RARRAY_PTR_USE_TRANSIENT(ary, p1, {
2552 p2 = p1 + len - 1; /* points last item */
2553 ary_reverse(p1, p2);
2554 }); /* WB: no new reference */
2555 }
2556 return ary;
2557}
2558
2559/*
2560 * call-seq:
2561 * ary.reverse! -> ary
2562 *
2563 * Reverses +self+ in place.
2564 *
2565 * a = [ "a", "b", "c" ]
2566 * a.reverse! #=> ["c", "b", "a"]
2567 * a #=> ["c", "b", "a"]
2568 */
2569
2570static VALUE
2571rb_ary_reverse_bang(VALUE ary)
2572{
2573 return rb_ary_reverse(ary);
2574}
2575
2576/*
2577 * call-seq:
2578 * ary.reverse -> new_ary
2579 *
2580 * Returns a new array containing +self+'s elements in reverse order.
2581 *
2582 * [ "a", "b", "c" ].reverse #=> ["c", "b", "a"]
2583 * [ 1 ].reverse #=> [1]
2584 */
2585
2586static VALUE
2587rb_ary_reverse_m(VALUE ary)
2588{
2589 long len = RARRAY_LEN(ary);
2591
2592 if (len > 0) {
2593 const VALUE *p1 = RARRAY_CONST_PTR_TRANSIENT(ary);
2595 do *p2-- = *p1++; while (--len > 0);
2596 }
2597 ARY_SET_LEN(dup, RARRAY_LEN(ary));
2598 return dup;
2599}
2600
2601static inline long
2602rotate_count(long cnt, long len)
2603{
2604 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
2605}
2606
2607static void
2608ary_rotate_ptr(VALUE *ptr, long len, long cnt)
2609{
2610 --len;
2611 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
2612 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
2613 if (len > 0) ary_reverse(ptr, ptr + len);
2614}
2615
2616VALUE
2618{
2619 rb_ary_modify(ary);
2620
2621 if (cnt != 0) {
2622 long len = RARRAY_LEN(ary);
2623 if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
2624 RARRAY_PTR_USE_TRANSIENT(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
2625 return ary;
2626 }
2627 }
2628 return Qnil;
2629}
2630
2631/*
2632 * call-seq:
2633 * ary.rotate!(count=1) -> ary
2634 *
2635 * Rotates +self+ in place so that the element at +count+ comes first, and
2636 * returns +self+.
2637 *
2638 * If +count+ is negative then it rotates in the opposite direction, starting
2639 * from the end of the array where +-1+ is the last element.
2640 *
2641 * a = [ "a", "b", "c", "d" ]
2642 * a.rotate! #=> ["b", "c", "d", "a"]
2643 * a #=> ["b", "c", "d", "a"]
2644 * a.rotate!(2) #=> ["d", "a", "b", "c"]
2645 * a.rotate!(-3) #=> ["a", "b", "c", "d"]
2646 */
2647
2648static VALUE
2649rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
2650{
2651 long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
2652 rb_ary_rotate(ary, n);
2653 return ary;
2654}
2655
2656/*
2657 * call-seq:
2658 * ary.rotate(count=1) -> new_ary
2659 *
2660 * Returns a new array by rotating +self+ so that the element at +count+ is
2661 * the first element of the new array.
2662 *
2663 * If +count+ is negative then it rotates in the opposite direction, starting
2664 * from the end of +self+ where +-1+ is the last element.
2665 *
2666 * a = [ "a", "b", "c", "d" ]
2667 * a.rotate #=> ["b", "c", "d", "a"]
2668 * a #=> ["a", "b", "c", "d"]
2669 * a.rotate(2) #=> ["c", "d", "a", "b"]
2670 * a.rotate(-3) #=> ["b", "c", "d", "a"]
2671 */
2672
2673static VALUE
2674rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
2675{
2676 VALUE rotated;
2677 const VALUE *ptr;
2678 long len;
2679 long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
2680
2681 len = RARRAY_LEN(ary);
2682 rotated = rb_ary_new2(len);
2683 if (len > 0) {
2684 cnt = rotate_count(cnt, len);
2686 len -= cnt;
2687 ary_memcpy(rotated, 0, len, ptr + cnt);
2688 ary_memcpy(rotated, len, cnt, ptr);
2689 }
2690 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
2691 return rotated;
2692}
2693
2697};
2698
2699static VALUE
2700sort_reentered(VALUE ary)
2701{
2702 if (RBASIC(ary)->klass) {
2703 rb_raise(rb_eRuntimeError, "sort reentered");
2704 }
2705 return Qnil;
2706}
2707
2708static int
2709sort_1(const void *ap, const void *bp, void *dummy)
2710{
2711 struct ary_sort_data *data = dummy;
2712 VALUE retval = sort_reentered(data->ary);
2713 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
2714 VALUE args[2];
2715 int n;
2716
2717 args[0] = a;
2718 args[1] = b;
2719 retval = rb_yield_values2(2, args);
2720 n = rb_cmpint(retval, a, b);
2721 sort_reentered(data->ary);
2722 return n;
2723}
2724
2725static int
2726sort_2(const void *ap, const void *bp, void *dummy)
2727{
2728 struct ary_sort_data *data = dummy;
2729 VALUE retval = sort_reentered(data->ary);
2730 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
2731 int n;
2732
2733 if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, Fixnum)) {
2734 if ((long)a > (long)b) return 1;
2735 if ((long)a < (long)b) return -1;
2736 return 0;
2737 }
2738 if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, String)) {
2739 return rb_str_cmp(a, b);
2740 }
2741 if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(data->cmp_opt, Float)) {
2742 return rb_float_cmp(a, b);
2743 }
2744
2745 retval = rb_funcallv(a, id_cmp, 1, &b);
2746 n = rb_cmpint(retval, a, b);
2747 sort_reentered(data->ary);
2748
2749 return n;
2750}
2751
2752/*
2753 * call-seq:
2754 * ary.sort! -> ary
2755 * ary.sort! {|a, b| block} -> ary
2756 *
2757 * Sorts +self+ in place.
2758 *
2759 * Comparisons for the sort will be done using the <code><=></code> operator
2760 * or using an optional code block.
2761 *
2762 * The block must implement a comparison between +a+ and +b+ and return
2763 * an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+
2764 * are equivalent, or an integer greater than 0 when +a+ follows +b+.
2765 *
2766 * The result is not guaranteed to be stable. When the comparison of two
2767 * elements returns +0+, the order of the elements is unpredictable.
2768 *
2769 * ary = [ "d", "a", "e", "c", "b" ]
2770 * ary.sort! #=> ["a", "b", "c", "d", "e"]
2771 * ary.sort! {|a, b| b <=> a} #=> ["e", "d", "c", "b", "a"]
2772 *
2773 * See also Enumerable#sort_by.
2774 */
2775
2776VALUE
2778{
2781 if (RARRAY_LEN(ary) > 1) {
2782 VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
2783 struct ary_sort_data data;
2784 long len = RARRAY_LEN(ary);
2785 RBASIC_CLEAR_CLASS(tmp);
2786 data.ary = tmp;
2787 data.cmp_opt.opt_methods = 0;
2788 data.cmp_opt.opt_inited = 0;
2789 RARRAY_PTR_USE(tmp, ptr, {
2790 ruby_qsort(ptr, len, sizeof(VALUE),
2791 rb_block_given_p()?sort_1:sort_2, &data);
2792 }); /* WB: no new reference */
2794 if (ARY_EMBED_P(tmp)) {
2795 if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
2796 rb_ary_unshare(ary);
2798 }
2799 ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
2801 }
2802 else {
2803 if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
2806 }
2807 else {
2808 assert(!ARY_SHARED_P(tmp));
2809 if (ARY_EMBED_P(ary)) {
2811 }
2812 else if (ARY_SHARED_P(ary)) {
2813 /* ary might be destructively operated in the given block */
2814 rb_ary_unshare(ary);
2815 }
2816 else {
2817 ary_heap_free(ary);
2818 }
2822 }
2823 /* tmp was lost ownership for the ptr */
2824 FL_UNSET(tmp, FL_FREEZE);
2825 FL_SET_EMBED(tmp);
2826 ARY_SET_EMBED_LEN(tmp, 0);
2827 FL_SET(tmp, FL_FREEZE);
2828 }
2829 /* tmp will be GC'ed. */
2830 RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
2831 }
2832 ary_verify(ary);
2833 return ary;
2834}
2835
2836/*
2837 * call-seq:
2838 * ary.sort -> new_ary
2839 * ary.sort {|a, b| block} -> new_ary
2840 *
2841 * Returns a new array created by sorting +self+.
2842 *
2843 * Comparisons for the sort will be done using the <code><=></code> operator
2844 * or using an optional code block.
2845 *
2846 * The block must implement a comparison between +a+ and +b+ and return
2847 * an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+
2848 * are equivalent, or an integer greater than 0 when +a+ follows +b+.
2849 *
2850 * The result is not guaranteed to be stable. When the comparison of two
2851 * elements returns +0+, the order of the elements is unpredictable.
2852 *
2853 * ary = [ "d", "a", "e", "c", "b" ]
2854 * ary.sort #=> ["a", "b", "c", "d", "e"]
2855 * ary.sort {|a, b| b <=> a} #=> ["e", "d", "c", "b", "a"]
2856 *
2857 * To produce the reverse order, the following can also be used
2858 * (and may be faster):
2859 *
2860 * ary.sort.reverse! #=> ["e", "d", "c", "b", "a"]
2861 *
2862 * See also Enumerable#sort_by.
2863 */
2864
2865VALUE
2867{
2868 ary = rb_ary_dup(ary);
2870 return ary;
2871}
2872
2873static VALUE rb_ary_bsearch_index(VALUE ary);
2874
2875/*
2876 * call-seq:
2877 * ary.bsearch {|x| block } -> elem
2878 *
2879 * By using binary search, finds a value from this array which meets
2880 * the given condition in O(log n) where n is the size of the array.
2881 *
2882 * You can use this method in two modes: a find-minimum mode and
2883 * a find-any mode. In either case, the elements of the array must be
2884 * monotone (or sorted) with respect to the block.
2885 *
2886 * In find-minimum mode (this is a good choice for typical use cases),
2887 * the block must always return true or false, and there must be an index i
2888 * (0 <= i <= ary.size) so that:
2889 *
2890 * - the block returns false for any element whose index is less than
2891 * i, and
2892 * - the block returns true for any element whose index is greater
2893 * than or equal to i.
2894 *
2895 * This method returns the i-th element. If i is equal to ary.size,
2896 * it returns nil.
2897 *
2898 * ary = [0, 4, 7, 10, 12]
2899 * ary.bsearch {|x| x >= 4 } #=> 4
2900 * ary.bsearch {|x| x >= 6 } #=> 7
2901 * ary.bsearch {|x| x >= -1 } #=> 0
2902 * ary.bsearch {|x| x >= 100 } #=> nil
2903 *
2904 * In find-any mode (this behaves like libc's bsearch(3)), the block
2905 * must always return a number, and there must be two indices i and j
2906 * (0 <= i <= j <= ary.size) so that:
2907 *
2908 * - the block returns a positive number for ary[k] if 0 <= k < i,
2909 * - the block returns zero for ary[k] if i <= k < j, and
2910 * - the block returns a negative number for ary[k] if
2911 * j <= k < ary.size.
2912 *
2913 * Under this condition, this method returns any element whose index
2914 * is within i...j. If i is equal to j (i.e., there is no element
2915 * that satisfies the block), this method returns nil.
2916 *
2917 * ary = [0, 4, 7, 10, 12]
2918 * # try to find v such that 4 <= v < 8
2919 * ary.bsearch {|x| 1 - x / 4 } #=> 4 or 7
2920 * # try to find v such that 8 <= v < 10
2921 * ary.bsearch {|x| 4 - x / 2 } #=> nil
2922 *
2923 * You must not mix the two modes at a time; the block must always
2924 * return either true/false, or always return a number. It is
2925 * undefined which value is actually picked up at each iteration.
2926 */
2927
2928static VALUE
2929rb_ary_bsearch(VALUE ary)
2930{
2931 VALUE index_result = rb_ary_bsearch_index(ary);
2932
2933 if (FIXNUM_P(index_result)) {
2934 return rb_ary_entry(ary, FIX2LONG(index_result));
2935 }
2936 return index_result;
2937}
2938
2939/*
2940 * call-seq:
2941 * ary.bsearch_index {|x| block } -> int or nil
2942 *
2943 * By using binary search, finds an index of a value from this array which
2944 * meets the given condition in O(log n) where n is the size of the array.
2945 *
2946 * It supports two modes, depending on the nature of the block. They are
2947 * exactly the same as in the case of the #bsearch method, with the only difference
2948 * being that this method returns the index of the element instead of the
2949 * element itself. For more details consult the documentation for #bsearch.
2950 */
2951
2952static VALUE
2953rb_ary_bsearch_index(VALUE ary)
2954{
2955 long low = 0, high = RARRAY_LEN(ary), mid;
2956 int smaller = 0, satisfied = 0;
2957 VALUE v, val;
2958
2959 RETURN_ENUMERATOR(ary, 0, 0);
2960 while (low < high) {
2961 mid = low + ((high - low) / 2);
2962 val = rb_ary_entry(ary, mid);
2963 v = rb_yield(val);
2964 if (FIXNUM_P(v)) {
2965 if (v == INT2FIX(0)) return INT2FIX(mid);
2966 smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
2967 }
2968 else if (v == Qtrue) {
2969 satisfied = 1;
2970 smaller = 1;
2971 }
2972 else if (v == Qfalse || v == Qnil) {
2973 smaller = 0;
2974 }
2975 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
2976 const VALUE zero = INT2FIX(0);
2977 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
2978 case 0: return INT2FIX(mid);
2979 case 1: smaller = 1; break;
2980 case -1: smaller = 0;
2981 }
2982 }
2983 else {
2984 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
2985 " (must be numeric, true, false or nil)",
2986 rb_obj_class(v));
2987 }
2988 if (smaller) {
2989 high = mid;
2990 }
2991 else {
2992 low = mid + 1;
2993 }
2994 }
2995 if (!satisfied) return Qnil;
2996 return INT2FIX(low);
2997}
2998
2999
3000static VALUE
3001sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
3002{
3003 return rb_yield(i);
3004}
3005
3006/*
3007 * call-seq:
3008 * ary.sort_by! {|obj| block} -> ary
3009 * ary.sort_by! -> Enumerator
3010 *
3011 * Sorts +self+ in place using a set of keys generated by mapping the
3012 * values in +self+ through the given block.
3013 *
3014 * The result is not guaranteed to be stable. When two keys are equal,
3015 * the order of the corresponding elements is unpredictable.
3016 *
3017 * If no block is given, an Enumerator is returned instead.
3018 *
3019 * See also Enumerable#sort_by.
3020 */
3021
3022static VALUE
3023rb_ary_sort_by_bang(VALUE ary)
3024{
3025 VALUE sorted;
3026
3027 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3029 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
3030 rb_ary_replace(ary, sorted);
3031 return ary;
3032}
3033
3034
3035/*
3036 * call-seq:
3037 * ary.collect {|item| block} -> new_ary
3038 * ary.map {|item| block} -> new_ary
3039 * ary.collect -> Enumerator
3040 * ary.map -> Enumerator
3041 *
3042 * Invokes the given block once for each element of +self+.
3043 *
3044 * Creates a new array containing the values returned by the block.
3045 *
3046 * See also Enumerable#collect.
3047 *
3048 * If no block is given, an Enumerator is returned instead.
3049 *
3050 * a = [ "a", "b", "c", "d" ]
3051 * a.collect {|x| x + "!"} #=> ["a!", "b!", "c!", "d!"]
3052 * a.map.with_index {|x, i| x * i} #=> ["", "b", "cc", "ddd"]
3053 * a #=> ["a", "b", "c", "d"]
3054 */
3055
3056static VALUE
3057rb_ary_collect(VALUE ary)
3058{
3059 long i;
3060 VALUE collect;
3061
3062 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3063 collect = rb_ary_new2(RARRAY_LEN(ary));
3064 for (i = 0; i < RARRAY_LEN(ary); i++) {
3065 rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
3066 }
3067 return collect;
3068}
3069
3070
3071/*
3072 * call-seq:
3073 * ary.collect! {|item| block } -> ary
3074 * ary.map! {|item| block } -> ary
3075 * ary.collect! -> Enumerator
3076 * ary.map! -> Enumerator
3077 *
3078 * Invokes the given block once for each element of +self+, replacing the
3079 * element with the value returned by the block.
3080 *
3081 * See also Enumerable#collect.
3082 *
3083 * If no block is given, an Enumerator is returned instead.
3084 *
3085 * a = [ "a", "b", "c", "d" ]
3086 * a.map! {|x| x + "!" }
3087 * a #=> [ "a!", "b!", "c!", "d!" ]
3088 * a.collect!.with_index {|x, i| x[0...i] }
3089 * a #=> ["", "b", "c!", "d!"]
3090 */
3091
3092static VALUE
3093rb_ary_collect_bang(VALUE ary)
3094{
3095 long i;
3096
3097 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3099 for (i = 0; i < RARRAY_LEN(ary); i++) {
3101 }
3102 return ary;
3103}
3104
3105VALUE
3106rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
3107{
3108 VALUE result = rb_ary_new2(argc);
3109 long beg, len, i, j;
3110
3111 for (i=0; i<argc; i++) {
3112 if (FIXNUM_P(argv[i])) {
3113 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
3114 continue;
3115 }
3116 /* check if idx is Range */
3117 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
3118 long end = olen < beg+len ? olen : beg+len;
3119 for (j = beg; j < end; j++) {
3120 rb_ary_push(result, (*func)(obj, j));
3121 }
3122 if (beg + len > j)
3123 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
3124 continue;
3125 }
3126 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
3127 }
3128 return result;
3129}
3130
3131static VALUE
3132append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
3133{
3134 long beg, len;
3135 if (FIXNUM_P(idx)) {
3136 beg = FIX2LONG(idx);
3137 }
3138 /* check if idx is Range */
3139 else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
3140 if (len > 0) {
3141 const VALUE *const src = RARRAY_CONST_PTR_TRANSIENT(ary);
3142 const long end = beg + len;
3143 const long prevlen = RARRAY_LEN(result);
3144 if (beg < olen) {
3145 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
3146 }
3147 if (end > olen) {
3148 rb_ary_store(result, prevlen + len - 1, Qnil);
3149 }
3150 }
3151 return result;
3152 }
3153 else {
3154 beg = NUM2LONG(idx);
3155 }
3156 return rb_ary_push(result, rb_ary_entry(ary, beg));
3157}
3158
3159/*
3160 * call-seq:
3161 * ary.values_at(selector, ...) -> new_ary
3162 *
3163 * Returns an array containing the elements in +self+ corresponding to the
3164 * given +selector+(s).
3165 *
3166 * The selectors may be either integer indices or ranges.
3167 *
3168 * See also Array#select.
3169 *
3170 * a = %w{ a b c d e f }
3171 * a.values_at(1, 3, 5) # => ["b", "d", "f"]
3172 * a.values_at(1, 3, 5, 7) # => ["b", "d", "f", nil]
3173 * a.values_at(-1, -2, -2, -7) # => ["f", "e", "e", nil]
3174 * a.values_at(4..6, 3...6) # => ["e", "f", nil, "d", "e", "f"]
3175 */
3176
3177static VALUE
3178rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
3179{
3180 long i, olen = RARRAY_LEN(ary);
3181 VALUE result = rb_ary_new_capa(argc);
3182 for (i = 0; i < argc; ++i) {
3183 append_values_at_single(result, ary, olen, argv[i]);
3184 }
3186 return result;
3187}
3188
3189
3190/*
3191 * call-seq:
3192 * ary.select {|item| block} -> new_ary
3193 * ary.select -> Enumerator
3194 * ary.filter {|item| block} -> new_ary
3195 * ary.filter -> Enumerator
3196 *
3197 * Returns a new array containing all elements of +ary+
3198 * for which the given +block+ returns a true value.
3199 *
3200 * If no block is given, an Enumerator is returned instead.
3201 *
3202 * [1,2,3,4,5].select {|num| num.even? } #=> [2, 4]
3203 *
3204 * a = %w[ a b c d e f ]
3205 * a.select {|v| v =~ /[aeiou]/ } #=> ["a", "e"]
3206 *
3207 * See also Enumerable#select.
3208 *
3209 * Array#filter is an alias for Array#select.
3210 */
3211
3212static VALUE
3213rb_ary_select(VALUE ary)
3214{
3215 VALUE result;
3216 long i;
3217
3218 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3219 result = rb_ary_new2(RARRAY_LEN(ary));
3220 for (i = 0; i < RARRAY_LEN(ary); i++) {
3221 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
3222 rb_ary_push(result, rb_ary_elt(ary, i));
3223 }
3224 }
3225 return result;
3226}
3227
3230 long len[2];
3231};
3232
3233static VALUE
3234select_bang_i(VALUE a)
3235{
3236 volatile struct select_bang_arg *arg = (void *)a;
3237 VALUE ary = arg->ary;
3238 long i1, i2;
3239
3240 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
3241 VALUE v = RARRAY_AREF(ary, i1);
3242 if (!RTEST(rb_yield(v))) continue;
3243 if (i1 != i2) {
3244 rb_ary_store(ary, i2, v);
3245 }
3246 arg->len[1] = ++i2;
3247 }
3248 return (i1 == i2) ? Qnil : ary;
3249}
3250
3251static VALUE
3252select_bang_ensure(VALUE a)
3253{
3254 volatile struct select_bang_arg *arg = (void *)a;
3255 VALUE ary = arg->ary;
3256 long len = RARRAY_LEN(ary);
3257 long i1 = arg->len[0], i2 = arg->len[1];
3258
3259 if (i2 < len && i2 < i1) {
3260 long tail = 0;
3261 if (i1 < len) {
3262 tail = len - i1;
3264 MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
3265 });
3266 }
3267 ARY_SET_LEN(ary, i2 + tail);
3268 }
3269 return ary;
3270}
3271
3272/*
3273 * call-seq:
3274 * ary.select! {|item| block } -> ary or nil
3275 * ary.select! -> Enumerator
3276 * ary.filter! {|item| block } -> ary or nil
3277 * ary.filter! -> Enumerator
3278 *
3279 * Invokes the given block passing in successive elements from +self+,
3280 * deleting elements for which the block returns a +false+ value.
3281 *
3282 * The array may not be changed instantly every time the block is called.
3283 *
3284 * If changes were made, it will return +self+, otherwise it returns +nil+.
3285 *
3286 * If no block is given, an Enumerator is returned instead.
3287 *
3288 * See also Array#keep_if.
3289 *
3290 * Array#filter! is an alias for Array#select!.
3291 */
3292
3293static VALUE
3294rb_ary_select_bang(VALUE ary)
3295{
3296 struct select_bang_arg args;
3297
3298 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3300
3301 args.ary = ary;
3302 args.len[0] = args.len[1] = 0;
3303 return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
3304}
3305
3306/*
3307 * call-seq:
3308 * ary.keep_if {|item| block} -> ary
3309 * ary.keep_if -> Enumerator
3310 *
3311 * Deletes every element of +self+ for which the given block evaluates to
3312 * +false+, and returns +self+.
3313 *
3314 * If no block is given, an Enumerator is returned instead.
3315 *
3316 * a = %w[ a b c d e f ]
3317 * a.keep_if {|v| v =~ /[aeiou]/ } #=> ["a", "e"]
3318 * a #=> ["a", "e"]
3319 *
3320 * See also Array#select!.
3321 */
3322
3323static VALUE
3324rb_ary_keep_if(VALUE ary)
3325{
3326 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3327 rb_ary_select_bang(ary);
3328 return ary;
3329}
3330
3331static void
3332ary_resize_smaller(VALUE ary, long len)
3333{
3335 if (RARRAY_LEN(ary) > len) {
3337 if (len * 2 < ARY_CAPA(ary) &&
3339 ary_resize_capa(ary, len * 2);
3340 }
3341 }
3342}
3343
3344/*
3345 * call-seq:
3346 * ary.delete(obj) -> item or nil
3347 * ary.delete(obj) {block} -> item or result of block
3348 *
3349 * Deletes all items from +self+ that are equal to +obj+.
3350 *
3351 * Returns the last deleted item, or +nil+ if no matching item is found.
3352 *
3353 * If the optional code block is given, the result of the block is returned if
3354 * the item is not found. (To remove +nil+ elements and get an informative
3355 * return value, use Array#compact!)
3356 *
3357 * a = [ "a", "b", "b", "b", "c" ]
3358 * a.delete("b") #=> "b"
3359 * a #=> ["a", "c"]
3360 * a.delete("z") #=> nil
3361 * a.delete("z") {"not found"} #=> "not found"
3362 */
3363
3364VALUE
3366{
3367 VALUE v = item;
3368 long i1, i2;
3369
3370 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
3371 VALUE e = RARRAY_AREF(ary, i1);
3372
3373 if (rb_equal(e, item)) {
3374 v = e;
3375 continue;
3376 }
3377 if (i1 != i2) {
3378 rb_ary_store(ary, i2, e);
3379 }
3380 i2++;
3381 }
3382 if (RARRAY_LEN(ary) == i2) {
3383 if (rb_block_given_p()) {
3384 return rb_yield(item);
3385 }
3386 return Qnil;
3387 }
3388
3389 ary_resize_smaller(ary, i2);
3390
3391 ary_verify(ary);
3392 return v;
3393}
3394
3395void
3397{
3398 long i1, i2;
3399
3400 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
3401 VALUE e = RARRAY_AREF(ary, i1);
3402
3403 if (e == item) {
3404 continue;
3405 }
3406 if (i1 != i2) {
3407 rb_ary_store(ary, i2, e);
3408 }
3409 i2++;
3410 }
3411 if (RARRAY_LEN(ary) == i2) {
3412 return;
3413 }
3414
3415 ary_resize_smaller(ary, i2);
3416}
3417
3418VALUE
3420{
3421 long len = RARRAY_LEN(ary);
3422 VALUE del;
3423
3424 if (pos >= len) return Qnil;
3425 if (pos < 0) {
3426 pos += len;
3427 if (pos < 0) return Qnil;
3428 }
3429
3431 del = RARRAY_AREF(ary, pos);
3433 MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
3434 });
3435 ARY_INCREASE_LEN(ary, -1);
3436 ary_verify(ary);
3437 return del;
3438}
3439
3440/*
3441 * call-seq:
3442 * ary.delete_at(index) -> obj or nil
3443 *
3444 * Deletes the element at the specified +index+, returning that element, or
3445 * +nil+ if the +index+ is out of range.
3446 *
3447 * See also Array#slice!
3448 *
3449 * a = ["ant", "bat", "cat", "dog"]
3450 * a.delete_at(2) #=> "cat"
3451 * a #=> ["ant", "bat", "dog"]
3452 * a.delete_at(99) #=> nil
3453 */
3454
3455static VALUE
3456rb_ary_delete_at_m(VALUE ary, VALUE pos)
3457{
3458 return rb_ary_delete_at(ary, NUM2LONG(pos));
3459}
3460
3461/*
3462 * call-seq:
3463 * ary.slice!(index) -> obj or nil
3464 * ary.slice!(start, length) -> new_ary or nil
3465 * ary.slice!(range) -> new_ary or nil
3466 *
3467 * Deletes the element(s) given by an +index+ (optionally up to +length+
3468 * elements) or by a +range+.
3469 *
3470 * Returns the deleted object (or objects), or +nil+ if the +index+ is out of
3471 * range.
3472 *
3473 * a = [ "a", "b", "c" ]
3474 * a.slice!(1) #=> "b"
3475 * a #=> ["a", "c"]
3476 * a.slice!(-1) #=> "c"
3477 * a #=> ["a"]
3478 * a.slice!(100) #=> nil
3479 * a #=> ["a"]
3480 */
3481
3482static VALUE
3483rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
3484{
3485 VALUE arg1, arg2;
3486 long pos, len, orig_len;
3487
3488 rb_ary_modify_check(ary);
3489 if (argc == 2) {
3490 pos = NUM2LONG(argv[0]);
3491 len = NUM2LONG(argv[1]);
3492 delete_pos_len:
3493 if (len < 0) return Qnil;
3494 orig_len = RARRAY_LEN(ary);
3495 if (pos < 0) {
3496 pos += orig_len;
3497 if (pos < 0) return Qnil;
3498 }
3499 else if (orig_len < pos) return Qnil;
3500 if (orig_len < pos + len) {
3501 len = orig_len - pos;
3502 }
3503 if (len == 0) return rb_ary_new2(0);
3506 rb_ary_splice(ary, pos, len, 0, 0);
3507 return arg2;
3508 }
3509
3510 rb_check_arity(argc, 1, 2);
3511 arg1 = argv[0];
3512
3513 if (!FIXNUM_P(arg1)) {
3514 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
3515 case Qtrue:
3516 /* valid range */
3517 goto delete_pos_len;
3518 case Qnil:
3519 /* invalid range */
3520 return Qnil;
3521 default:
3522 /* not a range */
3523 break;
3524 }
3525 }
3526
3527 return rb_ary_delete_at(ary, NUM2LONG(arg1));
3528}
3529
3530static VALUE
3531ary_reject(VALUE orig, VALUE result)
3532{
3533 long i;
3534
3535 for (i = 0; i < RARRAY_LEN(orig); i++) {
3536 VALUE v = RARRAY_AREF(orig, i);
3537
3538 if (!RTEST(rb_yield(v))) {
3539 rb_ary_push(result, v);
3540 }
3541 }
3542 return result;
3543}
3544
3545static VALUE
3546reject_bang_i(VALUE a)
3547{
3548 volatile struct select_bang_arg *arg = (void *)a;
3549 VALUE ary = arg->ary;
3550 long i1, i2;
3551
3552 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
3553 VALUE v = RARRAY_AREF(ary, i1);
3554 if (RTEST(rb_yield(v))) continue;
3555 if (i1 != i2) {
3556 rb_ary_store(ary, i2, v);
3557 }
3558 arg->len[1] = ++i2;
3559 }
3560 return (i1 == i2) ? Qnil : ary;
3561}
3562
3563static VALUE
3564ary_reject_bang(VALUE ary)
3565{
3566 struct select_bang_arg args;
3567 rb_ary_modify_check(ary);
3568 args.ary = ary;
3569 args.len[0] = args.len[1] = 0;
3570 return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
3571}
3572
3573/*
3574 * call-seq:
3575 * ary.reject! {|item| block} -> ary or nil
3576 * ary.reject! -> Enumerator
3577 *
3578 * Deletes every element of +self+ for which the block evaluates to +true+,
3579 * if no changes were made returns +nil+.
3580 *
3581 * The array may not be changed instantly every time the block is called.
3582 *
3583 * See also Enumerable#reject and Array#delete_if.
3584 *
3585 * If no block is given, an Enumerator is returned instead.
3586 */
3587
3588static VALUE
3589rb_ary_reject_bang(VALUE ary)
3590{
3591 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3593 return ary_reject_bang(ary);
3594}
3595
3596/*
3597 * call-seq:
3598 * ary.reject {|item| block } -> new_ary
3599 * ary.reject -> Enumerator
3600 *
3601 * Returns a new array containing the items in +self+ for which the given
3602 * block is not +true+. The ordering of non-rejected elements is maintained.
3603 *
3604 * See also Array#delete_if
3605 *
3606 * If no block is given, an Enumerator is returned instead.
3607 */
3608
3609static VALUE
3610rb_ary_reject(VALUE ary)
3611{
3612 VALUE rejected_ary;
3613
3614 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3615 rejected_ary = rb_ary_new();
3616 ary_reject(ary, rejected_ary);
3617 return rejected_ary;
3618}
3619
3620/*
3621 * call-seq:
3622 * ary.delete_if {|item| block} -> ary
3623 * ary.delete_if -> Enumerator
3624 *
3625 * Deletes every element of +self+ for which block evaluates to +true+.
3626 *
3627 * The array is changed instantly every time the block is called, not after
3628 * the iteration is over.
3629 *
3630 * See also Array#reject!
3631 *
3632 * If no block is given, an Enumerator is returned instead.
3633 *
3634 * scores = [ 97, 42, 75 ]
3635 * scores.delete_if {|score| score < 80 } #=> [97]
3636 */
3637
3638static VALUE
3639rb_ary_delete_if(VALUE ary)
3640{
3641 ary_verify(ary);
3642 RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3643 ary_reject_bang(ary);
3644 return ary;
3645}
3646
3647static VALUE
3648take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
3649{
3650 VALUE *args = (VALUE *)cbarg;
3651 if (args[1] == 0) rb_iter_break();
3652 else args[1]--;
3653 if (argc > 1) val = rb_ary_new4(argc, argv);
3654 rb_ary_push(args[0], val);
3655 return Qnil;
3656}
3657
3658static VALUE
3659take_items(VALUE obj, long n)
3660{
3661 VALUE result = rb_check_array_type(obj);
3662 VALUE args[2];
3663
3664 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
3665 result = rb_ary_new2(n);
3666 args[0] = result; args[1] = (VALUE)n;
3667 if (rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args) == Qundef)
3668 rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
3669 rb_obj_class(obj));
3670 return result;
3671}
3672
3673
3674/*
3675 * call-seq:
3676 * ary.zip(arg, ...) -> new_ary
3677 * ary.zip(arg, ...) {|arr| block} -> nil
3678 *
3679 * Converts any arguments to arrays, then merges elements of +self+ with
3680 * corresponding elements from each argument.
3681 *
3682 * This generates a sequence of <code>ary.size</code> _n_-element arrays,
3683 * where _n_ is one more than the count of arguments.
3684 *
3685 * If the size of any argument is less than the size of the initial array,
3686 * +nil+ values are supplied.
3687 *
3688 * If a block is given, it is invoked for each output +array+, otherwise an
3689 * array of arrays is returned.
3690 *
3691 * a = [ 4, 5, 6 ]
3692 * b = [ 7, 8, 9 ]
3693 * [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
3694 * [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
3695 * a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
3696 */
3697
3698static VALUE
3699rb_ary_zip(int argc, VALUE *argv, VALUE ary)
3700{
3701 int i, j;
3702 long len = RARRAY_LEN(ary);
3703 VALUE result = Qnil;
3704
3705 for (i=0; i<argc; i++) {
3706 argv[i] = take_items(argv[i], len);
3707 }
3708
3709 if (rb_block_given_p()) {
3710 int arity = rb_block_arity();
3711
3712 if (arity > 1) {
3713 VALUE work, *tmp;
3714
3715 tmp = ALLOCV_N(VALUE, work, argc+1);
3716
3717 for (i=0; i<RARRAY_LEN(ary); i++) {
3718 tmp[0] = RARRAY_AREF(ary, i);
3719 for (j=0; j<argc; j++) {
3720 tmp[j+1] = rb_ary_elt(argv[j], i);
3721 }
3722 rb_yield_values2(argc+1, tmp);
3723 }
3724
3725 if (work) ALLOCV_END(work);
3726 }
3727 else {
3728 for (i=0; i<RARRAY_LEN(ary); i++) {
3729 VALUE tmp = rb_ary_new2(argc+1);
3730
3731 rb_ary_push(tmp, RARRAY_AREF(ary, i));
3732 for (j=0; j<argc; j++) {
3733 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
3734 }
3735 rb_yield(tmp);
3736 }
3737 }
3738 }
3739 else {
3740 result = rb_ary_new_capa(len);
3741
3742 for (i=0; i<len; i++) {
3743 VALUE tmp = rb_ary_new_capa(argc+1);
3744
3745 rb_ary_push(tmp, RARRAY_AREF(ary, i));
3746 for (j=0; j<argc; j++) {
3747 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
3748 }
3749 rb_ary_push(result, tmp);
3750 }
3751 }
3752
3753 return result;
3754}
3755
3756/*
3757 * call-seq:
3758 * ary.transpose -> new_ary
3759 *
3760 * Assumes that +self+ is an array of arrays and transposes the rows and
3761 * columns.
3762 *
3763 * a = [[1,2], [3,4], [5,6]]
3764 * a.transpose #=> [[1, 3, 5], [2, 4, 6]]
3765 *
3766 * If the length of the subarrays don't match, an IndexError is raised.
3767 */
3768
3769static VALUE
3770rb_ary_transpose(VALUE ary)
3771{
3772 long elen = -1, alen, i, j;
3773 VALUE tmp, result = 0;
3774
3775 alen = RARRAY_LEN(ary);
3776 if (alen == 0) return rb_ary_dup(ary);
3777 for (i=0; i<alen; i++) {
3778 tmp = to_ary(rb_ary_elt(ary, i));
3779 if (elen < 0) { /* first element */
3780 elen = RARRAY_LEN(tmp);
3781 result = rb_ary_new2(elen);
3782 for (j=0; j<elen; j++) {
3783 rb_ary_store(result, j, rb_ary_new2(alen));
3784 }
3785 }
3786 else if (elen != RARRAY_LEN(tmp)) {
3787 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
3788 RARRAY_LEN(tmp), elen);
3789 }
3790 for (j=0; j<elen; j++) {
3791 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
3792 }
3793 }
3794 return result;
3795}
3796
3797/*
3798 * call-seq:
3799 * ary.replace(other_ary) -> ary
3800 * ary.initialize_copy(other_ary) -> ary
3801 *
3802 * Replaces the contents of +self+ with the contents of +other_ary+,
3803 * truncating or expanding if necessary.
3804 *
3805 * a = [ "a", "b", "c", "d", "e" ]
3806 * a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"]
3807 * a #=> ["x", "y", "z"]
3808 */
3809
3810VALUE
3812{
3813 rb_ary_modify_check(copy);
3814 orig = to_ary(orig);
3815 if (copy == orig) return copy;
3816
3817 if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
3818 VALUE shared_root = 0;
3819
3820 if (ARY_OWNS_HEAP_P(copy)) {
3821 ary_heap_free(copy);
3822 }
3823 else if (ARY_SHARED_P(copy)) {
3824 shared_root = ARY_SHARED_ROOT(copy);
3825 FL_UNSET_SHARED(copy);
3826 }
3827 FL_SET_EMBED(copy);
3828 ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR_TRANSIENT(orig));
3829 if (shared_root) {
3830 rb_ary_decrement_share(shared_root);
3831 }
3832 ARY_SET_LEN(copy, RARRAY_LEN(orig));
3833 }
3834 else {
3835 VALUE shared_root = ary_make_shared(orig);
3836 if (ARY_OWNS_HEAP_P(copy)) {
3837 ary_heap_free(copy);
3838 }
3839 else {
3840 rb_ary_unshare_safe(copy);
3841 }
3842 FL_UNSET_EMBED(copy);
3843 ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
3844 ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
3845 rb_ary_set_shared(copy, shared_root);
3846 }
3847 ary_verify(copy);
3848 return copy;
3849}
3850
3851/*
3852 * call-seq:
3853 * ary.clear -> ary
3854 *
3855 * Removes all elements from +self+.
3856 *
3857 * a = [ "a", "b", "c", "d", "e" ]
3858 * a.clear #=> [ ]
3859 */
3860
3861VALUE
3863{
3864 rb_ary_modify_check(ary);
3865 if (ARY_SHARED_P(ary)) {
3866 if (!ARY_EMBED_P(ary)) {
3867 rb_ary_unshare(ary);
3870 }
3871 }
3872 else {
3873 ARY_SET_LEN(ary, 0);
3874 if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
3875 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
3876 }
3877 }
3878 ary_verify(ary);
3879 return ary;
3880}
3881
3882/*
3883 * call-seq:
3884 * ary.fill(obj) -> ary
3885 * ary.fill(obj, start [, length]) -> ary
3886 * ary.fill(obj, range) -> ary
3887 * ary.fill {|index| block} -> ary
3888 * ary.fill(start [, length]) {|index| block} -> ary
3889 * ary.fill(range) {|index| block} -> ary
3890 *
3891 * The first three forms set the selected elements of +self+ (which
3892 * may be the entire array) to +obj+.
3893 *
3894 * A +start+ of +nil+ is equivalent to zero.
3895 *
3896 * A +length+ of +nil+ is equivalent to the length of the array.
3897 *
3898 * The last three forms fill the array with the value of the given block,
3899 * which is passed the absolute index of each element to be filled.
3900 *
3901 * Negative values of +start+ count from the end of the array, where +-1+ is
3902 * the last element.
3903 *
3904 * a = [ "a", "b", "c", "d" ]
3905 * a.fill("x") #=> ["x", "x", "x", "x"]
3906 * a.fill("z", 2, 2) #=> ["x", "x", "z", "z"]
3907 * a.fill("y", 0..1) #=> ["y", "y", "z", "z"]
3908 * a.fill {|i| i*i} #=> [0, 1, 4, 9]
3909 * a.fill(-2) {|i| i*i*i} #=> [0, 1, 8, 27]
3910 */
3911
3912static VALUE
3913rb_ary_fill(int argc, VALUE *argv, VALUE ary)
3914{
3915 VALUE item = Qundef, arg1, arg2;
3916 long beg = 0, end = 0, len = 0;
3917
3918 if (rb_block_given_p()) {
3919 rb_scan_args(argc, argv, "02", &arg1, &arg2);
3920 argc += 1; /* hackish */
3921 }
3922 else {
3923 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
3924 }
3925 switch (argc) {
3926 case 1:
3927 beg = 0;
3928 len = RARRAY_LEN(ary);
3929 break;
3930 case 2:
3931 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
3932 break;
3933 }
3934 /* fall through */
3935 case 3:
3936 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
3937 if (beg < 0) {
3938 beg = RARRAY_LEN(ary) + beg;
3939 if (beg < 0) beg = 0;
3940 }
3941 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
3942 break;
3943 }
3945 if (len < 0) {
3946 return ary;
3947 }
3948 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
3949 rb_raise(rb_eArgError, "argument too big");
3950 }
3951 end = beg + len;
3952 if (RARRAY_LEN(ary) < end) {
3953 if (end >= ARY_CAPA(ary)) {
3954 ary_resize_capa(ary, end);
3955 }
3956 ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
3957 ARY_SET_LEN(ary, end);
3958 }
3959
3960 if (item == Qundef) {
3961 VALUE v;
3962 long i;
3963
3964 for (i=beg; i<end; i++) {
3965 v = rb_yield(LONG2NUM(i));
3966 if (i>=RARRAY_LEN(ary)) break;
3967 ARY_SET(ary, i, v);
3968 }
3969 }
3970 else {
3971 ary_memfill(ary, beg, len, item);
3972 }
3973 return ary;
3974}
3975
3976/*
3977 * call-seq:
3978 * ary + other_ary -> new_ary
3979 *
3980 * Concatenation --- Returns a new array built by concatenating the
3981 * two arrays together to produce a third array.
3982 *
3983 * [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]
3984 * a = [ "a", "b", "c" ]
3985 * c = a + [ "d", "e", "f" ]
3986 * c #=> [ "a", "b", "c", "d", "e", "f" ]
3987 * a #=> [ "a", "b", "c" ]
3988 *
3989 * Note that
3990 * x += y
3991 * is the same as
3992 * x = x + y
3993 * This means that it produces a new array. As a consequence,
3994 * repeated use of <code>+=</code> on arrays can be quite inefficient.
3995 *
3996 * See also Array#concat.
3997 */
3998
3999VALUE
4001{
4002 VALUE z;
4003 long len, xlen, ylen;
4004
4005 y = to_ary(y);
4006 xlen = RARRAY_LEN(x);
4007 ylen = RARRAY_LEN(y);
4008 len = xlen + ylen;
4009 z = rb_ary_new2(len);
4010
4011 ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR_TRANSIENT(x));
4012 ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR_TRANSIENT(y));
4013 ARY_SET_LEN(z, len);
4014 return z;
4015}
4016
4017static VALUE
4018ary_append(VALUE x, VALUE y)
4019{
4020 long n = RARRAY_LEN(y);
4021 if (n > 0) {
4022 rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR_TRANSIENT(y), n);
4023 }
4024 return x;
4025}
4026
4027/*
4028 * call-seq:
4029 * ary.concat(other_ary1, other_ary2, ...) -> ary
4030 *
4031 * Appends the elements of <code>other_ary</code>s to +self+.
4032 *
4033 * [ "a", "b" ].concat( ["c", "d"]) #=> [ "a", "b", "c", "d" ]
4034 * [ "a" ].concat( ["b"], ["c", "d"]) #=> [ "a", "b", "c", "d" ]
4035 * [ "a" ].concat #=> [ "a" ]
4036 *
4037 * a = [ 1, 2, 3 ]
4038 * a.concat( [ 4, 5 ])
4039 * a #=> [ 1, 2, 3, 4, 5 ]
4040 *
4041 * a = [ 1, 2 ]
4042 * a.concat(a, a) #=> [1, 2, 1, 2, 1, 2]
4043 *
4044 * See also Array#+.
4045 */
4046
4047static VALUE
4048rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
4049{
4050 rb_ary_modify_check(ary);
4051
4052 if (argc == 1) {
4053 rb_ary_concat(ary, argv[0]);
4054 }
4055 else if (argc > 1) {
4056 int i;
4057 VALUE args = rb_ary_tmp_new(argc);
4058 for (i = 0; i < argc; i++) {
4059 rb_ary_concat(args, argv[i]);
4060 }
4061 ary_append(ary, args);
4062 }
4063
4064 ary_verify(ary);
4065 return ary;
4066}
4067
4068VALUE
4070{
4071 return ary_append(x, to_ary(y));
4072}
4073
4074/*
4075 * call-seq:
4076 * ary * int -> new_ary
4077 * ary * str -> new_string
4078 *
4079 * Repetition --- With a String argument, equivalent to
4080 * <code>ary.join(str)</code>.
4081 *
4082 * Otherwise, returns a new array built by concatenating the +int+ copies of
4083 * +self+.
4084 *
4085 *
4086 * [ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
4087 * [ 1, 2, 3 ] * "," #=> "1,2,3"
4088 *
4089 */
4090
4091static VALUE
4092rb_ary_times(VALUE ary, VALUE times)
4093{
4094 VALUE ary2, tmp;
4095 const VALUE *ptr;
4096 long t, len;
4097
4098 tmp = rb_check_string_type(times);
4099 if (!NIL_P(tmp)) {
4100 return rb_ary_join(ary, tmp);
4101 }
4102
4103 len = NUM2LONG(times);
4104 if (len == 0) {
4105 ary2 = ary_new(rb_obj_class(ary), 0);
4106 goto out;
4107 }
4108 if (len < 0) {
4109 rb_raise(rb_eArgError, "negative argument");
4110 }
4111 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
4112 rb_raise(rb_eArgError, "argument too big");
4113 }
4114 len *= RARRAY_LEN(ary);
4115
4116 ary2 = ary_new(rb_obj_class(ary), len);
4117 ARY_SET_LEN(ary2, len);
4118
4120 t = RARRAY_LEN(ary);
4121 if (0 < t) {
4122 ary_memcpy(ary2, 0, t, ptr);
4123 while (t <= len/2) {
4124 ary_memcpy(ary2, t, t, RARRAY_CONST_PTR_TRANSIENT(ary2));
4125 t *= 2;
4126 }
4127 if (t < len) {
4128 ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR_TRANSIENT(ary2));
4129 }
4130 }
4131 out:
4132 return ary2;
4133}
4134
4135/*
4136 * call-seq:
4137 * ary.assoc(obj) -> element_ary or nil
4138 *
4139 * Searches through an array whose elements are also arrays comparing +obj+
4140 * with the first element of each contained array using <code>obj.==</code>.
4141 *
4142 * Returns the first contained array that matches (that is, the first
4143 * associated array), or +nil+ if no match is found.
4144 *
4145 * See also Array#rassoc
4146 *
4147 * s1 = [ "colors", "red", "blue", "green" ]
4148 * s2 = [ "letters", "a", "b", "c" ]
4149 * s3 = "foo"
4150 * a = [ s1, s2, s3 ]
4151 * a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
4152 * a.assoc("foo") #=> nil
4153 */
4154
4155VALUE
4157{
4158 long i;
4159 VALUE v;
4160
4161 for (i = 0; i < RARRAY_LEN(ary); ++i) {
4163 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
4164 rb_equal(RARRAY_AREF(v, 0), key))
4165 return v;
4166 }
4167 return Qnil;
4168}
4169
4170/*
4171 * call-seq:
4172 * ary.rassoc(obj) -> element_ary or nil
4173 *
4174 * Searches through the array whose elements are also arrays.
4175 *
4176 * Compares +obj+ with the second element of each contained array using
4177 * <code>obj.==</code>.
4178 *
4179 * Returns the first contained array that matches +obj+.
4180 *
4181 * See also Array#assoc.
4182 *
4183 * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
4184 * a.rassoc("two") #=> [2, "two"]
4185 * a.rassoc("four") #=> nil
4186 */
4187
4188VALUE
4190{
4191 long i;
4192 VALUE v;
4193
4194 for (i = 0; i < RARRAY_LEN(ary); ++i) {
4195 v = RARRAY_AREF(ary, i);
4196 if (RB_TYPE_P(v, T_ARRAY) &&
4197 RARRAY_LEN(v) > 1 &&
4198 rb_equal(RARRAY_AREF(v, 1), value))
4199 return v;
4200 }
4201 return Qnil;
4202}
4203
4204static VALUE
4205recursive_equal(VALUE ary1, VALUE ary2, int recur)
4206{
4207 long i, len1;
4208 const VALUE *p1, *p2;
4209
4210 if (recur) return Qtrue; /* Subtle! */
4211
4212 /* rb_equal() can evacuate ptrs */
4213 p1 = RARRAY_CONST_PTR(ary1);
4214 p2 = RARRAY_CONST_PTR(ary2);
4215 len1 = RARRAY_LEN(ary1);
4216
4217 for (i = 0; i < len1; i++) {
4218 if (*p1 != *p2) {
4219 if (rb_equal(*p1, *p2)) {
4220 len1 = RARRAY_LEN(ary1);
4221 if (len1 != RARRAY_LEN(ary2))
4222 return Qfalse;
4223 if (len1 < i)
4224 return Qtrue;
4225 p1 = RARRAY_CONST_PTR(ary1) + i;
4226 p2 = RARRAY_CONST_PTR(ary2) + i;
4227 }
4228 else {
4229 return Qfalse;
4230 }
4231 }
4232 p1++;
4233 p2++;
4234 }
4235 return Qtrue;
4236}
4237
4238/*
4239 * call-seq:
4240 * ary == other_ary -> bool
4241 *
4242 * Equality --- Two arrays are equal if they contain the same number of
4243 * elements and if each element is equal to (according to Object#==) the
4244 * corresponding element in +other_ary+.
4245 *
4246 * [ "a", "c" ] == [ "a", "c", 7 ] #=> false
4247 * [ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true
4248 * [ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false
4249 *
4250 */
4251
4252static VALUE
4253rb_ary_equal(VALUE ary1, VALUE ary2)
4254{
4255 if (ary1 == ary2) return Qtrue;
4256 if (!RB_TYPE_P(ary2, T_ARRAY)) {
4257 if (!rb_respond_to(ary2, idTo_ary)) {
4258 return Qfalse;
4259 }
4260 return rb_equal(ary2, ary1);
4261 }
4262 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
4264 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
4265}
4266
4267static VALUE
4268recursive_eql(VALUE ary1, VALUE ary2, int recur)
4269{
4270 long i;
4271
4272 if (recur) return Qtrue; /* Subtle! */
4273 for (i=0; i<RARRAY_LEN(ary1); i++) {
4274 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
4275 return Qfalse;
4276 }
4277 return Qtrue;
4278}
4279
4280/*
4281 * call-seq:
4282 * ary.eql?(other) -> true or false
4283 *
4284 * Returns +true+ if +self+ and +other+ are the same object,
4285 * or are both arrays with the same content (according to Object#eql?).
4286 */
4287
4288static VALUE
4289rb_ary_eql(VALUE ary1, VALUE ary2)
4290{
4291 if (ary1 == ary2) return Qtrue;
4292 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
4293 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
4295 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
4296}
4297
4298/*
4299 * call-seq:
4300 * ary.hash -> integer
4301 *
4302 * Compute a hash-code for this array.
4303 *
4304 * Two arrays with the same content will have the same hash code (and will
4305 * compare using #eql?).
4306 *
4307 * See also Object#hash.
4308 */
4309
4310static VALUE
4311rb_ary_hash(VALUE ary)
4312{
4313 long i;
4314 st_index_t h;
4315 VALUE n;
4316
4318 h = rb_hash_uint(h, (st_index_t)rb_ary_hash);
4319 for (i=0; i<RARRAY_LEN(ary); i++) {
4320 n = rb_hash(RARRAY_AREF(ary, i));
4321 h = rb_hash_uint(h, NUM2LONG(n));
4322 }
4323 h = rb_hash_end(h);
4324 return ST2FIX(h);
4325}
4326
4327/*
4328 * call-seq:
4329 * ary.include?(object) -> true or false
4330 *
4331 * Returns +true+ if the given +object+ is present in +self+ (that is, if any
4332 * element <code>==</code> +object+), otherwise returns +false+.
4333 *
4334 * a = [ "a", "b", "c" ]
4335 * a.include?("b") #=> true
4336 * a.include?("z") #=> false
4337 */
4338
4339VALUE
4341{
4342 long i;
4343 VALUE e;
4344
4345 for (i=0; i<RARRAY_LEN(ary); i++) {
4346 e = RARRAY_AREF(ary, i);
4347 if (rb_equal(e, item)) {
4348 return Qtrue;
4349 }
4350 }
4351 return Qfalse;
4352}
4353
4354static VALUE
4355rb_ary_includes_by_eql(VALUE ary, VALUE item)
4356{
4357 long i;
4358 VALUE e;
4359
4360 for (i=0; i<RARRAY_LEN(ary); i++) {
4361 e = RARRAY_AREF(ary, i);
4362 if (rb_eql(item, e)) {
4363 return Qtrue;
4364 }
4365 }
4366 return Qfalse;
4367}
4368
4369static VALUE
4370recursive_cmp(VALUE ary1, VALUE ary2, int recur)
4371{
4372 long i, len;
4373
4374 if (recur) return Qundef; /* Subtle! */
4375 len = RARRAY_LEN(ary1);
4376 if (len > RARRAY_LEN(ary2)) {
4377 len = RARRAY_LEN(ary2);
4378 }
4379 for (i=0; i<len; i++) {
4380 VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
4381 VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
4382 if (v != INT2FIX(0)) {
4383 return v;
4384 }
4385 }
4386 return Qundef;
4387}
4388
4389/*
4390 * call-seq:
4391 * ary <=> other_ary -> -1, 0, +1 or nil
4392 *
4393 * Comparison --- Returns an integer (+-1+, +0+, or <code>+1</code>) if this
4394 * array is less than, equal to, or greater than +other_ary+.
4395 *
4396 * Each object in each array is compared (using the <=> operator).
4397 *
4398 * Arrays are compared in an "element-wise" manner; the first element of +ary+
4399 * is compared with the first one of +other_ary+ using the <=> operator, then
4400 * each of the second elements, etc...
4401 * As soon as the result of any such comparison is non zero (i.e. the two
4402 * corresponding elements are not equal), that result is returned for the
4403 * whole array comparison.
4404 *
4405 * If all the elements are equal, then the result is based on a comparison of
4406 * the array lengths. Thus, two arrays are "equal" according to Array#<=> if,
4407 * and only if, they have the same length and the value of each element is
4408 * equal to the value of the corresponding element in the other array.
4409 *
4410 * +nil+ is returned if the +other_ary+ is not an array or if the comparison
4411 * of two elements returned +nil+.
4412 *
4413 * [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1
4414 * [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1
4415 * [ 1, 2 ] <=> [ 1, :two ] #=> nil
4416 *
4417 */
4418
4419VALUE
4421{
4422 long len;
4423 VALUE v;
4424
4425 ary2 = rb_check_array_type(ary2);
4426 if (NIL_P(ary2)) return Qnil;
4427 if (ary1 == ary2) return INT2FIX(0);
4428 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
4429 if (v != Qundef) return v;
4430 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
4431 if (len == 0) return INT2FIX(0);
4432 if (len > 0) return INT2FIX(1);
4433 return INT2FIX(-1);
4434}
4435
4436static VALUE
4437ary_add_hash(VALUE hash, VALUE ary)
4438{
4439 long i;
4440
4441 for (i=0; i<RARRAY_LEN(ary); i++) {
4442 VALUE elt = RARRAY_AREF(ary, i);
4443 rb_hash_add_new_element(hash, elt, elt);
4444 }
4445 return hash;
4446}
4447
4448static inline VALUE
4449ary_tmp_hash_new(VALUE ary)
4450{
4451 long size = RARRAY_LEN(ary);
4453
4454 RBASIC_CLEAR_CLASS(hash);
4455 return hash;
4456}
4457
4458static VALUE
4459ary_make_hash(VALUE ary)
4460{
4461 VALUE hash = ary_tmp_hash_new(ary);
4462 return ary_add_hash(hash, ary);
4463}
4464
4465static VALUE
4466ary_add_hash_by(VALUE hash, VALUE ary)
4467{
4468 long i;
4469
4470 for (i = 0; i < RARRAY_LEN(ary); ++i) {
4471 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
4472 rb_hash_add_new_element(hash, k, v);
4473 }
4474 return hash;
4475}
4476
4477static VALUE
4478ary_make_hash_by(VALUE ary)
4479{
4480 VALUE hash = ary_tmp_hash_new(ary);
4481 return ary_add_hash_by(hash, ary);
4482}
4483
4484static inline void
4485ary_recycle_hash(VALUE hash)
4486{
4487 assert(RBASIC_CLASS(hash) == 0);
4488 if (RHASH_ST_TABLE_P(hash)) {
4489 st_table *tbl = RHASH_ST_TABLE(hash);
4490 st_free_table(tbl);
4491 RHASH_ST_CLEAR(hash);
4492 }
4493}
4494
4495/*
4496 * call-seq:
4497 * ary - other_ary -> new_ary
4498 *
4499 * Array Difference
4500 *
4501 * Returns a new array that is a copy of the original array, removing all
4502 * occurrences of any item that also appear in +other_ary+. The order is
4503 * preserved from the original array.
4504 *
4505 * It compares elements using their #hash and #eql? methods for efficiency.
4506 *
4507 * [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
4508 *
4509 * Note that while 1 and 2 were only present once in the array argument, and
4510 * were present twice in the receiver array, all occurrences of each Integer are
4511 * removed in the returned array.
4512 *
4513 * If you need set-like behavior, see the library class Set.
4514 *
4515 * See also Array#difference.
4516 */
4517
4518static VALUE
4519rb_ary_diff(VALUE ary1, VALUE ary2)
4520{
4521 VALUE ary3;
4522 VALUE hash;
4523 long i;
4524
4525 ary2 = to_ary(ary2);
4526 ary3 = rb_ary_new();
4527
4528 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
4529 for (i=0; i<RARRAY_LEN(ary1); i++) {
4530 VALUE elt = rb_ary_elt(ary1, i);
4531 if (rb_ary_includes_by_eql(ary2, elt)) continue;
4532 rb_ary_push(ary3, elt);
4533 }
4534 return ary3;
4535 }
4536
4537 hash = ary_make_hash(ary2);
4538 for (i=0; i<RARRAY_LEN(ary1); i++) {
4539 if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
4540 rb_ary_push(ary3, rb_ary_elt(ary1, i));
4541 }
4542 ary_recycle_hash(hash);
4543 return ary3;
4544}
4545
4546/*
4547 * call-seq:
4548 * ary.difference(other_ary1, other_ary2, ...) -> new_ary
4549 *
4550 * Array Difference
4551 *
4552 * Returns a new array that is a copy of the original array, removing all
4553 * occurrences of any item that also appear in +other_ary+. The order is
4554 * preserved from the original array.
4555 *
4556 * It compares elements using their #hash and #eql? methods for efficiency.
4557 *
4558 * [ 1, 1, 2, 2, 3, 3, 4, 5 ].difference([ 1, 2, 4 ]) #=> [ 3, 3, 5 ]
4559 *
4560 * Note that while 1 and 2 were only present once in the array argument, and
4561 * were present twice in the receiver array, all occurrences of each Integer are
4562 * removed in the returned array.
4563 *
4564 * Multiple array arguments can be supplied and all occurrences of any element
4565 * in those supplied arrays that match the receiver will be removed from the
4566 * returned array.
4567 *
4568 * [ 1, 'c', :s, 'yep' ].difference([ 1 ], [ 'a', 'c' ]) #=> [ :s, "yep" ]
4569 *
4570 * If you need set-like behavior, see the library class Set.
4571 *
4572 * See also Array#-.
4573 */
4574
4575static VALUE
4576rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
4577{
4578 VALUE ary_diff;
4579 long i, length;
4580 volatile VALUE t0;
4581 bool *is_hash = ALLOCV_N(bool, t0, argc);
4582 ary_diff = rb_ary_new();
4583 length = RARRAY_LEN(ary);
4584
4585 for (i = 0; i < argc; i++) {
4586 argv[i] = to_ary(argv[i]);
4587 is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
4588 if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
4589 }
4590
4591 for (i = 0; i < RARRAY_LEN(ary); i++) {
4592 int j;
4593 VALUE elt = rb_ary_elt(ary, i);
4594 for (j = 0; j < argc; j++) {
4595 if (is_hash[j]) {
4597 break;
4598 }
4599 else {
4600 if (rb_ary_includes_by_eql(argv[j], elt)) break;
4601 }
4602 }
4603 if (j == argc) rb_ary_push(ary_diff, elt);
4604 }
4605
4606 ALLOCV_END(t0);
4607
4608 return ary_diff;
4609}
4610
4611
4612/*
4613 * call-seq:
4614 * ary & other_ary -> new_ary
4615 *
4616 * Set Intersection --- Returns a new array containing unique elements common to the
4617 * two arrays. The order is preserved from the original array.
4618 *
4619 * It compares elements using their #hash and #eql? methods for efficiency.
4620 *
4621 * [ 1, 1, 3, 5 ] & [ 3, 2, 1 ] #=> [ 1, 3 ]
4622 * [ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ] #=> [ 'a', 'b' ]
4623 *
4624 * See also Array#uniq.
4625 */
4626
4627
4628static VALUE
4629rb_ary_and(VALUE ary1, VALUE ary2)
4630{
4631 VALUE hash, ary3, v;
4632 st_data_t vv;
4633 long i;
4634
4635 ary2 = to_ary(ary2);
4636 ary3 = rb_ary_new();
4637 if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
4638
4639 if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
4640 for (i=0; i<RARRAY_LEN(ary1); i++) {
4641 v = RARRAY_AREF(ary1, i);
4642 if (!rb_ary_includes_by_eql(ary2, v)) continue;
4643 if (rb_ary_includes_by_eql(ary3, v)) continue;
4644 rb_ary_push(ary3, v);
4645 }
4646 return ary3;
4647 }
4648
4649 hash = ary_make_hash(ary2);
4650
4651 for (i=0; i<RARRAY_LEN(ary1); i++) {
4652 v = RARRAY_AREF(ary1, i);
4653 vv = (st_data_t)v;
4654 if (rb_hash_stlike_delete(hash, &vv, 0)) {
4655 rb_ary_push(ary3, v);
4656 }
4657 }
4658 ary_recycle_hash(hash);
4659
4660 return ary3;
4661}
4662
4663/*
4664 * call-seq:
4665 * ary.intersection(other_ary1, other_ary2, ...) -> new_ary
4666 *
4667 * Set Intersection --- Returns a new array containing unique elements common
4668 * to +self+ and <code>other_ary</code>s. Order is preserved from the original
4669 * array.
4670 *
4671 * It compares elements using their #hash and #eql? methods for efficiency.
4672 *
4673 * [ 1, 1, 3, 5 ].intersection([ 3, 2, 1 ]) # => [ 1, 3 ]
4674 * [ "a", "b", "z" ].intersection([ "a", "b", "c" ], [ "b" ]) # => [ "b" ]
4675 * [ "a" ].intersection #=> [ "a" ]
4676 *
4677 * See also Array#&.
4678 */
4679
4680static VALUE
4681rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
4682{
4683 VALUE result = rb_ary_dup(ary);
4684 int i;
4685
4686 for (i = 0; i < argc; i++) {
4687 result = rb_ary_and(result, argv[i]);
4688 }
4689
4690 return result;
4691}
4692
4693static int
4694ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
4695{
4696 if (existing) return ST_STOP;
4697 *key = *value = (VALUE)arg;
4698 return ST_CONTINUE;
4699}
4700
4701static void
4702rb_ary_union(VALUE ary_union, VALUE ary)
4703{
4704 long i;
4705 for (i = 0; i < RARRAY_LEN(ary); i++) {
4706 VALUE elt = rb_ary_elt(ary, i);
4707 if (rb_ary_includes_by_eql(ary_union, elt)) continue;
4708 rb_ary_push(ary_union, elt);
4709 }
4710}
4711
4712static void
4713rb_ary_union_hash(VALUE hash, VALUE ary2)
4714{
4715 long i;
4716 for (i = 0; i < RARRAY_LEN(ary2); i++) {
4717 VALUE elt = RARRAY_AREF(ary2, i);
4718 if (!rb_hash_stlike_update(hash, (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
4719 RB_OBJ_WRITTEN(hash, Qundef, elt);
4720 }
4721 }
4722}
4723
4724/*
4725 * call-seq:
4726 * ary | other_ary -> new_ary
4727 *
4728 * Set Union --- Returns a new array by joining +ary+ with +other_ary+,
4729 * excluding any duplicates and preserving the order from the given arrays.
4730 *
4731 * It compares elements using their #hash and #eql? methods for efficiency.
4732 *
4733 * [ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ]
4734 * [ "c", "d", "a" ] | [ "a", "b", "c" ] #=> [ "c", "d", "a", "b" ]
4735 *
4736 * See also Array#union.
4737 */
4738
4739static VALUE
4740rb_ary_or(VALUE ary1, VALUE ary2)
4741{
4742 VALUE hash, ary3;
4743
4744 ary2 = to_ary(ary2);
4745 if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
4746 ary3 = rb_ary_new();
4747 rb_ary_union(ary3, ary1);
4748 rb_ary_union(ary3, ary2);
4749 return ary3;
4750 }
4751
4752 hash = ary_make_hash(ary1);
4753 rb_ary_union_hash(hash, ary2);
4754
4755 ary3 = rb_hash_values(hash);
4756 ary_recycle_hash(hash);
4757 return ary3;
4758}
4759
4760/*
4761 * call-seq:
4762 * ary.union(other_ary1, other_ary2, ...) -> new_ary
4763 *
4764 * Set Union --- Returns a new array by joining <code>other_ary</code>s with +self+,
4765 * excluding any duplicates and preserving the order from the given arrays.
4766 *
4767 * It compares elements using their #hash and #eql? methods for efficiency.
4768 *
4769 * [ "a", "b", "c" ].union( [ "c", "d", "a" ] ) #=> [ "a", "b", "c", "d" ]
4770 * [ "a" ].union( ["e", "b"], ["a", "c", "b"] ) #=> [ "a", "e", "b", "c" ]
4771 * [ "a" ].union #=> [ "a" ]
4772 *
4773 * See also Array#|.
4774 */
4775
4776static VALUE
4777rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
4778{
4779 int i;
4780 long sum;
4781 VALUE hash, ary_union;
4782
4783 sum = RARRAY_LEN(ary);
4784 for (i = 0; i < argc; i++) {
4785 argv[i] = to_ary(argv[i]);
4786 sum += RARRAY_LEN(argv[i]);
4787 }
4788
4789 if (sum <= SMALL_ARRAY_LEN) {
4790 ary_union = rb_ary_new();
4791
4792 rb_ary_union(ary_union, ary);
4793 for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
4794
4795 return ary_union;
4796 }
4797
4798 hash = ary_make_hash(ary);
4799 for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
4800
4801 ary_union = rb_hash_values(hash);
4802 ary_recycle_hash(hash);
4803 return ary_union;
4804}
4805
4806/*
4807 * call-seq:
4808 * ary.max -> obj
4809 * ary.max {|a, b| block} -> obj
4810 * ary.max(n) -> array
4811 * ary.max(n) {|a, b| block} -> array
4812 *
4813 * Returns the object in _ary_ with the maximum value. The
4814 * first form assumes all objects implement Comparable;
4815 * the second uses the block to return <em>a <=> b</em>.
4816 *
4817 * ary = %w(albatross dog horse)
4818 * ary.max #=> "horse"
4819 * ary.max {|a, b| a.length <=> b.length} #=> "albatross"
4820 *
4821 * If the +n+ argument is given, maximum +n+ elements are returned
4822 * as an array.
4823 *
4824 * ary = %w[albatross dog horse]
4825 * ary.max(2) #=> ["horse", "dog"]
4826 * ary.max(2) {|a, b| a.length <=> b.length } #=> ["albatross", "horse"]
4827 */
4828static VALUE
4829rb_ary_max(int argc, VALUE *argv, VALUE ary)
4830{
4831 struct cmp_opt_data cmp_opt = { 0, 0 };
4832 VALUE result = Qundef, v;
4833 VALUE num;
4834 long i;
4835
4836 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
4837 return rb_nmin_run(ary, num, 0, 1, 1);
4838
4839 if (rb_block_given_p()) {
4840 for (i = 0; i < RARRAY_LEN(ary); i++) {
4841 v = RARRAY_AREF(ary, i);
4842 if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
4843 result = v;
4844 }
4845 }
4846 }
4847 else {
4848 for (i = 0; i < RARRAY_LEN(ary); i++) {
4849 v = RARRAY_AREF(ary, i);
4850 if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) > 0) {
4851 result = v;
4852 }
4853 }
4854 }
4855 if (result == Qundef) return Qnil;
4856 return result;
4857}
4858
4859/*
4860 * call-seq:
4861 * ary.min -> obj
4862 * ary.min {| a,b | block } -> obj
4863 * ary.min(n) -> array
4864 * ary.min(n) {| a,b | block } -> array
4865 *
4866 * Returns the object in _ary_ with the minimum value. The
4867 * first form assumes all objects implement Comparable;
4868 * the second uses the block to return <em>a <=> b</em>.
4869 *
4870 * ary = %w(albatross dog horse)
4871 * ary.min #=> "albatross"
4872 * ary.min {|a, b| a.length <=> b.length} #=> "dog"
4873 *
4874 * If the +n+ argument is given, minimum +n+ elements are returned
4875 * as an array.
4876 *
4877 * ary = %w[albatross dog horse]
4878 * ary.min(2) #=> ["albatross", "dog"]
4879 * ary.min(2) {|a, b| a.length <=> b.length } #=> ["dog", "horse"]
4880 */
4881static VALUE
4882rb_ary_min(int argc, VALUE *argv, VALUE ary)
4883{
4884 struct cmp_opt_data cmp_opt = { 0, 0 };
4885 VALUE result = Qundef, v;
4886 VALUE num;
4887 long i;
4888
4889 if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
4890 return rb_nmin_run(ary, num, 0, 0, 1);
4891
4892 if (rb_block_given_p()) {
4893 for (i = 0; i < RARRAY_LEN(ary); i++) {
4894 v = RARRAY_AREF(ary, i);
4895 if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
4896 result = v;
4897 }
4898 }
4899 }
4900 else {
4901 for (i = 0; i < RARRAY_LEN(ary); i++) {
4902 v = RARRAY_AREF(ary, i);
4903 if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) < 0) {
4904 result = v;
4905 }
4906 }
4907 }
4908 if (result == Qundef) return Qnil;
4909 return result;
4910}
4911
4912/*
4913 * call-seq:
4914 * ary.minmax -> [obj, obj]
4915 * ary.minmax {| a,b | block } -> [obj, obj]
4916 *
4917 * Returns a two element array which contains the minimum and the
4918 * maximum value in the array.
4919 *
4920 * Can be given an optional block to override the default comparison
4921 * method <code>a <=> b</code>.
4922 */
4923static VALUE
4924rb_ary_minmax(VALUE ary)
4925{
4926 if (rb_block_given_p()) {
4927 return rb_call_super(0, NULL);
4928 }
4929 return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
4930}
4931
4932static int
4933push_value(st_data_t key, st_data_t val, st_data_t ary)
4934{
4935 rb_ary_push((VALUE)ary, (VALUE)val);
4936 return ST_CONTINUE;
4937}
4938
4939/*
4940 * call-seq:
4941 * ary.uniq! -> ary or nil
4942 * ary.uniq! {|item| ...} -> ary or nil
4943 *
4944 * Removes duplicate elements from +self+.
4945 *
4946 * If a block is given, it will use the return value of the block for
4947 * comparison.
4948 *
4949 * It compares values using their #hash and #eql? methods for efficiency.
4950 *
4951 * +self+ is traversed in order, and the first occurrence is kept.
4952 *
4953 * Returns +nil+ if no changes are made (that is, no duplicates are found).
4954 *
4955 * a = [ "a", "a", "b", "b", "c" ]
4956 * a.uniq! # => ["a", "b", "c"]
4957 *
4958 * b = [ "a", "b", "c" ]
4959 * b.uniq! # => nil
4960 *
4961 * c = [["student","sam"], ["student","george"], ["teacher","matz"]]
4962 * c.uniq! {|s| s.first} # => [["student", "sam"], ["teacher", "matz"]]
4963 *
4964 */
4965
4966static VALUE
4967rb_ary_uniq_bang(VALUE ary)
4968{
4969 VALUE hash;
4970 long hash_size;
4971
4972 rb_ary_modify_check(ary);
4973 if (RARRAY_LEN(ary) <= 1)
4974 return Qnil;
4975 if (rb_block_given_p())
4976 hash = ary_make_hash_by(ary);
4977 else
4978 hash = ary_make_hash(ary);
4979
4980 hash_size = RHASH_SIZE(hash);
4981 if (RARRAY_LEN(ary) == hash_size) {
4982 return Qnil;
4983 }
4984 rb_ary_modify_check(ary);
4985 ARY_SET_LEN(ary, 0);
4986 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
4987 rb_ary_unshare(ary);
4988 FL_SET_EMBED(ary);
4989 }
4990 ary_resize_capa(ary, hash_size);
4991 rb_hash_foreach(hash, push_value, ary);
4992 ary_recycle_hash(hash);
4993
4994 return ary;
4995}
4996
4997/*
4998 * call-seq:
4999 * ary.uniq -> new_ary
5000 * ary.uniq {|item| ...} -> new_ary
5001 *
5002 * Returns a new array by removing duplicate values in +self+.
5003 *
5004 * If a block is given, it will use the return value of the block for comparison.
5005 *
5006 * It compares values using their #hash and #eql? methods for efficiency.
5007 *
5008 * +self+ is traversed in order, and the first occurrence is kept.
5009 *
5010 * a = [ "a", "a", "b", "b", "c" ]
5011 * a.uniq # => ["a", "b", "c"]
5012 *
5013 * b = [["student","sam"], ["student","george"], ["teacher","matz"]]
5014 * b.uniq {|s| s.first} # => [["student", "sam"], ["teacher", "matz"]]
5015 *
5016 */
5017
5018static VALUE
5019rb_ary_uniq(VALUE ary)
5020{
5021 VALUE hash, uniq;
5022
5023 if (RARRAY_LEN(ary) <= 1) {
5024 hash = 0;
5025 uniq = rb_ary_dup(ary);
5026 }
5027 else if (rb_block_given_p()) {
5028 hash = ary_make_hash_by(ary);
5029 uniq = rb_hash_values(hash);
5030 }
5031 else {
5032 hash = ary_make_hash(ary);
5033 uniq = rb_hash_values(hash);
5034 }
5035 RBASIC_SET_CLASS(uniq, rb_obj_class(ary));
5036 if (hash) {
5037 ary_recycle_hash(hash);
5038 }
5039
5040 return uniq;
5041}
5042
5043/*
5044 * call-seq:
5045 * ary.compact! -> ary or nil
5046 *
5047 * Removes +nil+ elements from the array.
5048 *
5049 * Returns +nil+ if no changes were made, otherwise returns the array.
5050 *
5051 * [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
5052 * [ "a", "b", "c" ].compact! #=> nil
5053 */
5054
5055static VALUE
5056rb_ary_compact_bang(VALUE ary)
5057{
5058 VALUE *p, *t, *end;
5059 long n;
5060
5061 rb_ary_modify(ary);
5062 p = t = (VALUE *)RARRAY_CONST_PTR_TRANSIENT(ary); /* WB: no new reference */
5063 end = p + RARRAY_LEN(ary);
5064
5065 while (t < end) {
5066 if (NIL_P(*t)) t++;
5067 else *p++ = *t++;
5068 }
5069 n = p - RARRAY_CONST_PTR_TRANSIENT(ary);
5070 if (RARRAY_LEN(ary) == n) {
5071 return Qnil;
5072 }
5073 ary_resize_smaller(ary, n);
5074
5075 return ary;
5076}
5077
5078/*
5079 * call-seq:
5080 * ary.compact -> new_ary
5081 *
5082 * Returns a copy of +self+ with all +nil+ elements removed.
5083 *
5084 * [ "a", nil, "b", nil, "c", nil ].compact
5085 * #=> [ "a", "b", "c" ]
5086 */
5087
5088static VALUE
5089rb_ary_compact(VALUE ary)
5090{
5091 ary = rb_ary_dup(ary);
5092 rb_ary_compact_bang(ary);
5093 return ary;
5094}
5095
5096/*
5097 * call-seq:
5098 * ary.count -> int
5099 * ary.count(obj) -> int
5100 * ary.count {|item| block} -> int
5101 *
5102 * Returns the number of elements.
5103 *
5104 * If an argument is given, counts the number of elements which equal +obj+
5105 * using <code>==</code>.
5106 *
5107 * If a block is given, counts the number of elements for which the block
5108 * returns a true value.
5109 *
5110 * ary = [1, 2, 4, 2]
5111 * ary.count #=> 4
5112 * ary.count(2) #=> 2
5113 * ary.count {|x| x%2 == 0} #=> 3
5114 *
5115 */
5116
5117static VALUE
5118rb_ary_count(int argc, VALUE *argv, VALUE ary)
5119{
5120 long i, n = 0;
5121
5122 if (rb_check_arity(argc, 0, 1) == 0) {
5123 VALUE v;
5124
5125 if (!rb_block_given_p())
5126 return LONG2NUM(RARRAY_LEN(ary));
5127
5128 for (i = 0; i < RARRAY_LEN(ary); i++) {
5129 v = RARRAY_AREF(ary, i);
5130 if (RTEST(rb_yield(v))) n++;
5131 }
5132 }
5133 else {
5134 VALUE obj = argv[0];
5135
5136 if (rb_block_given_p()) {
5137 rb_warn("given block not used");
5138 }
5139 for (i = 0; i < RARRAY_LEN(ary); i++) {
5140 if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
5141 }
5142 }
5143
5144 return LONG2NUM(n);
5145}
5146
5147static VALUE
5148flatten(VALUE ary, int level)
5149{
5150 long i;
5151 VALUE stack, result, tmp, elt, vmemo;
5152 st_table *memo = 0;
5153 st_data_t id;
5154
5155 for (i = 0; i < RARRAY_LEN(ary); i++) {
5156 elt = RARRAY_AREF(ary, i);
5157 tmp = rb_check_array_type(elt);
5158 if (!NIL_P(tmp)) {
5159 break;
5160 }
5161 }
5162 if (i == RARRAY_LEN(ary)) {
5163 return ary;
5164 }
5165
5166 result = ary_new(0, RARRAY_LEN(ary));
5167 ary_memcpy(result, 0, i, RARRAY_CONST_PTR_TRANSIENT(ary));
5168 ARY_SET_LEN(result, i);
5169
5170 stack = ary_new(0, ARY_DEFAULT_SIZE);
5171 rb_ary_push(stack, ary);
5172 rb_ary_push(stack, LONG2NUM(i + 1));
5173
5174 if (level < 0) {
5175 vmemo = rb_hash_new();
5176 RBASIC_CLEAR_CLASS(vmemo);
5177 memo = st_init_numtable();
5178 rb_hash_st_table_set(vmemo, memo);
5179 st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
5180 st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue);
5181 }
5182
5183 ary = tmp;
5184 i = 0;
5185
5186 while (1) {
5187 while (i < RARRAY_LEN(ary)) {
5188 elt = RARRAY_AREF(ary, i++);
5189 if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
5190 rb_ary_push(result, elt);
5191 continue;
5192 }
5193 tmp = rb_check_array_type(elt);
5194 if (RBASIC(result)->klass) {
5195 if (memo) {
5196 RB_GC_GUARD(vmemo);
5197 st_clear(memo);
5198 }
5199 rb_raise(rb_eRuntimeError, "flatten reentered");
5200 }
5201 if (NIL_P(tmp)) {
5202 rb_ary_push(result, elt);
5203 }
5204 else {
5205 if (memo) {
5206 id = (st_data_t)tmp;
5207 if (st_is_member(memo, id)) {
5208 st_clear(memo);
5209 rb_raise(rb_eArgError, "tried to flatten recursive array");
5210 }
5211 st_insert(memo, id, (st_data_t)Qtrue);
5212 }
5213 rb_ary_push(stack, ary);
5214 rb_ary_push(stack, LONG2NUM(i));
5215 ary = tmp;
5216 i = 0;
5217 }
5218 }
5219 if (RARRAY_LEN(stack) == 0) {
5220 break;
5221 }
5222 if (memo) {
5223 id = (st_data_t)ary;
5224 st_delete(memo, &id, 0);
5225 }
5226 tmp = rb_ary_pop(stack);
5227 i = NUM2LONG(tmp);
5228 ary = rb_ary_pop(stack);
5229 }
5230
5231 if (memo) {
5232 st_clear(memo);
5233 }
5234
5235 RBASIC_SET_CLASS(result, rb_obj_class(ary));
5236 return result;
5237}
5238
5239/*
5240 * call-seq:
5241 * ary.flatten! -> ary or nil
5242 * ary.flatten!(level) -> ary or nil
5243 *
5244 * Flattens +self+ in place.
5245 *
5246 * Returns +nil+ if no modifications were made (i.e., the array contains no
5247 * subarrays.)
5248 *
5249 * The optional +level+ argument determines the level of recursion to flatten.
5250 *
5251 * a = [ 1, 2, [3, [4, 5] ] ]
5252 * a.flatten! #=> [1, 2, 3, 4, 5]
5253 * a.flatten! #=> nil
5254 * a #=> [1, 2, 3, 4, 5]
5255 * a = [ 1, 2, [3, [4, 5] ] ]
5256 * a.flatten!(1) #=> [1, 2, 3, [4, 5]]
5257 */
5258
5259static VALUE
5260rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
5261{
5262 int mod = 0, level = -1;
5263 VALUE result, lv;
5264
5265 lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
5266 rb_ary_modify_check(ary);
5267 if (!NIL_P(lv)) level = NUM2INT(lv);
5268 if (level == 0) return Qnil;
5269
5270 result = flatten(ary, level);
5271 if (result == ary) {
5272 return Qnil;
5273 }
5274 if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
5275 rb_ary_replace(ary, result);
5276 if (mod) ARY_SET_EMBED_LEN(result, 0);
5277
5278 return ary;
5279}
5280
5281/*
5282 * call-seq:
5283 * ary.flatten -> new_ary
5284 * ary.flatten(level) -> new_ary
5285 *
5286 * Returns a new array that is a one-dimensional flattening of +self+
5287 * (recursively).
5288 *
5289 * That is, for every element that is an array, extract its elements into
5290 * the new array.
5291 *
5292 * The optional +level+ argument determines the level of recursion to
5293 * flatten.
5294 *
5295 * s = [ 1, 2, 3 ] #=> [1, 2, 3]
5296 * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
5297 * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
5298 * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
5299 * a = [ 1, 2, [3, [4, 5] ] ]
5300 * a.flatten(1) #=> [1, 2, 3, [4, 5]]
5301 */
5302
5303static VALUE
5304rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
5305{
5306 int level = -1;
5307 VALUE result;
5308
5309 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
5310 level = NUM2INT(argv[0]);
5311 if (level == 0) return ary_make_shared_copy(ary);
5312 }
5313
5314 result = flatten(ary, level);
5315 if (result == ary) {
5316 result = ary_make_shared_copy(ary);
5317 }
5318
5319 return result;
5320}
5321
5322#define OPTHASH_GIVEN_P(opts) \
5323 (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
5324static ID id_random;
5325
5326#define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
5327
5328/*
5329 * call-seq:
5330 * ary.shuffle! -> ary
5331 * ary.shuffle!(random: rng) -> ary
5332 *
5333 * Shuffles elements in +self+ in place.
5334 *
5335 * a = [ 1, 2, 3 ] #=> [1, 2, 3]
5336 * a.shuffle! #=> [2, 3, 1]
5337 * a #=> [2, 3, 1]
5338 *
5339 * The optional +rng+ argument will be used as the random number generator.
5340 *
5341 * a.shuffle!(random: Random.new(1)) #=> [1, 3, 2]
5342 */
5343
5344static VALUE
5345rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
5346{
5347 VALUE opts, randgen = rb_cRandom;
5348 long i, len;
5349
5350 if (OPTHASH_GIVEN_P(opts)) {
5351 VALUE rnd;
5352 ID keyword_ids[1];
5353
5354 keyword_ids[0] = id_random;
5355 rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
5356 if (rnd != Qundef) {
5357 randgen = rnd;
5358 }
5359 }
5360 rb_check_arity(argc, 0, 0);
5361 rb_ary_modify(ary);
5362 i = len = RARRAY_LEN(ary);
5363 RARRAY_PTR_USE(ary, ptr, {
5364 while (i) {
5365 long j = RAND_UPTO(i);
5366 VALUE tmp;
5367 if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR_TRANSIENT(ary)) {
5368 rb_raise(rb_eRuntimeError, "modified during shuffle");
5369 }
5370 tmp = ptr[--i];
5371 ptr[i] = ptr[j];
5372 ptr[j] = tmp;
5373 }
5374 }); /* WB: no new reference */
5375 return ary;
5376}
5377
5378
5379/*
5380 * call-seq:
5381 * ary.shuffle -> new_ary
5382 * ary.shuffle(random: rng) -> new_ary
5383 *
5384 * Returns a new array with elements of +self+ shuffled.
5385 *
5386 * a = [ 1, 2, 3 ] #=> [1, 2, 3]
5387 * a.shuffle #=> [2, 3, 1]
5388 * a #=> [1, 2, 3]
5389 *
5390 * The optional +rng+ argument will be used as the random number generator.
5391 *
5392 * a.shuffle(random: Random.new(1)) #=> [1, 3, 2]
5393 */
5394
5395static VALUE
5396rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
5397{
5398 ary = rb_ary_dup(ary);
5399 rb_ary_shuffle_bang(argc, argv, ary);
5400 return ary;
5401}
5402
5403
5404/*
5405 * call-seq:
5406 * ary.sample -> obj
5407 * ary.sample(random: rng) -> obj
5408 * ary.sample(n) -> new_ary
5409 * ary.sample(n, random: rng) -> new_ary
5410 *
5411 * Choose a random element or +n+ random elements from the array.
5412 *
5413 * The elements are chosen by using random and unique indices into the array
5414 * in order to ensure that an element doesn't repeat itself unless the array
5415 * already contained duplicate elements.
5416 *
5417 * If the array is empty the first form returns +nil+ and the second form
5418 * returns an empty array.
5419 *
5420 * a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
5421 * a.sample #=> 7
5422 * a.sample(4) #=> [6, 4, 2, 5]
5423 *
5424 * The optional +rng+ argument will be used as the random number generator.
5425 *
5426 * a.sample(random: Random.new(1)) #=> 6
5427 * a.sample(4, random: Random.new(1)) #=> [6, 10, 9, 2]
5428 */
5429
5430
5431static VALUE
5432rb_ary_sample(int argc, VALUE *argv, VALUE ary)
5433{
5434 VALUE nv, result;
5435 VALUE opts, randgen = rb_cRandom;
5436 long n, len, i, j, k, idx[10];
5437 long rnds[numberof(idx)];
5438 long memo_threshold;
5439
5440 if (OPTHASH_GIVEN_P(opts)) {
5441 VALUE rnd;
5442 ID keyword_ids[1];
5443
5444 keyword_ids[0] = id_random;
5445 rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
5446 if (rnd != Qundef) {
5447 randgen = rnd;
5448 }
5449 }
5450 len = RARRAY_LEN(ary);
5451 if (rb_check_arity(argc, 0, 1) == 0) {
5452 if (len < 2)
5453 i = 0;
5454 else
5455 i = RAND_UPTO(len);
5456
5457 return rb_ary_elt(ary, i);
5458 }
5459 nv = argv[0];
5460 n = NUM2LONG(nv);
5461 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
5462 if (n > len) n = len;
5463 if (n <= numberof(idx)) {
5464 for (i = 0; i < n; ++i) {
5465 rnds[i] = RAND_UPTO(len - i);
5466 }
5467 }
5468 k = len;
5469 len = RARRAY_LEN(ary);
5470 if (len < k && n <= numberof(idx)) {
5471 for (i = 0; i < n; ++i) {
5472 if (rnds[i] >= len) return rb_ary_new_capa(0);
5473 }
5474 }
5475 if (n > len) n = len;
5476 switch (n) {
5477 case 0:
5478 return rb_ary_new_capa(0);
5479 case 1:
5480 i = rnds[0];
5481 return rb_ary_new_from_values(1, &RARRAY_AREF(ary, i));
5482 case 2:
5483 i = rnds[0];
5484 j = rnds[1];
5485 if (j >= i) j++;
5486 return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
5487 case 3:
5488 i = rnds[0];
5489 j = rnds[1];
5490 k = rnds[2];
5491 {
5492 long l = j, g = i;
5493 if (j >= i) l = i, g = ++j;
5494 if (k >= l && (++k >= g)) ++k;
5495 }
5496 return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
5497 }
5498 memo_threshold =
5499 len < 2560 ? len / 128 :
5500 len < 5120 ? len / 64 :
5501 len < 10240 ? len / 32 :
5502 len / 16;
5503 if (n <= numberof(idx)) {
5504 long sorted[numberof(idx)];
5505 sorted[0] = idx[0] = rnds[0];
5506 for (i=1; i<n; i++) {
5507 k = rnds[i];
5508 for (j = 0; j < i; ++j) {
5509 if (k < sorted[j]) break;
5510 ++k;
5511 }
5512 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
5513 sorted[j] = idx[i] = k;
5514 }
5515 result = rb_ary_new_capa(n);
5516 RARRAY_PTR_USE_TRANSIENT(result, ptr_result, {
5517 for (i=0; i<n; i++) {
5518 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
5519 }
5520 });
5521 }
5522 else if (n <= memo_threshold / 2) {
5523 long max_idx = 0;
5524#undef RUBY_UNTYPED_DATA_WARNING
5525#define RUBY_UNTYPED_DATA_WARNING 0
5526 VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
5528 DATA_PTR(vmemo) = memo;
5529 result = rb_ary_new_capa(n);
5530 RARRAY_PTR_USE(result, ptr_result, {
5531 for (i=0; i<n; i++) {
5532 long r = RAND_UPTO(len-i) + i;
5533 ptr_result[i] = r;
5534 if (r > max_idx) max_idx = r;
5535 }
5536 len = RARRAY_LEN(ary);
5537 if (len <= max_idx) n = 0;
5538 else if (n > len) n = len;
5539 RARRAY_PTR_USE_TRANSIENT(ary, ptr_ary, {
5540 for (i=0; i<n; i++) {
5541 long j2 = j = ptr_result[i];
5542 long i2 = i;
5543 st_data_t value;
5544 if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
5545 if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
5546 st_insert(memo, (st_data_t)j, (st_data_t)i2);
5547 ptr_result[i] = ptr_ary[j2];
5548 }
5549 });
5550 });
5551 DATA_PTR(vmemo) = 0;
5552 st_free_table(memo);
5553 }
5554 else {
5555 result = rb_ary_dup(ary);
5556 RBASIC_CLEAR_CLASS(result);
5557 RB_GC_GUARD(ary);
5558 RARRAY_PTR_USE(result, ptr_result, {
5559 for (i=0; i<n; i++) {
5560 j = RAND_UPTO(len-i) + i;
5561 nv = ptr_result[j];
5562 ptr_result[j] = ptr_result[i];
5563 ptr_result[i] = nv;
5564 }
5565 });
5567 }
5568 ARY_SET_LEN(result, n);
5569
5570 return result;
5571}
5572
5573static VALUE
5574rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
5575{
5576 long mul;
5577 VALUE n = Qnil;
5578 if (args && (RARRAY_LEN(args) > 0)) {
5579 n = RARRAY_AREF(args, 0);
5580 }
5581 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
5582 if (n == Qnil) return DBL2NUM(HUGE_VAL);
5583 mul = NUM2LONG(n);
5584 if (mul <= 0) return INT2FIX(0);
5585 n = LONG2FIX(mul);
5586 return rb_fix_mul_fix(rb_ary_length(self), n);
5587}
5588
5589/*
5590 * call-seq:
5591 * ary.cycle(n=nil) {|obj| block} -> nil
5592 * ary.cycle(n=nil) -> Enumerator
5593 *
5594 * Calls the given block for each element +n+ times or forever if +nil+ is
5595 * given.
5596 *
5597 * Does nothing if a non-positive number is given or the array is empty.
5598 *
5599 * Returns +nil+ if the loop has finished without getting interrupted.
5600 *
5601 * If no block is given, an Enumerator is returned instead.
5602 *
5603 * a = ["a", "b", "c"]
5604 * a.cycle {|x| puts x} # print, a, b, c, a, b, c,.. forever.
5605 * a.cycle(2) {|x| puts x} # print, a, b, c, a, b, c.
5606 *
5607 */
5608
5609static VALUE
5610rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
5611{
5612 long n, i;
5613
5614 rb_check_arity(argc, 0, 1);
5615
5616 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
5617 if (argc == 0 || NIL_P(argv[0])) {
5618 n = -1;
5619 }
5620 else {
5621 n = NUM2LONG(argv[0]);
5622 if (n <= 0) return Qnil;
5623 }
5624
5625 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
5626 for (i=0; i<RARRAY_LEN(ary); i++) {
5627 rb_yield(RARRAY_AREF(ary, i));
5628 }
5629 }
5630 return Qnil;
5631}
5632
5633#define tmpary(n) rb_ary_tmp_new(n)
5634#define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
5635
5636/*
5637 * Build a ruby array of the corresponding values and yield it to the
5638 * associated block.
5639 * Return the class of +values+ for reentry check.
5640 */
5641static int
5642yield_indexed_values(const VALUE values, const long r, const long *const p)
5643{
5644 const VALUE result = rb_ary_new2(r);
5645 long i;
5646
5647 for (i = 0; i < r; i++) ARY_SET(result, i, RARRAY_AREF(values, p[i]));
5648 ARY_SET_LEN(result, r);
5649 rb_yield(result);
5650 return !RBASIC(values)->klass;
5651}
5652
5653/*
5654 * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
5655 *
5656 * When we have a complete permutation of array indices, copy the values
5657 * at those indices into a new array and yield that array.
5658 *
5659 * n: the size of the set
5660 * r: the number of elements in each permutation
5661 * p: the array (of size r) that we're filling in
5662 * used: an array of booleans: whether a given index is already used
5663 * values: the Ruby array that holds the actual values to permute
5664 */
5665static void
5666permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
5667{
5668 long i = 0, index = 0;
5669
5670 for (;;) {
5671 const char *const unused = memchr(&used[i], 0, n-i);
5672 if (!unused) {
5673 if (!index) break;
5674 i = p[--index]; /* pop index */
5675 used[i++] = 0; /* index unused */
5676 }
5677 else {
5678 i = unused - used;
5679 p[index] = i;
5680 used[i] = 1; /* mark index used */
5681 ++index;
5682 if (index < r-1) { /* if not done yet */
5683 p[index] = i = 0;
5684 continue;
5685 }
5686 for (i = 0; i < n; ++i) {
5687 if (used[i]) continue;
5688 p[index] = i;
5689 if (!yield_indexed_values(values, r, p)) {
5690 rb_raise(rb_eRuntimeError, "permute reentered");
5691 }
5692 }
5693 i = p[--index]; /* pop index */
5694 used[i] = 0; /* index unused */
5695 p[index] = ++i;
5696 }
5697 }
5698}
5699
5700/*
5701 * Returns the product of from, from-1, ..., from - how_many + 1.
5702 * http://en.wikipedia.org/wiki/Pochhammer_symbol
5703 */
5704static VALUE
5705descending_factorial(long from, long how_many)
5706{
5707 VALUE cnt;
5708 if (how_many > 0) {
5709 cnt = LONG2FIX(from);
5710 while (--how_many > 0) {
5711 long v = --from;
5713 }
5714 }
5715 else {
5716 cnt = LONG2FIX(how_many == 0);
5717 }
5718 return cnt;
5719}
5720
5721static VALUE
5722binomial_coefficient(long comb, long size)
5723{
5724 VALUE r;
5725 long i;
5726 if (comb > size-comb) {
5727 comb = size-comb;
5728 }
5729 if (comb < 0) {
5730 return LONG2FIX(0);
5731 }
5732 else if (comb == 0) {
5733 return LONG2FIX(1);
5734 }
5735 r = LONG2FIX(size);
5736 for (i = 1; i < comb; ++i) {
5737 r = rb_int_mul(r, LONG2FIX(size - i));
5738 r = rb_int_idiv(r, LONG2FIX(i + 1));
5739 }
5740 return r;
5741}
5742
5743static VALUE
5744rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
5745{
5746 long n = RARRAY_LEN(ary);
5747 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
5748
5749 return descending_factorial(n, k);
5750}
5751
5752/*
5753 * call-seq:
5754 * ary.permutation {|p| block} -> ary
5755 * ary.permutation -> Enumerator
5756 * ary.permutation(n) {|p| block} -> ary
5757 * ary.permutation(n) -> Enumerator
5758 *
5759 * When invoked with a block, yield all permutations of length +n+ of the
5760 * elements of the array, then return the array itself.
5761 *
5762 * If +n+ is not specified, yield all permutations of all elements.
5763 *
5764 * The implementation makes no guarantees about the order in which the
5765 * permutations are yielded.
5766 *
5767 * If no block is given, an Enumerator is returned instead.
5768 *
5769 * Examples:
5770 *
5771 * a = [1, 2, 3]
5772 * a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
5773 * a.permutation(1).to_a #=> [[1],[2],[3]]
5774 * a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
5775 * a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
5776 * a.permutation(0).to_a #=> [[]] # one permutation of length 0
5777 * a.permutation(4).to_a #=> [] # no permutations of length 4
5778 */
5779
5780static VALUE
5781rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
5782{
5783 long r, n, i;
5784
5785 n = RARRAY_LEN(ary); /* Array length */
5786 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size); /* Return enumerator if no block */
5787 r = n;
5788 if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
5789 r = NUM2LONG(argv[0]); /* Permutation size from argument */
5790
5791 if (r < 0 || n < r) {
5792 /* no permutations: yield nothing */
5793 }
5794 else if (r == 0) { /* exactly one permutation: the zero-length array */
5796 }
5797 else if (r == 1) { /* this is a special, easy case */
5798 for (i = 0; i < RARRAY_LEN(ary); i++) {
5799 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
5800 }
5801 }
5802 else { /* this is the general case */
5803 volatile VALUE t0;
5804 long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
5805 char *used = (char*)(p + r);
5806 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
5807 RBASIC_CLEAR_CLASS(ary0);
5808
5809 MEMZERO(used, char, n); /* initialize array */
5810
5811 permute0(n, r, p, used, ary0); /* compute and yield permutations */
5812 ALLOCV_END(t0);
5814 }
5815 return ary;
5816}
5817
5818static void
5819combinate0(const long len, const long n, long *const stack, const VALUE values)
5820{
5821 long lev = 0;
5822
5823 MEMZERO(stack+1, long, n);
5824 stack[0] = -1;
5825 for (;;) {
5826 for (lev++; lev < n; lev++) {
5827 stack[lev+1] = stack[lev]+1;
5828 }
5829 if (!yield_indexed_values(values, n, stack+1)) {
5830 rb_raise(rb_eRuntimeError, "combination reentered");
5831 }
5832 do {
5833 if (lev == 0) return;
5834 stack[lev--]++;
5835 } while (stack[lev+1]+n == len+lev+1);
5836 }
5837}
5838
5839static VALUE
5840rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
5841{
5842 long n = RARRAY_LEN(ary);
5843 long k = NUM2LONG(RARRAY_AREF(args, 0));
5844
5845 return binomial_coefficient(k, n);
5846}
5847
5848/*
5849 * call-seq:
5850 * ary.combination(n) {|c| block} -> ary
5851 * ary.combination(n) -> Enumerator
5852 *
5853 * When invoked with a block, yields all combinations of length +n+ of elements
5854 * from the array and then returns the array itself.
5855 *
5856 * The implementation makes no guarantees about the order in which the
5857 * combinations are yielded.
5858 *
5859 * If no block is given, an Enumerator is returned instead.
5860 *
5861 * Examples:
5862 *
5863 * a = [1, 2, 3, 4]
5864 * a.combination(1).to_a #=> [[1],[2],[3],[4]]
5865 * a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
5866 * a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
5867 * a.combination(4).to_a #=> [[1,2,3,4]]
5868 * a.combination(0).to_a #=> [[]] # one combination of length 0
5869 * a.combination(5).to_a #=> [] # no combinations of length 5
5870 *
5871 */
5872
5873static VALUE
5874rb_ary_combination(VALUE ary, VALUE num)
5875{
5876 long i, n, len;
5877
5878 n = NUM2LONG(num);
5879 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
5880 len = RARRAY_LEN(ary);
5881 if (n < 0 || len < n) {
5882 /* yield nothing */
5883 }
5884 else if (n == 0) {
5886 }
5887 else if (n == 1) {
5888 for (i = 0; i < RARRAY_LEN(ary); i++) {
5889 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
5890 }
5891 }
5892 else {
5893 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
5894 volatile VALUE t0;
5895 long *stack = ALLOCV_N(long, t0, n+1);
5896
5897 RBASIC_CLEAR_CLASS(ary0);
5898 combinate0(len, n, stack, ary0);
5899 ALLOCV_END(t0);
5901 }
5902 return ary;
5903}
5904
5905/*
5906 * Compute repeated permutations of +r+ elements of the set
5907 * <code>[0..n-1]</code>.
5908 *
5909 * When we have a complete repeated permutation of array indices, copy the
5910 * values at those indices into a new array and yield that array.
5911 *
5912 * n: the size of the set
5913 * r: the number of elements in each permutation
5914 * p: the array (of size r) that we're filling in
5915 * values: the Ruby array that holds the actual values to permute
5916 */
5917static void
5918rpermute0(const long n, const long r, long *const p, const VALUE values)
5919{
5920 long i = 0, index = 0;
5921
5922 p[index] = i;
5923 for (;;) {
5924 if (++index < r-1) {
5925 p[index] = i = 0;
5926 continue;
5927 }
5928 for (i = 0; i < n; ++i) {
5929 p[index] = i;
5930 if (!yield_indexed_values(values, r, p)) {
5931 rb_raise(rb_eRuntimeError, "repeated permute reentered");
5932 }
5933 }
5934 do {
5935 if (index <= 0) return;
5936 } while ((i = ++p[--index]) >= n);
5937 }
5938}
5939
5940static VALUE
5941rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
5942{
5943 long n = RARRAY_LEN(ary);
5944 long k = NUM2LONG(RARRAY_AREF(args, 0));
5945
5946 if (k < 0) {
5947 return LONG2FIX(0);
5948 }
5949 if (n <= 0) {
5950 return LONG2FIX(!k);
5951 }
5952 return rb_int_positive_pow(n, (unsigned long)k);
5953}
5954
5955/*
5956 * call-seq:
5957 * ary.repeated_permutation(n) {|p| block} -> ary
5958 * ary.repeated_permutation(n) -> Enumerator
5959 *
5960 * When invoked with a block, yield all repeated permutations of length +n+ of
5961 * the elements of the array, then return the array itself.
5962 *
5963 * The implementation makes no guarantees about the order in which the repeated
5964 * permutations are yielded.
5965 *
5966 * If no block is given, an Enumerator is returned instead.
5967 *
5968 * Examples:
5969 *
5970 * a = [1, 2]
5971 * a.repeated_permutation(1).to_a #=> [[1], [2]]
5972 * a.repeated_permutation(2).to_a #=> [[1,1],[1,2],[2,1],[2,2]]
5973 * a.repeated_permutation(3).to_a #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2],
5974 * # [2,1,1],[2,1,2],[2,2,1],[2,2,2]]
5975 * a.repeated_permutation(0).to_a #=> [[]] # one permutation of length 0
5976 */
5977
5978static VALUE
5979rb_ary_repeated_permutation(VALUE ary, VALUE num)
5980{
5981 long r, n, i;
5982
5983 n = RARRAY_LEN(ary); /* Array length */
5984 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size); /* Return Enumerator if no block */
5985 r = NUM2LONG(num); /* Permutation size from argument */
5986
5987 if (r < 0) {
5988 /* no permutations: yield nothing */
5989 }
5990 else if (r == 0) { /* exactly one permutation: the zero-length array */
5992 }
5993 else if (r == 1) { /* this is a special, easy case */
5994 for (i = 0; i < RARRAY_LEN(ary); i++) {
5995 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
5996 }
5997 }
5998 else { /* this is the general case */
5999 volatile VALUE t0;
6000 long *p = ALLOCV_N(long, t0, r);
6001 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
6002 RBASIC_CLEAR_CLASS(ary0);
6003
6004 rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
6005 ALLOCV_END(t0);
6007 }
6008 return ary;
6009}
6010
6011static void
6012rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
6013{
6014 long i = 0, index = 0;
6015
6016 p[index] = i;
6017 for (;;) {
6018 if (++index < r-1) {
6019 p[index] = i;
6020 continue;
6021 }
6022 for (; i < n; ++i) {
6023 p[index] = i;
6024 if (!yield_indexed_values(values, r, p)) {
6025 rb_raise(rb_eRuntimeError, "repeated combination reentered");
6026 }
6027 }
6028 do {
6029 if (index <= 0) return;
6030 } while ((i = ++p[--index]) >= n);
6031 }
6032}
6033
6034static VALUE
6035rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
6036{
6037 long n = RARRAY_LEN(ary);
6038 long k = NUM2LONG(RARRAY_AREF(args, 0));
6039 if (k == 0) {
6040 return LONG2FIX(1);
6041 }
6042 return binomial_coefficient(k, n + k - 1);
6043}
6044
6045/*
6046 * call-seq:
6047 * ary.repeated_combination(n) {|c| block} -> ary
6048 * ary.repeated_combination(n) -> Enumerator
6049 *
6050 * When invoked with a block, yields all repeated combinations of length +n+ of
6051 * elements from the array and then returns the array itself.
6052 *
6053 * The implementation makes no guarantees about the order in which the repeated
6054 * combinations are yielded.
6055 *
6056 * If no block is given, an Enumerator is returned instead.
6057 *
6058 * Examples:
6059 *
6060 * a = [1, 2, 3]
6061 * a.repeated_combination(1).to_a #=> [[1], [2], [3]]
6062 * a.repeated_combination(2).to_a #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
6063 * a.repeated_combination(3).to_a #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],
6064 * # [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]
6065 * a.repeated_combination(4).to_a #=> [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3],
6066 * # [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3],
6067 * # [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]]
6068 * a.repeated_combination(0).to_a #=> [[]] # one combination of length 0
6069 *
6070 */
6071
6072static VALUE
6073rb_ary_repeated_combination(VALUE ary, VALUE num)
6074{
6075 long n, i, len;
6076
6077 n = NUM2LONG(num); /* Combination size from argument */
6078 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size); /* Return enumerator if no block */
6079 len = RARRAY_LEN(ary);
6080 if (n < 0) {
6081 /* yield nothing */
6082 }
6083 else if (n == 0) {
6085 }
6086 else if (n == 1) {
6087 for (i = 0; i < RARRAY_LEN(ary); i++) {
6088 rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
6089 }
6090 }
6091 else if (len == 0) {
6092 /* yield nothing */
6093 }
6094 else {
6095 volatile VALUE t0;
6096 long *p = ALLOCV_N(long, t0, n);
6097 VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
6098 RBASIC_CLEAR_CLASS(ary0);
6099
6100 rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
6101 ALLOCV_END(t0);
6103 }
6104 return ary;
6105}
6106
6107/*
6108 * call-seq:
6109 * ary.product(other_ary, ...) -> new_ary
6110 * ary.product(other_ary, ...) {|p| block} -> ary
6111 *
6112 * Returns an array of all combinations of elements from all arrays.
6113 *
6114 * The length of the returned array is the product of the length of +self+ and
6115 * the argument arrays.
6116 *
6117 * If given a block, #product will yield all combinations and return +self+
6118 * instead.
6119 *
6120 * [1,2,3].product([4,5]) #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
6121 * [1,2].product([1,2]) #=> [[1,1],[1,2],[2,1],[2,2]]
6122 * [1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
6123 * # [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
6124 * [1,2].product() #=> [[1],[2]]
6125 * [1,2].product([]) #=> []
6126 */
6127
6128static VALUE
6129rb_ary_product(int argc, VALUE *argv, VALUE ary)
6130{
6131 int n = argc+1; /* How many arrays we're operating on */
6132 volatile VALUE t0 = tmpary(n);
6133 volatile VALUE t1 = Qundef;
6134 VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
6135 int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
6136 VALUE result = Qnil; /* The array we'll be returning, when no block given */
6137 long i,j;
6138 long resultlen = 1;
6139
6141
6142 /* initialize the arrays of arrays */
6143 ARY_SET_LEN(t0, n);
6144 arrays[0] = ary;
6145 for (i = 1; i < n; i++) arrays[i] = Qnil;
6146 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
6147
6148 /* initialize the counters for the arrays */
6149 for (i = 0; i < n; i++) counters[i] = 0;
6150
6151 /* Otherwise, allocate and fill in an array of results */
6152 if (rb_block_given_p()) {
6153 /* Make defensive copies of arrays; exit if any is empty */
6154 for (i = 0; i < n; i++) {
6155 if (RARRAY_LEN(arrays[i]) == 0) goto done;
6156 arrays[i] = ary_make_shared_copy(arrays[i]);
6157 }
6158 }
6159 else {
6160 /* Compute the length of the result array; return [] if any is empty */
6161 for (i = 0; i < n; i++) {
6162 long k = RARRAY_LEN(arrays[i]);
6163 if (k == 0) {
6164 result = rb_ary_new2(0);
6165 goto done;
6166 }
6167 if (MUL_OVERFLOW_LONG_P(resultlen, k))
6168 rb_raise(rb_eRangeError, "too big to product");
6169 resultlen *= k;
6170 }
6171 result = rb_ary_new2(resultlen);
6172 }
6173 for (;;) {
6174 int m;
6175 /* fill in one subarray */
6176 VALUE subarray = rb_ary_new2(n);
6177 for (j = 0; j < n; j++) {
6178 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
6179 }
6180
6181 /* put it on the result array */
6182 if (NIL_P(result)) {
6183 FL_SET(t0, FL_USER5);
6184 rb_yield(subarray);
6185 if (! FL_TEST(t0, FL_USER5)) {
6186 rb_raise(rb_eRuntimeError, "product reentered");
6187 }
6188 else {
6189 FL_UNSET(t0, FL_USER5);
6190 }
6191 }
6192 else {
6193 rb_ary_push(result, subarray);
6194 }
6195
6196 /*
6197 * Increment the last counter. If it overflows, reset to 0
6198 * and increment the one before it.
6199 */
6200 m = n-1;
6201 counters[m]++;
6202 while (counters[m] == RARRAY_LEN(arrays[m])) {
6203 counters[m] = 0;
6204 /* If the first counter overflows, we are done */
6205 if (--m < 0) goto done;
6206 counters[m]++;
6207 }
6208 }
6209done:
6210 tmpary_discard(t0);
6211 ALLOCV_END(t1);
6212
6213 return NIL_P(result) ? ary : result;
6214}
6215
6216/*
6217 * call-seq:
6218 * ary.take(n) -> new_ary
6219 *
6220 * Returns first +n+ elements from the array.
6221 *
6222 * If a negative number is given, raises an ArgumentError.
6223 *
6224 * See also Array#drop
6225 *
6226 * a = [1, 2, 3, 4, 5, 0]
6227 * a.take(3) #=> [1, 2, 3]
6228 *
6229 */
6230
6231static VALUE
6232rb_ary_take(VALUE obj, VALUE n)
6233{
6234 long len = NUM2LONG(n);
6235 if (len < 0) {
6236 rb_raise(rb_eArgError, "attempt to take negative size");
6237 }
6238 return rb_ary_subseq(obj, 0, len);
6239}
6240
6241/*
6242 * call-seq:
6243 * ary.take_while {|obj| block} -> new_ary
6244 * ary.take_while -> Enumerator
6245 *
6246 * Passes elements to the block until the block returns +nil+ or +false+, then
6247 * stops iterating and returns an array of all prior elements.
6248 *
6249 * If no block is given, an Enumerator is returned instead.
6250 *
6251 * See also Array#drop_while
6252 *
6253 * a = [1, 2, 3, 4, 5, 0]
6254 * a.take_while {|i| i < 3} #=> [1, 2]
6255 *
6256 */
6257
6258static VALUE
6259rb_ary_take_while(VALUE ary)
6260{
6261 long i;
6262
6263 RETURN_ENUMERATOR(ary, 0, 0);
6264 for (i = 0; i < RARRAY_LEN(ary); i++) {
6265 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
6266 }
6267 return rb_ary_take(ary, LONG2FIX(i));
6268}
6269
6270/*
6271 * call-seq:
6272 * ary.drop(n) -> new_ary
6273 *
6274 * Drops first +n+ elements from +ary+ and returns the rest of the elements in
6275 * an array.
6276 *
6277 * If a negative number is given, raises an ArgumentError.
6278 *
6279 * See also Array#take
6280 *
6281 * a = [1, 2, 3, 4, 5, 0]
6282 * a.drop(3) #=> [4, 5, 0]
6283 *
6284 */
6285
6286static VALUE
6287rb_ary_drop(VALUE ary, VALUE n)
6288{
6289 VALUE result;
6290 long pos = NUM2LONG(n);
6291 if (pos < 0) {
6292 rb_raise(rb_eArgError, "attempt to drop negative size");
6293 }
6294
6295 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
6296 if (result == Qnil) result = rb_ary_new();
6297 return result;
6298}
6299
6300/*
6301 * call-seq:
6302 * ary.drop_while {|obj| block} -> new_ary
6303 * ary.drop_while -> Enumerator
6304 *
6305 * Drops elements up to, but not including, the first element for which the
6306 * block returns +nil+ or +false+ and returns an array containing the
6307 * remaining elements.
6308 *
6309 * If no block is given, an Enumerator is returned instead.
6310 *
6311 * See also Array#take_while
6312 *
6313 * a = [1, 2, 3, 4, 5, 0]
6314 * a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
6315 *
6316 */
6317
6318static VALUE
6319rb_ary_drop_while(VALUE ary)
6320{
6321 long i;
6322
6323 RETURN_ENUMERATOR(ary, 0, 0);
6324 for (i = 0; i < RARRAY_LEN(ary); i++) {
6325 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
6326 }
6327 return rb_ary_drop(ary, LONG2FIX(i));
6328}
6329
6330/*
6331 * call-seq:
6332 * ary.any? [{|obj| block} ] -> true or false
6333 * ary.any?(pattern) -> true or false
6334 *
6335 * See also Enumerable#any?
6336 */
6337
6338static VALUE
6339rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
6340{
6341 long i, len = RARRAY_LEN(ary);
6342
6343 rb_check_arity(argc, 0, 1);
6344 if (!len) return Qfalse;
6345 if (argc) {
6346 if (rb_block_given_p()) {
6347 rb_warn("given block not used");
6348 }
6349 for (i = 0; i < RARRAY_LEN(ary); ++i) {
6350 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
6351 }
6352 }
6353 else if (!rb_block_given_p()) {
6354 for (i = 0; i < len; ++i) {
6355 if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
6356 }
6357 }
6358 else {
6359 for (i = 0; i < RARRAY_LEN(ary); ++i) {
6360 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
6361 }
6362 }
6363 return Qfalse;
6364}
6365
6366/*
6367 * call-seq:
6368 * ary.all? [{|obj| block} ] -> true or false
6369 * ary.all?(pattern) -> true or false
6370 *
6371 * See also Enumerable#all?
6372 */
6373
6374static VALUE
6375rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
6376{
6377 long i, len = RARRAY_LEN(ary);
6378
6379 rb_check_arity(argc, 0, 1);
6380 if (!len) return Qtrue;
6381 if (argc) {
6382 if (rb_block_given_p()) {
6383 rb_warn("given block not used");
6384 }
6385 for (i = 0; i < RARRAY_LEN(ary); ++i) {
6386 if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
6387 }
6388 }
6389 else if (!rb_block_given_p()) {
6390 for (i = 0; i < len; ++i) {
6391 if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
6392 }
6393 }
6394 else {
6395 for (i = 0; i < RARRAY_LEN(ary); ++i) {
6396 if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
6397 }
6398 }
6399 return Qtrue;
6400}
6401
6402/*
6403 * call-seq:
6404 * ary.none? [{|obj| block} ] -> true or false
6405 * ary.none?(pattern) -> true or false
6406 *
6407 * See also Enumerable#none?
6408 */
6409
6410static VALUE
6411rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
6412{
6413 long i, len = RARRAY_LEN(ary);
6414
6415 rb_check_arity(argc, 0, 1);
6416 if (!len) return Qtrue;
6417 if (argc) {
6418 if (rb_block_given_p()) {
6419 rb_warn("given block not used");
6420 }
6421 for (i = 0; i < RARRAY_LEN(ary); ++i) {
6422 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
6423 }
6424 }
6425 else if (!rb_block_given_p()) {
6426 for (i = 0; i < len; ++i) {
6427 if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
6428 }
6429 }
6430 else {
6431 for (i = 0; i < RARRAY_LEN(ary); ++i) {
6432 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
6433 }
6434 }
6435 return Qtrue;
6436}
6437
6438/*
6439 * call-seq:
6440 * ary.one? [{|obj| block} ] -> true or false
6441 * ary.one?(pattern) -> true or false
6442 *
6443 * See also Enumerable#one?
6444 */
6445
6446static VALUE
6447rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
6448{
6449 long i, len = RARRAY_LEN(ary);
6450 VALUE result = Qfalse;
6451
6452 rb_check_arity(argc, 0, 1);
6453 if (!len) return Qfalse;
6454 if (argc) {
6455 if (rb_block_given_p()) {
6456 rb_warn("given block not used");
6457 }
6458 for (i = 0; i < RARRAY_LEN(ary); ++i) {
6459 if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
6460 if (result) return Qfalse;
6461 result = Qtrue;
6462 }
6463 }
6464 }
6465 else if (!rb_block_given_p()) {
6466 for (i = 0; i < len; ++i) {
6467 if (RTEST(RARRAY_AREF(ary, i))) {
6468 if (result) return Qfalse;
6469 result = Qtrue;
6470 }
6471 }
6472 }
6473 else {
6474 for (i = 0; i < RARRAY_LEN(ary); ++i) {
6475 if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
6476 if (result) return Qfalse;
6477 result = Qtrue;
6478 }
6479 }
6480 }
6481 return result;
6482}
6483
6484/*
6485 * call-seq:
6486 * ary.dig(idx, ...) -> object
6487 *
6488 * Extracts the nested value specified by the sequence of <i>idx</i>
6489 * objects by calling +dig+ at each step, returning +nil+ if any
6490 * intermediate step is +nil+.
6491 *
6492 * a = [[1, [2, 3]]]
6493 *
6494 * a.dig(0, 1, 1) #=> 3
6495 * a.dig(1, 2, 3) #=> nil
6496 * a.dig(0, 0, 0) #=> TypeError: Integer does not have #dig method
6497 * [42, {foo: :bar}].dig(1, :foo) #=> :bar
6498 */
6499
6500static VALUE
6501rb_ary_dig(int argc, VALUE *argv, VALUE self)
6502{
6504 self = rb_ary_at(self, *argv);
6505 if (!--argc) return self;
6506 ++argv;
6507 return rb_obj_dig(argc, argv, self, Qnil);
6508}
6509
6510static inline VALUE
6511finish_exact_sum(long n, VALUE r, VALUE v, int z)
6512{
6513 if (n != 0)
6514 v = rb_fix_plus(LONG2FIX(n), v);
6515 if (r != Qundef) {
6516 /* r can be an Integer when mathn is loaded */
6517 if (FIXNUM_P(r))
6518 v = rb_fix_plus(r, v);
6519 else if (RB_TYPE_P(r, T_BIGNUM))
6520 v = rb_big_plus(r, v);
6521 else
6522 v = rb_rational_plus(r, v);
6523 }
6524 else if (!n && z) {
6525 v = rb_fix_plus(LONG2FIX(0), v);
6526 }
6527 return v;
6528}
6529
6530/*
6531 * call-seq:
6532 * ary.sum(init=0) -> number
6533 * ary.sum(init=0) {|e| expr } -> number
6534 *
6535 * Returns the sum of elements.
6536 * For example, [e1, e2, e3].sum returns init + e1 + e2 + e3.
6537 *
6538 * If a block is given, the block is applied to each element
6539 * before addition.
6540 *
6541 * If <i>ary</i> is empty, it returns <i>init</i>.
6542 *
6543 * [].sum #=> 0
6544 * [].sum(0.0) #=> 0.0
6545 * [1, 2, 3].sum #=> 6
6546 * [3, 5.5].sum #=> 8.5
6547 * [2.5, 3.0].sum(0.0) {|e| e * e } #=> 15.25
6548 * [Object.new].sum #=> TypeError
6549 *
6550 * The (arithmetic) mean value of an array can be obtained as follows.
6551 *
6552 * mean = ary.sum(0.0) / ary.length
6553 *
6554 * This method can be used for non-numeric objects by
6555 * explicit <i>init</i> argument.
6556 *
6557 * ["a", "b", "c"].sum("") #=> "abc"
6558 * [[1], [[2]], [3]].sum([]) #=> [1, [2], 3]
6559 *
6560 * However, Array#join and Array#flatten is faster than Array#sum for
6561 * array of strings and array of arrays.
6562 *
6563 * ["a", "b", "c"].join #=> "abc"
6564 * [[1], [[2]], [3]].flatten(1) #=> [1, [2], 3]
6565 *
6566 *
6567 * Array#sum method may not respect method redefinition of "+" methods
6568 * such as Integer#+.
6569 *
6570 */
6571
6572static VALUE
6573rb_ary_sum(int argc, VALUE *argv, VALUE ary)
6574{
6575 VALUE e, v, r;
6576 long i, n;
6577 int block_given;
6578
6579 v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));
6580
6581 block_given = rb_block_given_p();
6582
6583 if (RARRAY_LEN(ary) == 0)
6584 return v;
6585
6586 n = 0;
6587 r = Qundef;
6588 for (i = 0; i < RARRAY_LEN(ary); i++) {
6589 e = RARRAY_AREF(ary, i);
6590 if (block_given)
6591 e = rb_yield(e);
6592 if (FIXNUM_P(e)) {
6593 n += FIX2LONG(e); /* should not overflow long type */
6594 if (!FIXABLE(n)) {
6595 v = rb_big_plus(LONG2NUM(n), v);
6596 n = 0;
6597 }
6598 }
6599 else if (RB_TYPE_P(e, T_BIGNUM))
6600 v = rb_big_plus(e, v);
6601 else if (RB_TYPE_P(e, T_RATIONAL)) {
6602 if (r == Qundef)
6603 r = e;
6604 else
6605 r = rb_rational_plus(r, e);
6606 }
6607 else
6608 goto not_exact;
6609 }
6610 v = finish_exact_sum(n, r, v, argc!=0);
6611 return v;
6612
6613 not_exact:
6614 v = finish_exact_sum(n, r, v, i!=0);
6615
6616 if (RB_FLOAT_TYPE_P(e)) {
6617 /*
6618 * Kahan-Babuska balancing compensated summation algorithm
6619 * See http://link.springer.com/article/10.1007/s00607-005-0139-x
6620 */
6621 double f, c;
6622 double x, t;
6623
6624 f = NUM2DBL(v);
6625 c = 0.0;
6626 goto has_float_value;
6627 for (; i < RARRAY_LEN(ary); i++) {
6628 e = RARRAY_AREF(ary, i);
6629 if (block_given)
6630 e = rb_yield(e);
6631 if (RB_FLOAT_TYPE_P(e))
6632 has_float_value:
6633 x = RFLOAT_VALUE(e);
6634 else if (FIXNUM_P(e))
6635 x = FIX2LONG(e);
6636 else if (RB_TYPE_P(e, T_BIGNUM))
6637 x = rb_big2dbl(e);
6638 else if (RB_TYPE_P(e, T_RATIONAL))
6639 x = rb_num2dbl(e);
6640 else
6641 goto not_float;
6642
6643 if (isnan(f)) continue;
6644 if (isnan(x)) {
6645 f = x;
6646 continue;
6647 }
6648 if (isinf(x)) {
6649 if (isinf(f) && signbit(x) != signbit(f))
6650 f = NAN;
6651 else
6652 f = x;
6653 continue;
6654 }
6655 if (isinf(f)) continue;
6656
6657 t = f + x;
6658 if (fabs(f) >= fabs(x))
6659 c += ((f - t) + x);
6660 else
6661 c += ((x - t) + f);
6662 f = t;
6663 }
6664 f += c;
6665 return DBL2NUM(f);
6666
6667 not_float:
6668 v = DBL2NUM(f);
6669 }
6670
6671 goto has_some_value;
6672 for (; i < RARRAY_LEN(ary); i++) {
6673 e = RARRAY_AREF(ary, i);
6674 if (block_given)
6675 e = rb_yield(e);
6676 has_some_value:
6677 v = rb_funcall(v, idPLUS, 1, e);
6678 }
6679 return v;
6680}
6681
6682static VALUE
6683rb_ary_deconstruct(VALUE ary)
6684{
6685 return ary;
6686}
6687
6688/*
6689 * Arrays are ordered, integer-indexed collections of any object.
6690 *
6691 * Array indexing starts at 0, as in C or Java. A negative index is assumed
6692 * to be relative to the end of the array---that is, an index of -1 indicates
6693 * the last element of the array, -2 is the next to last element in the
6694 * array, and so on.
6695 *
6696 * == Creating Arrays
6697 *
6698 * A new array can be created by using the literal constructor
6699 * <code>[]</code>. Arrays can contain different types of objects. For
6700 * example, the array below contains an Integer, a String and a Float:
6701 *
6702 * ary = [1, "two", 3.0] #=> [1, "two", 3.0]
6703 *
6704 * An array can also be created by explicitly calling Array.new with zero, one
6705 * (the initial size of the Array) or two arguments (the initial size and a
6706 * default object).
6707 *
6708 * ary = Array.new #=> []
6709 * Array.new(3) #=> [nil, nil, nil]
6710 * Array.new(3, true) #=> [true, true, true]
6711 *
6712 * Note that the second argument populates the array with references to the
6713 * same object. Therefore, it is only recommended in cases when you need to
6714 * instantiate arrays with natively immutable objects such as Symbols,
6715 * numbers, true or false.
6716 *
6717 * To create an array with separate objects a block can be passed instead.
6718 * This method is safe to use with mutable objects such as hashes, strings or
6719 * other arrays:
6720 *
6721 * Array.new(4) {Hash.new} #=> [{}, {}, {}, {}]
6722 * Array.new(4) {|i| i.to_s } #=> ["0", "1", "2", "3"]
6723 *
6724 * This is also a quick way to build up multi-dimensional arrays:
6725 *
6726 * empty_table = Array.new(3) {Array.new(3)}
6727 * #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
6728 *
6729 * An array can also be created by using the Array() method, provided by
6730 * Kernel, which tries to call #to_ary, then #to_a on its argument.
6731 *
6732 * Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
6733 *
6734 * == Example Usage
6735 *
6736 * In addition to the methods it mixes in through the Enumerable module, the
6737 * Array class has proprietary methods for accessing, searching and otherwise
6738 * manipulating arrays.
6739 *
6740 * Some of the more common ones are illustrated below.
6741 *
6742 * == Accessing Elements
6743 *
6744 * Elements in an array can be retrieved using the Array#[] method. It can
6745 * take a single integer argument (a numeric index), a pair of arguments
6746 * (start and length) or a range. Negative indices start counting from the end,
6747 * with -1 being the last element.
6748 *
6749 * arr = [1, 2, 3, 4, 5, 6]
6750 * arr[2] #=> 3
6751 * arr[100] #=> nil
6752 * arr[-3] #=> 4
6753 * arr[2, 3] #=> [3, 4, 5]
6754 * arr[1..4] #=> [2, 3, 4, 5]
6755 * arr[1..-3] #=> [2, 3, 4]
6756 *
6757 * Another way to access a particular array element is by using the #at method
6758 *
6759 * arr.at(0) #=> 1
6760 *
6761 * The #slice method works in an identical manner to Array#[].
6762 *
6763 * To raise an error for indices outside of the array bounds or else to
6764 * provide a default value when that happens, you can use #fetch.
6765 *
6766 * arr = ['a', 'b', 'c', 'd', 'e', 'f']
6767 * arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
6768 * arr.fetch(100, "oops") #=> "oops"
6769 *
6770 * The special methods #first and #last will return the first and last
6771 * elements of an array, respectively.
6772 *
6773 * arr.first #=> 1
6774 * arr.last #=> 6
6775 *
6776 * To return the first +n+ elements of an array, use #take
6777 *
6778 * arr.take(3) #=> [1, 2, 3]
6779 *
6780 * #drop does the opposite of #take, by returning the elements after +n+
6781 * elements have been dropped:
6782 *
6783 * arr.drop(3) #=> [4, 5, 6]
6784 *
6785 * == Obtaining Information about an Array
6786 *
6787 * Arrays keep track of their own length at all times. To query an array
6788 * about the number of elements it contains, use #length, #count or #size.
6789 *
6790 * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
6791 * browsers.length #=> 5
6792 * browsers.count #=> 5
6793 *
6794 * To check whether an array contains any elements at all
6795 *
6796 * browsers.empty? #=> false
6797 *
6798 * To check whether a particular item is included in the array
6799 *
6800 * browsers.include?('Konqueror') #=> false
6801 *
6802 * == Adding Items to Arrays
6803 *
6804 * Items can be added to the end of an array by using either #push or #<<
6805 *
6806 * arr = [1, 2, 3, 4]
6807 * arr.push(5) #=> [1, 2, 3, 4, 5]
6808 * arr << 6 #=> [1, 2, 3, 4, 5, 6]
6809 *
6810 * #unshift will add a new item to the beginning of an array.
6811 *
6812 * arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
6813 *
6814 * With #insert you can add a new element to an array at any position.
6815 *
6816 * arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
6817 *
6818 * Using the #insert method, you can also insert multiple values at once:
6819 *
6820 * arr.insert(3, 'orange', 'pear', 'grapefruit')
6821 * #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
6822 *
6823 * == Removing Items from an Array
6824 *
6825 * The method #pop removes the last element in an array and returns it:
6826 *
6827 * arr = [1, 2, 3, 4, 5, 6]
6828 * arr.pop #=> 6
6829 * arr #=> [1, 2, 3, 4, 5]
6830 *
6831 * To retrieve and at the same time remove the first item, use #shift:
6832 *
6833 * arr.shift #=> 1
6834 * arr #=> [2, 3, 4, 5]
6835 *
6836 * To delete an element at a particular index:
6837 *
6838 * arr.delete_at(2) #=> 4
6839 * arr #=> [2, 3, 5]
6840 *
6841 * To delete a particular element anywhere in an array, use #delete:
6842 *
6843 * arr = [1, 2, 2, 3]
6844 * arr.delete(2) #=> 2
6845 * arr #=> [1,3]
6846 *
6847 * A useful method if you need to remove +nil+ values from an array is
6848 * #compact:
6849 *
6850 * arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
6851 * arr.compact #=> ['foo', 0, 'bar', 7, 'baz']
6852 * arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
6853 * arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
6854 * arr #=> ['foo', 0, 'bar', 7, 'baz']
6855 *
6856 * Another common need is to remove duplicate elements from an array.
6857 *
6858 * It has the non-destructive #uniq, and destructive method #uniq!
6859 *
6860 * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
6861 * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
6862 *
6863 * == Iterating over Arrays
6864 *
6865 * Like all classes that include the Enumerable module, Array has an each
6866 * method, which defines what elements should be iterated over and how. In
6867 * case of Array's #each, all elements in the Array instance are yielded to
6868 * the supplied block in sequence.
6869 *
6870 * Note that this operation leaves the array unchanged.
6871 *
6872 * arr = [1, 2, 3, 4, 5]
6873 * arr.each {|a| print a -= 10, " "}
6874 * # prints: -9 -8 -7 -6 -5
6875 * #=> [1, 2, 3, 4, 5]
6876 *
6877 * Another sometimes useful iterator is #reverse_each which will iterate over
6878 * the elements in the array in reverse order.
6879 *
6880 * words = %w[first second third fourth fifth sixth]
6881 * str = ""
6882 * words.reverse_each {|word| str += "#{word} "}
6883 * p str #=> "sixth fifth fourth third second first "
6884 *
6885 * The #map method can be used to create a new array based on the original
6886 * array, but with the values modified by the supplied block:
6887 *
6888 * arr.map {|a| 2*a} #=> [2, 4, 6, 8, 10]
6889 * arr #=> [1, 2, 3, 4, 5]
6890 * arr.map! {|a| a**2} #=> [1, 4, 9, 16, 25]
6891 * arr #=> [1, 4, 9, 16, 25]
6892 *
6893 * == Selecting Items from an Array
6894 *
6895 * Elements can be selected from an array according to criteria defined in a
6896 * block. The selection can happen in a destructive or a non-destructive
6897 * manner. While the destructive operations will modify the array they were
6898 * called on, the non-destructive methods usually return a new array with the
6899 * selected elements, but leave the original array unchanged.
6900 *
6901 * === Non-destructive Selection
6902 *
6903 * arr = [1, 2, 3, 4, 5, 6]
6904 * arr.select {|a| a > 3} #=> [4, 5, 6]
6905 * arr.reject {|a| a < 3} #=> [3, 4, 5, 6]
6906 * arr.drop_while {|a| a < 4} #=> [4, 5, 6]
6907 * arr #=> [1, 2, 3, 4, 5, 6]
6908 *
6909 * === Destructive Selection
6910 *
6911 * #select! and #reject! are the corresponding destructive methods to #select
6912 * and #reject
6913 *
6914 * Similar to #select vs. #reject, #delete_if and #keep_if have the exact
6915 * opposite result when supplied with the same block:
6916 *
6917 * arr.delete_if {|a| a < 4} #=> [4, 5, 6]
6918 * arr #=> [4, 5, 6]
6919 *
6920 * arr = [1, 2, 3, 4, 5, 6]
6921 * arr.keep_if {|a| a < 4} #=> [1, 2, 3]
6922 * arr #=> [1, 2, 3]
6923 *
6924 */
6925
6926void
6928{
6929#undef rb_intern
6930#define rb_intern(str) rb_intern_const(str)
6931
6934
6935 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
6936 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
6937 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
6938 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
6939 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
6940
6941 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
6942 rb_define_alias(rb_cArray, "to_s", "inspect");
6943 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
6944 rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
6945 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
6946
6947 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
6948 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
6949 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
6950
6952 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
6954 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
6955 rb_define_method(rb_cArray, "first", rb_ary_first, -1);
6957 rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
6958 rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
6959 rb_define_method(rb_cArray, "difference", rb_ary_difference_multi, -1);
6960 rb_define_method(rb_cArray, "intersection", rb_ary_intersection_multi, -1);
6962 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
6963 rb_define_alias(rb_cArray, "append", "push");
6964 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
6965 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
6966 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
6967 rb_define_alias(rb_cArray, "prepend", "unshift");
6968 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
6970 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
6971 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
6972 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
6973 rb_define_alias(rb_cArray, "size", "length");
6974 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
6975 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
6976 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
6977 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
6978 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
6979 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
6980 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
6981 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
6982 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
6985 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
6986 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
6987 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
6988 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
6989 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
6990 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
6991 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
6992 rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
6993 rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
6994 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
6995 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
6997 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
6998 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
6999 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
7000 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
7001 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
7002 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
7005 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
7008
7009 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
7010 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
7011
7014
7016 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
7017
7018 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
7019 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
7020 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
7021
7022 rb_define_method(rb_cArray, "max", rb_ary_max, -1);
7023 rb_define_method(rb_cArray, "min", rb_ary_min, -1);
7024 rb_define_method(rb_cArray, "minmax", rb_ary_minmax, 0);
7025
7026 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
7027 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
7028 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
7029 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
7030 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
7031 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
7032 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
7033 rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1);
7034 rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1);
7035 rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
7036 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
7037 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
7038 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
7039 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
7040 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
7041 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
7042
7043 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
7044 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
7045 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
7046 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
7047 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
7048 rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
7049 rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
7050 rb_define_method(rb_cArray, "all?", rb_ary_all_p, -1);
7051 rb_define_method(rb_cArray, "none?", rb_ary_none_p, -1);
7052 rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
7053 rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
7054 rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
7055
7056 rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
7057
7058 id_random = rb_intern("random");
7059}
void rb_mem_clear(VALUE *mem, long size)
Definition: array.c:243
VALUE rb_ary_new_from_values(long n, const VALUE *elts)
Definition: array.c:762
#define ARY_OWNS_HEAP_P(a)
Definition: array.c:70
void rb_ary_transient_heap_evacuate(VALUE ary, int promote)
Definition: array.c:402
#define FL_UNSET_EMBED(ary)
Definition: array.c:80
VALUE rb_ary_includes(VALUE ary, VALUE item)
Definition: array.c:4340
#define ary_verify(ary)
Definition: array.c:222
#define FL_SET_SHARED(ary)
Definition: array.c:81
#define ARY_SHARED_ROOT_REFCNT(ary)
Definition: array.c:148
#define ARY_SET_SHARED(ary, value)
Definition: array.c:137
void rb_ary_detransient(VALUE ary)
Definition: array.c:408
#define ARY_SHARED_P(ary)
Definition: array.c:48
VALUE rb_ary_assoc(VALUE ary, VALUE key)
Definition: array.c:4156
RUBY_FUNC_EXPORTED size_t rb_ary_memsize(VALUE ary)
Definition: array.c:816
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1079
#define ARY_EMBED_P(ary)
Definition: array.c:53
VALUE rb_ary_reverse(VALUE ary)
Definition: array.c:2544
#define ARY_INCREASE_PTR(ary, n)
Definition: array.c:112
VALUE rb_cArray
Definition: array.c:27
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:1294
VALUE rb_ary_tmp_new_fill(long capa)
Definition: array.c:776
#define ARY_MAX_SIZE
Definition: array.c:33
VALUE rb_ary_sort(VALUE ary)
Definition: array.c:2866
VALUE rb_to_array_type(VALUE ary)
Definition: array.c:902
#define tmpary_discard(a)
Definition: array.c:5634
VALUE rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE(*func)(VALUE, long))
Definition: array.c:3106
VALUE rb_ary_resurrect(VALUE ary)
Definition: array.c:2251
#define ARY_EMBED_PTR(a)
Definition: array.c:63
#define ARY_HEAP_CAPA(a)
Definition: array.c:60
#define ARY_DEFAULT_SIZE
Definition: array.c:32
void Init_Array(void)
Definition: array.c:6927
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:2238
VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
Definition: array.c:1574
#define to_ary
Definition: array.c:906
MJIT_FUNC_EXPORTED VALUE rb_ary_behead(VALUE ary, long n)
Definition: array.c:1369
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
void rb_ary_free(VALUE ary)
Definition: array.c:786
VALUE rb_ary_freeze(VALUE ary)
Definition: array.c:648
VALUE rb_ary_each(VALUE ary)
Definition: array.c:2129
VALUE rb_ary_last(int argc, const VALUE *argv, VALUE ary)
Definition: array.c:1677
VALUE rb_ary_delete(VALUE ary, VALUE item)
Definition: array.c:3365
VALUE rb_ary_delete_at(VALUE ary, long pos)
Definition: array.c:3419
MJIT_FUNC_EXPORTED VALUE rb_check_to_array(VALUE ary)
Definition: array.c:915
void rb_ary_set_len(VALUE ary, long len)
Definition: array.c:1932
#define tmpary(n)
Definition: array.c:5633
#define ARY_SHARED_ROOT(ary)
Definition: array.c:136
#define ARY_SHARED_ROOT_OCCUPIED(ary)
Definition: array.c:150
#define ARY_HEAP_LEN(a)
Definition: array.c:59
VALUE * rb_ary_ptr_use_start(VALUE ary)
Definition: array.c:226
VALUE rb_ary_unshift(VALUE ary, VALUE item)
Definition: array.c:1494
void rb_ary_modify(VALUE ary)
Definition: array.c:548
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Definition: array.c:3811
#define ARY_SET_SHARED_ROOT_REFCNT(ary, value)
Definition: array.c:151
void rb_ary_ptr_use_end(VALUE ary)
Definition: array.c:235
#define ARY_SET_HEAP_LEN(ary, n)
Definition: array.c:99
VALUE() rb_ary_new_from_args(long n,...)
Definition: array.c:729
#define RARRAY_SHARED_ROOT_FLAG
Definition: array.c:145
VALUE rb_ary_to_ary(VALUE obj)
Definition: array.c:1853
VALUE rb_ary_new(void)
Definition: array.c:723
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:4069
#define ARY_HEAP_PTR(a)
Definition: array.c:58
#define rb_intern(str)
#define ARY_SET_EMBED_LEN(ary, n)
Definition: array.c:92
VALUE rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
Definition: array.c:661
#define ARY_SET_LEN(ary, n)
Definition: array.c:103
VALUE rb_ary_new_capa(long capa)
Definition: array.c:717
#define ARY_HEAP_SIZE(a)
Definition: array.c:68
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:909
VALUE rb_ary_resize(VALUE ary, long len)
expands or shrinks ary to len elements.
Definition: array.c:1955
#define ARY_SHARED_ROOT_P(ary)
Definition: array.c:146
VALUE rb_ary_pop(VALUE ary)
Definition: array.c:1241
#define FL_SET_SHARED_ROOT(ary)
Definition: array.c:155
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:768
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3862
VALUE rb_ary_subseq(VALUE ary, long beg, long len)
Definition: array.c:1518
#define ARY_EMBED_LEN(a)
Definition: array.c:64
VALUE rb_ary_at(VALUE ary, VALUE pos)
Definition: array.c:1629
void rb_ary_delete_same(VALUE ary, VALUE item)
Definition: array.c:3396
#define ARY_CAPA(ary)
Definition: array.c:127
#define FL_UNSET_SHARED(ary)
Definition: array.c:85
#define ARY_SET_CAPA(ary, n)
Definition: array.c:129
MJIT_FUNC_EXPORTED VALUE rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
Definition: array.c:748
VALUE rb_ary_plus(VALUE x, VALUE y)
Definition: array.c:4000
VALUE rb_output_fs
Definition: intern.h:584
VALUE rb_ary_rotate(VALUE ary, long cnt)
Definition: array.c:2617
#define RAND_UPTO(max)
Definition: array.c:5326
VALUE rb_ary_cmp(VALUE ary1, VALUE ary2)
Definition: array.c:4420
#define OPTHASH_GIVEN_P(opts)
Definition: array.c:5322
VALUE rb_ary_to_s(VALUE ary)
Definition: array.c:2453
VALUE rb_ary_cat(VALUE ary, const VALUE *argv, long len)
Definition: array.c:1208
#define FL_SET_EMBED(a)
Definition: array.c:73
#define SMALL_ARRAY_LEN
Definition: array.c:34
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
#define ARY_INCREASE_LEN(ary, n)
Definition: array.c:117
MJIT_FUNC_EXPORTED VALUE rb_ary_aref1(VALUE ary, VALUE arg)
Definition: array.c:1595
ary_take_pos_flags
Definition: array.c:1146
@ ARY_TAKE_FIRST
Definition: array.c:1147
@ ARY_TAKE_LAST
Definition: array.c:1148
VALUE rb_ary_sort_bang(VALUE ary)
Definition: array.c:2777
#define ARY_SET_PTR(ary, p)
Definition: array.c:87
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
#define id_cmp
Definition: array.c:30
VALUE rb_ary_join(VALUE ary, VALUE sep)
Definition: array.c:2347
VALUE rb_ary_rassoc(VALUE ary, VALUE value)
Definition: array.c:4189
#define mul(x, y)
Definition: date_strftime.c:25
#define mod(x, y)
Definition: date_strftime.c:28
#define range(low, item, hi)
Definition: date_strftime.c:21
#define recur(fmt)
struct RIMemo * ptr
Definition: debug.c:65
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:866
void rb_enc_copy(VALUE obj1, VALUE obj2)
Definition: encoding.c:990
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1340
#define rb_cmpint(cmp, a, b)
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
void rb_include_module(VALUE, VALUE)
Definition: class.c:882
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
Definition: class.c:662
void rb_define_alias(VALUE, const char *, const char *)
Defines an alias of a method.
Definition: class.c:1818
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *)
Definition: class.c:1904
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
VALUE rb_cNumeric
Definition: ruby.h:2039
VALUE rb_cRandom
Definition: ruby.h:2041
@ RARRAY_TRANSIENT_FLAG
Definition: ruby.h:1035
@ RARRAY_EMBED_FLAG
Definition: ruby.h:1029
@ RARRAY_EMBED_LEN_MASK
Definition: ruby.h:1031
@ RARRAY_EMBED_LEN_MAX
Definition: ruby.h:1028
VALUE rb_mEnumerable
Definition: enum.c:20
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
void rb_bug(const char *fmt,...)
Definition: error.c:636
VALUE rb_eRangeError
Definition: error.c:928
VALUE rb_eTypeError
Definition: error.c:924
VALUE rb_eRuntimeError
Definition: error.c:922
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_eIndexError
Definition: error.c:926
VALUE rb_ensure(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
Definition: eval.c:1115
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound)
Definition: object.c:3791
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
Definition: object.c:147
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2914
double rb_num2dbl(VALUE)
Converts a Numeric object to double.
Definition: object.c:3616
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2957
unsigned int top
Definition: nkf.c:4323
unsigned int last
Definition: nkf.c:4324
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
#define RARRAY_LEN(a)
void * memchr(const void *, int, size_t)
#define MEMCPY(p1, p2, type, n)
void rb_hash_foreach(VALUE, int(*)(VALUE, VALUE, VALUE), VALUE)
#define NULL
#define RARY_TRANSIENT_SET(ary)
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:5085
#define rb_funcallv(recv, mid, argc, argv)
#define NUM2DBL(x)
#define RBASIC_CLEAR_CLASS(obj)
#define RHASH_ST_CLEAR(h)
VALUE rb_hash(VALUE)
Definition: hash.c:129
#define UNLIMITED_ARGUMENTS
use StringValue() instead")))
#define RSTRING_LEN(str)
VALUE rb_hash_values(VALUE hash)
Definition: hash.c:3456
#define ARY_PTR_USING_P(ary)
#define rb_str_buf_cat2
#define NEWOBJ_OF(obj, type, klass, flags)
#define RTEST(v)
#define ALLOCV_END(v)
double fabs(double)
#define rb_hash_uint(h, i)
#define RHASH_ST_TABLE_P(h)
#define FL_TEST(x, f)
#define bp()
unsigned long st_data_t
#define RBASIC(obj)
VALUE rb_check_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
Definition: vm_eval.c:1528
void rb_hash_st_table_set(VALUE hash, st_table *st)
Definition: hash.c:558
#define T_STRING
#define rb_hash_end(h)
#define rb_yield_values(argc,...)
#define Data_Wrap_Struct(klass, mark, free, sval)
int rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:4547
#define LONG2FIX(i)
#define Qundef
double rb_big2dbl(VALUE)
Definition: bignum.c:5310
VALUE rb_range_beg_len(VALUE, long *, long *, long, int)
Definition: range.c:1278
int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval)
Definition: hash.c:2310
const VALUE VALUE obj
#define rb_check_frozen(obj)
#define FL_SET(x, f)
VALUE rb_rational_plus(VALUE self, VALUE other)
Definition: rational.c:737
#define st_is_member(table, key)
#define T_BIGNUM
#define rb_str_buf_new2
#define STRING_P(s)
int rb_block_arity(void)
Definition: proc.c:1144
#define rb_str_new(str, len)
#define NIL_P(v)
#define numberof(array)
#define DBL2NUM(dbl)
#define signbit(__x)
#define RARRAY_PTR(a)
#define ELTS_SHARED
const char size_t n
#define rb_usascii_str_new(str, len)
#define MEMZERO(p, type, n)
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1438
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2207
unsigned long VALUE
#define rb_ary_new4
__inline__ const void *__restrict__ src
VALUE rb_str_buf_new(long)
Definition: string.c:1315
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
#define RARRAY_ASET(a, i, v)
VALUE rb_int_positive_pow(long x, unsigned long y)
Definition: numeric.c:4038
VALUE rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary)
Definition: enum.c:1568
#define RARRAY(obj)
#define isinf(__x)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define FL_UNSET(x, f)
#define rb_usascii_str_new_cstr(str)
#define RGENGC_WB_PROTECTED_ARRAY
uint32_t i
#define roomof(x, y)
#define RB_FLOAT_TYPE_P(obj)
#define isnan(__x)
__inline__ const void *__restrict__ size_t len
#define OBJ_FROZEN(x)
#define ALLOC_N(type, n)
#define OBJ_FREEZE(x)
#define SIZED_REALLOC_N(var, type, n, old_n)
#define T_RATIONAL
#define RB_OBJ_WRITE(a, slot, b)
#define va_end(v)
VALUE rb_hash_new_with_size(st_index_t size)
Definition: hash.c:1529
#define LONG2NUM(x)
__gnuc_va_list va_list
#define long
#define NUM2INT(x)
void rb_define_singleton_method(VALUE, const char *, VALUE(*)(), int)
#define RB_GC_GUARD(v)
#define NAN
#define RUBY_DTRACE_CREATE_HOOK(name, arg)
#define PRIsVALUE
#define rb_ary_new3
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
#define CMP_OPTIMIZABLE(data, type)
#define rb_funcall(recv, mid, argc,...)
VALUE rb_yield_force_blockarg(VALUE values)
Definition: vm_eval.c:1309
int VALUE v
#define rb_scan_args(argc, argvp, fmt,...)
#define rb_usascii_str_new2
#define va_arg(v, l)
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:1271
#define va_start(v, l)
#define ALLOCV_N(type, v, n)
#define RARY_TRANSIENT_UNSET(ary)
#define RARRAY_PTR_USE(ary, ptr_name, expr)
#define RBASIC_SET_CLASS_RAW(obj, cls)
#define RFLOAT_VALUE(v)
#define RARRAY_CONST_PTR_TRANSIENT(a)
#define TRUE
#define FALSE
#define RHASH_ST_TABLE(hash)
#define RHASH_SIZE(h)
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:3228
unsigned int size
#define Qtrue
#define MEMMOVE(p1, p2, type, n)
#define ruby_sized_xfree(ptr, size)
#define FL_UNSET_RAW(x, f)
int dup(int __fildes)
#define memmove(dst, src, len)
#define MUL_OVERFLOW_LONG_P(a, b)
#define Qnil
#define Qfalse
#define DATA_PTR(dta)
#define T_ARRAY
VALUE rb_str_buf_append(VALUE, VALUE)
Definition: string.c:2950
#define SIGNED_VALUE
st_data_t st_index_t
#define RARRAY_TRANSIENT_P(ary)
#define FIXABLE(f)
#define RB_TYPE_P(obj, type)
#define FL_WB_PROTECTED
#define INT2FIX(i)
void rb_gc_force_recycle(VALUE)
Definition: gc.c:7027
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
#define MJIT_FUNC_EXPORTED
const VALUE * argv
VALUE rb_fix_plus(VALUE x, VALUE y)
Definition: numeric.c:3609
#define FIXNUM_P(f)
int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg)
Definition: hash.c:1651
#define RETURN_ENUMERATOR(obj, argc, argv)
void rb_gc_writebarrier_remember(VALUE obj)
Definition: gc.c:6891
#define RB_OBJ_WB_UNPROTECT_FOR(type, obj)
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
Definition: hash.c:2852
int rb_float_cmp(VALUE x, VALUE y)
Definition: numeric.c:1487
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
Definition: vm_eval.c:1470
#define assert
#define rb_check_arity
VALUE rb_int_idiv(VALUE x, VALUE y)
Definition: numeric.c:3848
#define FL_FREEZE
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5074
#define FL_USER5
#define RBASIC_CLASS(obj)
unsigned long ID
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
const char *void rb_warning(const char *,...) __attribute__((format(printf
size_t st_index_t h
#define RUBY_FUNC_EXPORTED
VALUE ID id
#define FIX2LONG(x)
#define RBASIC_SET_CLASS(obj, cls)
VALUE rb_big_plus(VALUE, VALUE)
Definition: bignum.c:5824
#define NUM2LONG(x)
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define rb_ary_new2
#define RARRAY_AREF(a, i)
#define RUBY_ASSERT_ALWAYS(expr)
#define USE_DEBUG_COUNTER
#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr)
VALUE rb_hash_new(void)
Definition: hash.c:1523
#define HUGE_VAL
#define ST2FIX(h)
#define RB_OBJ_WRITTEN(a, oldv, b)
#define RARRAY_CONST_PTR(a)
int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
Definition: hash.c:2017
#define OPTIMIZED_CMP(a, b, data)
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:306
#define FL_SET_RAW(x, f)
VALUE rb_int_mul(VALUE x, VALUE y)
Definition: numeric.c:3704
#define RB_DEBUG_COUNTER_INC(type)
#define RARRAY_PTR_IN_USE_FLAG
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:503
#define f
void st_free_table(st_table *tab)
Definition: st.c:709
st_table * st_init_numtable_with_size(st_index_t size)
Definition: st.c:660
int st_delete(st_table *tab, st_data_t *key, st_data_t *value)
Definition: st.c:1418
st_table * st_init_numtable(void)
Definition: st.c:653
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
void st_clear(st_table *tab)
Definition: st.c:698
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
Definition: st.c:1101
Definition: ruby.h:1048
struct cmp_opt_data cmp_opt
Definition: array.c:2696
VALUE ary
Definition: array.c:2695
long len[2]
Definition: array.c:3230
void * rb_transient_heap_alloc(VALUE obj, size_t req_size)
int rb_transient_heap_managed_ptr_p(const void *ptr)
void rb_transient_heap_verify(void)
void ruby_qsort(void *, const size_t, const size_t, int(*)(const void *, const void *, void *), void *)
void rb_iter_break(void)
Definition: vm.c:1546