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