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