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