The Ruby Cross Reference

Implementation: mri jruby rubinius
Version: 1.8.7-p370 1.9.1-p431 1.9.2-p381 1.9.3-p362 2.0.0-p0 HEAD
001 /**********************************************************************
002 
003   array.c -
004 
005   $Author$
006   created at: Fri Aug  6 09:46:12 JST 1993
007 
008   Copyright (C) 1993-2007 Yukihiro Matsumoto
009   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
010   Copyright (C) 2000  Information-technology Promotion Agency, Japan
011 
012 **********************************************************************/
013 
014 #include "ruby/ruby.h"
015 #include "ruby/util.h"
016 #include "ruby/st.h"
017 #include "ruby/encoding.h"
018 #include "internal.h"
019 #include "probes.h"
020 #include "id.h"
021 
022 #ifndef ARRAY_DEBUG
023 # define NDEBUG
024 #endif
025 #include <assert.h>
026 
027 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
028 
029 VALUE rb_cArray;
030 
031 static ID id_cmp, id_div, id_power;
032 
033 #define ARY_DEFAULT_SIZE 16
034 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
035 
036 void
037 rb_mem_clear(register VALUE *mem, register long size)
038 {
039     while (size--) {
040         *mem++ = Qnil;
041     }
042 }
043 
044 static inline void
045 memfill(register VALUE *mem, register long size, register VALUE val)
046 {
047     while (size--) {
048         *mem++ = val;
049     }
050 }
051 
052 # define ARY_SHARED_P(ary) \
053     (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
054      FL_TEST((ary),ELTS_SHARED)!=0)
055 # define ARY_EMBED_P(ary) \
056     (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
057      FL_TEST((ary), RARRAY_EMBED_FLAG)!=0)
058 
059 #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
060 #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
061 #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
062 #define ARY_EMBED_LEN(a) \
063     (assert(ARY_EMBED_P(a)), \
064      (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
065          (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
066 
067 #define ARY_OWNS_HEAP_P(a) (!FL_TEST((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
068 #define FL_SET_EMBED(a) do { \
069     assert(!ARY_SHARED_P(a)); \
070     assert(!OBJ_FROZEN(a)); \
071     FL_SET((a), RARRAY_EMBED_FLAG); \
072 } while (0)
073 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
074 #define FL_SET_SHARED(ary) do { \
075     assert(!ARY_EMBED_P(ary)); \
076     FL_SET((ary), ELTS_SHARED); \
077 } while (0)
078 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
079 
080 #define ARY_SET_PTR(ary, p) do { \
081     assert(!ARY_EMBED_P(ary)); \
082     assert(!OBJ_FROZEN(ary)); \
083     RARRAY(ary)->as.heap.ptr = (p); \
084 } while (0)
085 #define ARY_SET_EMBED_LEN(ary, n) do { \
086     long tmp_n = (n); \
087     assert(ARY_EMBED_P(ary)); \
088     assert(!OBJ_FROZEN(ary)); \
089     RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
090     RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
091 } while (0)
092 #define ARY_SET_HEAP_LEN(ary, n) do { \
093     assert(!ARY_EMBED_P(ary)); \
094     RARRAY(ary)->as.heap.len = (n); \
095 } while (0)
096 #define ARY_SET_LEN(ary, n) do { \
097     if (ARY_EMBED_P(ary)) { \
098         ARY_SET_EMBED_LEN((ary), (n)); \
099     } \
100     else { \
101         ARY_SET_HEAP_LEN((ary), (n)); \
102     } \
103     assert(RARRAY_LEN(ary) == (n)); \
104 } while (0)
105 #define ARY_INCREASE_PTR(ary, n) do  { \
106     assert(!ARY_EMBED_P(ary)); \
107     assert(!OBJ_FROZEN(ary)); \
108     RARRAY(ary)->as.heap.ptr += (n); \
109 } while (0)
110 #define ARY_INCREASE_LEN(ary, n) do  { \
111     assert(!OBJ_FROZEN(ary)); \
112     if (ARY_EMBED_P(ary)) { \
113         ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
114     } \
115     else { \
116         RARRAY(ary)->as.heap.len += (n); \
117     } \
118 } while (0)
119 
120 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
121                        ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : RARRAY(ary)->as.heap.aux.capa)
122 #define ARY_SET_CAPA(ary, n) do { \
123     assert(!ARY_EMBED_P(ary)); \
124     assert(!ARY_SHARED_P(ary)); \
125     assert(!OBJ_FROZEN(ary)); \
126     RARRAY(ary)->as.heap.aux.capa = (n); \
127 } while (0)
128 
129 #define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
130 #define ARY_SET_SHARED(ary, value) do { \
131     assert(!ARY_EMBED_P(ary)); \
132     assert(ARY_SHARED_P(ary)); \
133     assert(ARY_SHARED_ROOT_P(value)); \
134     RARRAY(ary)->as.heap.aux.shared = (value); \
135 } while (0)
136 #define RARRAY_SHARED_ROOT_FLAG FL_USER5
137 #define ARY_SHARED_ROOT_P(ary) (FL_TEST((ary), RARRAY_SHARED_ROOT_FLAG))
138 #define ARY_SHARED_NUM(ary) \
139     (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
140 #define ARY_SET_SHARED_NUM(ary, value) do { \
141     assert(ARY_SHARED_ROOT_P(ary)); \
142     RARRAY(ary)->as.heap.aux.capa = (value); \
143 } while (0)
144 #define FL_SET_SHARED_ROOT(ary) do { \
145     assert(!ARY_EMBED_P(ary)); \
146     FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
147 } while (0)
148 
149 static void
150 ary_resize_capa(VALUE ary, long capacity)
151 {
152     assert(RARRAY_LEN(ary) <= capacity);
153     assert(!OBJ_FROZEN(ary));
154     assert(!ARY_SHARED_P(ary));
155     if (capacity > RARRAY_EMBED_LEN_MAX) {
156         if (ARY_EMBED_P(ary)) {
157             long len = ARY_EMBED_LEN(ary);
158             VALUE *ptr = ALLOC_N(VALUE, (capacity));
159             MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
160             FL_UNSET_EMBED(ary);
161             ARY_SET_PTR(ary, ptr);
162             ARY_SET_HEAP_LEN(ary, len);
163         }
164         else {
165             REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, (capacity));
166         }
167         ARY_SET_CAPA(ary, (capacity));
168     }
169     else {
170         if (!ARY_EMBED_P(ary)) {
171             long len = RARRAY_LEN(ary);
172             VALUE *ptr = RARRAY_PTR(ary);
173             if (len > capacity) len = capacity;
174             MEMCPY(RARRAY(ary)->as.ary, ptr, VALUE, len);
175             FL_SET_EMBED(ary);
176             ARY_SET_LEN(ary, len);
177             xfree(ptr);
178         }
179     }
180 }
181 
182 static void
183 ary_double_capa(VALUE ary, long min)
184 {
185     long new_capa = ARY_CAPA(ary) / 2;
186 
187     if (new_capa < ARY_DEFAULT_SIZE) {
188         new_capa = ARY_DEFAULT_SIZE;
189     }
190     if (new_capa >= ARY_MAX_SIZE - min) {
191         new_capa = (ARY_MAX_SIZE - min) / 2;
192     }
193     new_capa += min;
194     ary_resize_capa(ary, new_capa);
195 }
196 
197 static void
198 rb_ary_decrement_share(VALUE shared)
199 {
200     if (shared) {
201         long num = ARY_SHARED_NUM(shared) - 1;
202         if (num == 0) {
203             rb_ary_free(shared);
204             rb_gc_force_recycle(shared);
205         }
206         else if (num > 0) {
207             ARY_SET_SHARED_NUM(shared, num);
208         }
209     }
210 }
211 
212 static void
213 rb_ary_unshare(VALUE ary)
214 {
215     VALUE shared = RARRAY(ary)->as.heap.aux.shared;
216     rb_ary_decrement_share(shared);
217     FL_UNSET_SHARED(ary);
218 }
219 
220 static inline void
221 rb_ary_unshare_safe(VALUE ary)
222 {
223     if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
224         rb_ary_unshare(ary);
225     }
226 }
227 
228 static VALUE
229 rb_ary_increment_share(VALUE shared)
230 {
231     long num = ARY_SHARED_NUM(shared);
232     if (num >= 0) {
233         ARY_SET_SHARED_NUM(shared, num + 1);
234     }
235     return shared;
236 }
237 
238 static void
239 rb_ary_set_shared(VALUE ary, VALUE shared)
240 {
241     rb_ary_increment_share(shared);
242     FL_SET_SHARED(ary);
243     ARY_SET_SHARED(ary, shared);
244 }
245 
246 static inline void
247 rb_ary_modify_check(VALUE ary)
248 {
249     rb_check_frozen(ary);
250     if (!OBJ_UNTRUSTED(ary) && rb_safe_level() >= 4)
251         rb_raise(rb_eSecurityError, "Insecure: can't modify array");
252 }
253 
254 void
255 rb_ary_modify(VALUE ary)
256 {
257     rb_ary_modify_check(ary);
258     if (ARY_SHARED_P(ary)) {
259         long len = RARRAY_LEN(ary);
260         VALUE shared = ARY_SHARED(ary);
261         if (len <= RARRAY_EMBED_LEN_MAX) {
262             VALUE *ptr = ARY_HEAP_PTR(ary);
263             FL_UNSET_SHARED(ary);
264             FL_SET_EMBED(ary);
265             MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len);
266             rb_ary_decrement_share(shared);
267             ARY_SET_EMBED_LEN(ary, len);
268         }
269         else if (ARY_SHARED_NUM(shared) == 1 && len > (RARRAY_LEN(shared)>>1)) {
270             long shift = RARRAY_PTR(ary) - RARRAY_PTR(shared);
271             ARY_SET_PTR(ary, RARRAY_PTR(shared));
272             ARY_SET_CAPA(ary, RARRAY_LEN(shared));
273             MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+shift, VALUE, len);
274             FL_UNSET_SHARED(ary);
275             FL_SET_EMBED(shared);
276             rb_ary_decrement_share(shared);
277         }
278         else {
279             VALUE *ptr = ALLOC_N(VALUE, len);
280             MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len);
281             rb_ary_unshare(ary);
282             ARY_SET_CAPA(ary, len);
283             ARY_SET_PTR(ary, ptr);
284         }
285     }
286 }
287 
288 static void
289 ary_ensure_room_for_push(VALUE ary, long add_len)
290 {
291     long new_len = RARRAY_LEN(ary) + add_len;
292     long capa;
293 
294     if (ARY_SHARED_P(ary)) {
295         if (new_len > RARRAY_EMBED_LEN_MAX) {
296             VALUE shared = ARY_SHARED(ary);
297             if (ARY_SHARED_NUM(shared) == 1) {
298                 if (RARRAY_PTR(ary) - RARRAY_PTR(shared) + new_len <= RARRAY_LEN(shared)) {
299                     rb_ary_modify_check(ary);
300                 }
301                 else {
302                     /* if array is shared, then it is likely it participate in push/shift pattern */
303                     rb_ary_modify(ary);
304                     capa = ARY_CAPA(ary);
305                     if (new_len > capa - (capa >> 6)) {
306                         ary_double_capa(ary, new_len);
307                     }
308                 }
309                 return;
310             }
311         }
312     }
313     rb_ary_modify(ary);
314     capa = ARY_CAPA(ary);
315     if (new_len > capa) {
316         ary_double_capa(ary, new_len);
317     }
318 }
319 
320 /*
321  *  call-seq:
322  *      ary.freeze -> ary
323  *
324  *  Calls Object#freeze on +ary+ to prevent any further
325  *  modification. A RuntimeError will be raised if a modification
326  *  attempt is made.
327  *
328  */
329 
330 VALUE
331 rb_ary_freeze(VALUE ary)
332 {
333     return rb_obj_freeze(ary);
334 }
335 
336 /*
337  *  call-seq:
338  *     ary.frozen?  -> true or false
339  *
340  *  Return +true+ if this array is frozen (or temporarily frozen
341  *  while being sorted). See also Object#frozen?
342  */
343 
344 static VALUE
345 rb_ary_frozen_p(VALUE ary)
346 {
347     if (OBJ_FROZEN(ary)) return Qtrue;
348     return Qfalse;
349 }
350 
351 /* This can be used to take a snapshot of an array (with
352    e.g. rb_ary_replace) and check later whether the array has been
353    modified from the snapshot.  The snapshot is cheap, though if
354    something does modify the array it will pay the cost of copying
355    it.  If Array#pop or Array#shift has been called, the array will
356    be still shared with the snapshot, but the array length will
357    differ. */
358 VALUE
359 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
360 {
361     if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
362         !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
363         RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared &&
364         RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
365         return Qtrue;
366     }
367     return Qfalse;
368 }
369 
370 static VALUE
371 ary_alloc(VALUE klass)
372 {
373     NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY);
374     FL_SET_EMBED((VALUE)ary);
375     ARY_SET_EMBED_LEN((VALUE)ary, 0);
376 
377     return (VALUE)ary;
378 }
379 
380 static VALUE
381 empty_ary_alloc(VALUE klass)
382 {
383     if (RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
384         RUBY_DTRACE_ARRAY_CREATE(0, rb_sourcefile(), rb_sourceline());
385     }
386 
387     return ary_alloc(klass);
388 }
389 
390 static VALUE
391 ary_new(VALUE klass, long capa)
392 {
393     VALUE ary;
394 
395     if (capa < 0) {
396         rb_raise(rb_eArgError, "negative array size (or size too big)");
397     }
398     if (capa > ARY_MAX_SIZE) {
399         rb_raise(rb_eArgError, "array size too big");
400     }
401 
402     if (RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
403         RUBY_DTRACE_ARRAY_CREATE(capa, rb_sourcefile(), rb_sourceline());
404     }
405 
406     ary = ary_alloc(klass);
407     if (capa > RARRAY_EMBED_LEN_MAX) {
408         FL_UNSET_EMBED(ary);
409         ARY_SET_PTR(ary, ALLOC_N(VALUE, capa));
410         ARY_SET_CAPA(ary, capa);
411         ARY_SET_HEAP_LEN(ary, 0);
412     }
413 
414     return ary;
415 }
416 
417 VALUE
418 rb_ary_new2(long capa)
419 {
420     return ary_new(rb_cArray, capa);
421 }
422 
423 
424 VALUE
425 rb_ary_new(void)
426 {
427     return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
428 }
429 
430 #include <stdarg.h>
431 
432 VALUE
433 rb_ary_new3(long n, ...)
434 {
435     va_list ar;
436     VALUE ary;
437     long i;
438 
439     ary = rb_ary_new2(n);
440 
441     va_start(ar, n);
442     for (i=0; i<n; i++) {
443         RARRAY_PTR(ary)[i] = va_arg(ar, VALUE);
444     }
445     va_end(ar);
446 
447     ARY_SET_LEN(ary, n);
448     return ary;
449 }
450 
451 VALUE
452 rb_ary_new4(long n, const VALUE *elts)
453 {
454     VALUE ary;
455 
456     ary = rb_ary_new2(n);
457     if (n > 0 && elts) {
458         MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
459         ARY_SET_LEN(ary, n);
460     }
461 
462     return ary;
463 }
464 
465 VALUE
466 rb_ary_tmp_new(long capa)
467 {
468     return ary_new(0, capa);
469 }
470 
471 void
472 rb_ary_free(VALUE ary)
473 {
474     if (ARY_OWNS_HEAP_P(ary)) {
475         xfree(ARY_HEAP_PTR(ary));
476     }
477 }
478 
479 RUBY_FUNC_EXPORTED size_t
480 rb_ary_memsize(VALUE ary)
481 {
482     if (ARY_OWNS_HEAP_P(ary)) {
483         return RARRAY(ary)->as.heap.aux.capa * sizeof(VALUE);
484     }
485     else {
486         return 0;
487     }
488 }
489 
490 static inline void
491 ary_discard(VALUE ary)
492 {
493     rb_ary_free(ary);
494     RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
495     RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK;
496 }
497 
498 static VALUE
499 ary_make_shared(VALUE ary)
500 {
501     assert(!ARY_EMBED_P(ary));
502     if (ARY_SHARED_P(ary)) {
503         return ARY_SHARED(ary);
504     }
505     else if (ARY_SHARED_ROOT_P(ary)) {
506         return ary;
507     }
508     else if (OBJ_FROZEN(ary)) {
509         ary_resize_capa(ary, ARY_HEAP_LEN(ary));
510         FL_SET_SHARED_ROOT(ary);
511         ARY_SET_SHARED_NUM(ary, 1);
512         return ary;
513     }
514     else {
515         NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY);
516         FL_UNSET_EMBED(shared);
517 
518         ARY_SET_LEN((VALUE)shared, ARY_CAPA(ary));
519         ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary));
520         rb_mem_clear(RARRAY_PTR(shared) + RARRAY_LEN(ary), ARY_CAPA(ary) - RARRAY_LEN(ary));
521         FL_SET_SHARED_ROOT(shared);
522         ARY_SET_SHARED_NUM((VALUE)shared, 1);
523         FL_SET_SHARED(ary);
524         ARY_SET_SHARED(ary, (VALUE)shared);
525         OBJ_FREEZE(shared);
526         return (VALUE)shared;
527     }
528 }
529 
530 
531 static VALUE
532 ary_make_substitution(VALUE ary)
533 {
534     if (RARRAY_LEN(ary) <= RARRAY_EMBED_LEN_MAX) {
535         VALUE subst = rb_ary_new2(RARRAY_LEN(ary));
536         MEMCPY(ARY_EMBED_PTR(subst), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
537         ARY_SET_EMBED_LEN(subst, RARRAY_LEN(ary));
538         return subst;
539     }
540     else {
541         return rb_ary_increment_share(ary_make_shared(ary));
542     }
543 }
544 
545 VALUE
546 rb_assoc_new(VALUE car, VALUE cdr)
547 {
548     return rb_ary_new3(2, car, cdr);
549 }
550 
551 static VALUE
552 to_ary(VALUE ary)
553 {
554     return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
555 }
556 
557 VALUE
558 rb_check_array_type(VALUE ary)
559 {
560     return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
561 }
562 
563 /*
564  *  call-seq:
565  *     Array.try_convert(obj) -> array or nil
566  *
567  *  Tries to convert +obj+ into an array, using +to_ary+ method.  Returns the
568  *  converted array or +nil+ if +obj+ cannot be converted for any reason.
569  *  This method can be used to check if an argument is an array.
570  *
571  *     Array.try_convert([1])   #=> [1]
572  *     Array.try_convert("1")   #=> nil
573  *
574  *     if tmp = Array.try_convert(arg)
575  *       # the argument is an array
576  *     elsif tmp = String.try_convert(arg)
577  *       # the argument is a string
578  *     end
579  *
580  */
581 
582 static VALUE
583 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
584 {
585     return rb_check_array_type(ary);
586 }
587 
588 /*
589  *  call-seq:
590  *     Array.new(size=0, obj=nil)
591  *     Array.new(array)
592  *     Array.new(size) {|index| block }
593  *
594  *  Returns a new array.
595  *
596  *  In the first form, if no arguments are sent, the new array will be empty.
597  *  When a +size+ and an optional +obj+ are sent, an array is created with
598  *  +size+ copies of +obj+.  Take notice that all elements will reference the
599  *  same object +obj+.
600  *
601  *  The second form creates a copy of the array passed as a parameter (the
602  *  array is generated by calling to_ary on the parameter).
603  *
604  *    first_array = ["Matz", "Guido"]
605  *
606  *    second_array = Array.new(first_array) #=> ["Matz", "Guido"]
607  *
608  *    first_array.equal? second_array       #=> false
609  *
610  *  In the last form, an array of the given size is created.  Each element in
611  *  this array is created by passing the element's index to the given block
612  *  and storing the return value.
613  *
614  *    Array.new(3){ |index| index ** 2 }
615  *    # => [0, 1, 4]
616  *
617  *  == Common gotchas
618  *
619  *  When sending the second parameter, the same object will be used as the
620  *  value for all the array elements:
621  *
622  *     a = Array.new(2, Hash.new)
623  *     # => [{}, {}]
624  *
625  *     a[0]['cat'] = 'feline'
626  *     a # => [{"cat"=>"feline"}, {"cat"=>"feline"}]
627  *
628  *     a[1]['cat'] = 'Felix'
629  *     a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]
630  *
631  *  Since all the Array elements store the same hash, changes to one of them
632  *  will affect them all.
633  *
634  *  If multiple copies are what you want, you should use the block
635  *  version which uses the result of that block each time an element
636  *  of the array needs to be initialized:
637  *
638  *     a = Array.new(2) { Hash.new }
639  *     a[0]['cat'] = 'feline'
640  *     a # => [{"cat"=>"feline"}, {}]
641  *
642  */
643 
644 static VALUE
645 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
646 {
647     long len;
648     VALUE size, val;
649 
650     rb_ary_modify(ary);
651     if (argc == 0) {
652         if (ARY_OWNS_HEAP_P(ary) && RARRAY_PTR(ary)) {
653             xfree(RARRAY_PTR(ary));
654         }
655         rb_ary_unshare_safe(ary);
656         FL_SET_EMBED(ary);
657         ARY_SET_EMBED_LEN(ary, 0);
658         if (rb_block_given_p()) {
659             rb_warning("given block not used");
660         }
661         return ary;
662     }
663     rb_scan_args(argc, argv, "02", &size, &val);
664     if (argc == 1 && !FIXNUM_P(size)) {
665         val = rb_check_array_type(size);
666         if (!NIL_P(val)) {
667             rb_ary_replace(ary, val);
668             return ary;
669         }
670     }
671 
672     len = NUM2LONG(size);
673     if (len < 0) {
674         rb_raise(rb_eArgError, "negative array size");
675     }
676     if (len > ARY_MAX_SIZE) {
677         rb_raise(rb_eArgError, "array size too big");
678     }
679     rb_ary_modify(ary);
680     ary_resize_capa(ary, len);
681     if (rb_block_given_p()) {
682         long i;
683 
684         if (argc == 2) {
685             rb_warn("block supersedes default value argument");
686         }
687         for (i=0; i<len; i++) {
688             rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
689             ARY_SET_LEN(ary, i + 1);
690         }
691     }
692     else {
693         memfill(RARRAY_PTR(ary), len, val);
694         ARY_SET_LEN(ary, len);
695     }
696     return ary;
697 }
698 
699 /*
700  * Returns a new array populated with the given objects.
701  *
702  *   Array.[]( 1, 'a', /^A/ ) # => [1, "a", /^A/]
703  *   Array[ 1, 'a', /^A/ ]    # => [1, "a", /^A/]
704  *   [ 1, 'a', /^A/ ]         # => [1, "a", /^A/]
705  */
706 
707 static VALUE
708 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
709 {
710     VALUE ary = ary_new(klass, argc);
711     if (argc > 0 && argv) {
712         MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
713         ARY_SET_LEN(ary, argc);
714     }
715 
716     return ary;
717 }
718 
719 void
720 rb_ary_store(VALUE ary, long idx, VALUE val)
721 {
722     if (idx < 0) {
723         idx += RARRAY_LEN(ary);
724         if (idx < 0) {
725             rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
726                      idx - RARRAY_LEN(ary), -RARRAY_LEN(ary));
727         }
728     }
729     else if (idx >= ARY_MAX_SIZE) {
730         rb_raise(rb_eIndexError, "index %ld too big", idx);
731     }
732 
733     rb_ary_modify(ary);
734     if (idx >= ARY_CAPA(ary)) {
735         ary_double_capa(ary, idx);
736     }
737     if (idx > RARRAY_LEN(ary)) {
738         rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary),
739                      idx-RARRAY_LEN(ary) + 1);
740     }
741 
742     if (idx >= RARRAY_LEN(ary)) {
743         ARY_SET_LEN(ary, idx + 1);
744     }
745     RARRAY_PTR(ary)[idx] = val;
746 }
747 
748 static VALUE
749 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
750 {
751     assert(offset >= 0);
752     assert(len >= 0);
753     assert(offset+len <= RARRAY_LEN(ary));
754 
755     if (len <= RARRAY_EMBED_LEN_MAX) {
756         VALUE result = ary_alloc(klass);
757         MEMCPY(ARY_EMBED_PTR(result), RARRAY_PTR(ary) + offset, VALUE, len);
758         ARY_SET_EMBED_LEN(result, len);
759         return result;
760     }
761     else {
762         VALUE shared, result = ary_alloc(klass);
763         FL_UNSET_EMBED(result);
764 
765         shared = ary_make_shared(ary);
766         ARY_SET_PTR(result, RARRAY_PTR(ary));
767         ARY_SET_LEN(result, RARRAY_LEN(ary));
768         rb_ary_set_shared(result, shared);
769 
770         ARY_INCREASE_PTR(result, offset);
771         ARY_SET_LEN(result, len);
772         return result;
773     }
774 }
775 
776 static VALUE
777 ary_make_shared_copy(VALUE ary)
778 {
779     return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary));
780 }
781 
782 enum ary_take_pos_flags
783 {
784     ARY_TAKE_FIRST = 0,
785     ARY_TAKE_LAST = 1
786 };
787 
788 static VALUE
789 ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
790 {
791     VALUE nv;
792     long n;
793     long offset = 0;
794 
795     rb_scan_args(argc, argv, "1", &nv);
796     n = NUM2LONG(nv);
797     if (n > RARRAY_LEN(ary)) {
798         n = RARRAY_LEN(ary);
799     }
800     else if (n < 0) {
801         rb_raise(rb_eArgError, "negative array size");
802     }
803     if (last) {
804         offset = RARRAY_LEN(ary) - n;
805     }
806     return ary_make_partial(ary, rb_cArray, offset, n);
807 }
808 
809 /*
810  *  call-seq:
811  *     ary << obj            -> ary
812  *
813  *  Append---Pushes the given object on to the end of this array. This
814  *  expression returns the array itself, so several appends
815  *  may be chained together.
816  *
817  *     [ 1, 2 ] << "c" << "d" << [ 3, 4 ]
818  *             #=>  [ 1, 2, "c", "d", [ 3, 4 ] ]
819  *
820  */
821 
822 VALUE
823 rb_ary_push(VALUE ary, VALUE item)
824 {
825     long idx = RARRAY_LEN(ary);
826 
827     ary_ensure_room_for_push(ary, 1);
828     RARRAY_PTR(ary)[idx] = item;
829     ARY_SET_LEN(ary, idx + 1);
830     return ary;
831 }
832 
833 static VALUE
834 rb_ary_push_1(VALUE ary, VALUE item)
835 {
836     long idx = RARRAY_LEN(ary);
837 
838     if (idx >= ARY_CAPA(ary)) {
839         ary_double_capa(ary, idx);
840     }
841     RARRAY_PTR(ary)[idx] = item;
842     ARY_SET_LEN(ary, idx + 1);
843     return ary;
844 }
845 
846 VALUE
847 rb_ary_cat(VALUE ary, const VALUE *ptr, long len)
848 {
849     long oldlen = RARRAY_LEN(ary);
850 
851     ary_ensure_room_for_push(ary, len);
852     MEMCPY(RARRAY_PTR(ary) + oldlen, ptr, VALUE, len);
853     ARY_SET_LEN(ary, oldlen + len);
854     return ary;
855 }
856 
857 /*
858  *  call-seq:
859  *     ary.push(obj, ... )   -> ary
860  *
861  *  Append --- Pushes the given object(s) on to the end of this array. This
862  *  expression returns the array itself, so several appends
863  *  may be chained together. See also Array#pop for the opposite
864  *  effect.
865  *
866  *     a = [ "a", "b", "c" ]
867  *     a.push("d", "e", "f")
868  *             #=> ["a", "b", "c", "d", "e", "f"]
869  *     [1, 2, 3,].push(4).push(5)
870  *             #=> [1, 2, 3, 4, 5]
871  */
872 
873 static VALUE
874 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
875 {
876     return rb_ary_cat(ary, argv, argc);
877 }
878 
879 VALUE
880 rb_ary_pop(VALUE ary)
881 {
882     long n;
883     rb_ary_modify_check(ary);
884     if (RARRAY_LEN(ary) == 0) return Qnil;
885     if (ARY_OWNS_HEAP_P(ary) &&
886         RARRAY_LEN(ary) * 3 < ARY_CAPA(ary) &&
887         ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
888     {
889         ary_resize_capa(ary, RARRAY_LEN(ary) * 2);
890     }
891     n = RARRAY_LEN(ary)-1;
892     ARY_SET_LEN(ary, n);
893     return RARRAY_PTR(ary)[n];
894 }
895 
896 /*
897  *  call-seq:
898  *     ary.pop    -> obj or nil
899  *     ary.pop(n) -> new_ary
900  *
901  *  Removes the last element from +self+ and returns it, or
902  *  +nil+ if the array is empty.
903  *
904  *  If a number +n+ is given, returns an array of the last +n+ elements
905  *  (or less) just like <code>array.slice!(-n, n)</code> does. See also
906  *  Array#push for the opposite effect.
907  *
908  *     a = [ "a", "b", "c", "d" ]
909  *     a.pop     #=> "d"
910  *     a.pop(2)  #=> ["b", "c"]
911  *     a         #=> ["a"]
912  */
913 
914 static VALUE
915 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
916 {
917     VALUE result;
918 
919     if (argc == 0) {
920         return rb_ary_pop(ary);
921     }
922 
923     rb_ary_modify_check(ary);
924     result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
925     ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
926     return result;
927 }
928 
929 VALUE
930 rb_ary_shift(VALUE ary)
931 {
932     VALUE top;
933 
934     rb_ary_modify_check(ary);
935     if (RARRAY_LEN(ary) == 0) return Qnil;
936     top = RARRAY_PTR(ary)[0];
937     if (!ARY_SHARED_P(ary)) {
938         if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
939             MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1);
940             ARY_INCREASE_LEN(ary, -1);
941             return top;
942         }
943         assert(!ARY_EMBED_P(ary)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
944 
945         RARRAY_PTR(ary)[0] = Qnil;
946         ary_make_shared(ary);
947     }
948     else if (ARY_SHARED_NUM(ARY_SHARED(ary)) == 1) {
949         RARRAY_PTR(ary)[0] = Qnil;
950     }
951     ARY_INCREASE_PTR(ary, 1);           /* shift ptr */
952     ARY_INCREASE_LEN(ary, -1);
953 
954     return top;
955 }
956 
957 /*
958  *  call-seq:
959  *     ary.shift    -> obj or nil
960  *     ary.shift(n) -> new_ary
961  *
962  *  Removes the first element of +self+ and returns it (shifting all
963  *  other elements down by one). Returns +nil+ if the array
964  *  is empty.
965  *
966  *  If a number +n+ is given, returns an array of the first +n+ elements
967  *  (or less) just like <code>array.slice!(0, n)</code> does. With +ary+
968  *  containing only the remainder elements, not including what was shifted to
969  *  +new_ary+. See also Array#unshift for the opposite effect.
970  *
971  *     args = [ "-m", "-q", "filename" ]
972  *     args.shift     #=> "-m"
973  *     args           #=> ["-q", "filename"]
974  *
975  *     args = [ "-m", "-q", "filename" ]
976  *     args.shift(2)  #=> ["-m", "-q"]
977  *     args           #=> ["filename"]
978  */
979 
980 static VALUE
981 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
982 {
983     VALUE result;
984     long n;
985 
986     if (argc == 0) {
987         return rb_ary_shift(ary);
988     }
989 
990     rb_ary_modify_check(ary);
991     result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
992     n = RARRAY_LEN(result);
993     if (ARY_SHARED_P(ary)) {
994         if (ARY_SHARED_NUM(ARY_SHARED(ary)) == 1) {
995             rb_mem_clear(RARRAY_PTR(ary), n);
996         }
997         ARY_INCREASE_PTR(ary, n);
998     }
999     else {
1000         MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
1001     }
1002     ARY_INCREASE_LEN(ary, -n);
1003 
1004     return result;
1005 }
1006 
1007 static void
1008 ary_ensure_room_for_unshift(VALUE ary, int argc)
1009 {
1010     long len = RARRAY_LEN(ary);
1011     long new_len = len + argc;
1012     long capa;
1013     VALUE *head, *sharedp;
1014 
1015     if (ARY_SHARED_P(ary)) {
1016         VALUE shared = ARY_SHARED(ary);
1017         capa = RARRAY_LEN(shared);
1018         if (ARY_SHARED_NUM(shared) == 1 && capa > new_len) {
1019             head = RARRAY_PTR(ary);
1020             sharedp = RARRAY_PTR(shared);
1021             goto makeroom_if_need;
1022         }
1023     }
1024 
1025     rb_ary_modify(ary);
1026     capa = ARY_CAPA(ary);
1027     if (capa - (capa >> 6) <= new_len) {
1028         ary_double_capa(ary, new_len);
1029     }
1030 
1031     /* use shared array for big "queues" */
1032     if (new_len > ARY_DEFAULT_SIZE * 4) {
1033         /* make a room for unshifted items */
1034         capa = ARY_CAPA(ary);
1035         ary_make_shared(ary);
1036 
1037         head = sharedp = RARRAY_PTR(ary);
1038         goto makeroom;
1039       makeroom_if_need:
1040         if (head - sharedp < argc) {
1041             long room;
1042           makeroom:
1043             room = capa - new_len;
1044             room -= room >> 4;
1045             MEMMOVE(sharedp + argc + room, head, VALUE, len);
1046             head = sharedp + argc + room;
1047         }
1048         ARY_SET_PTR(ary, head - argc);
1049     }
1050     else {
1051         /* sliding items */
1052         MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len);
1053     }
1054 }
1055 
1056 /*
1057  *  call-seq:
1058  *     ary.unshift(obj, ...)  -> ary
1059  *
1060  *  Prepends objects to the front of +self+, moving other elements upwards.
1061  *  See also Array#shift for the opposite effect.
1062  *
1063  *     a = [ "b", "c", "d" ]
1064  *     a.unshift("a")   #=> ["a", "b", "c", "d"]
1065  *     a.unshift(1, 2)  #=> [ 1, 2, "a", "b", "c", "d"]
1066  */
1067 
1068 static VALUE
1069 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
1070 {
1071     long len = RARRAY_LEN(ary);
1072 
1073     if (argc == 0) {
1074         rb_ary_modify_check(ary);
1075         return ary;
1076     }
1077 
1078     ary_ensure_room_for_unshift(ary, argc);
1079     MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
1080     ARY_SET_LEN(ary, len + argc);
1081     return ary;
1082 }
1083 
1084 VALUE
1085 rb_ary_unshift(VALUE ary, VALUE item)
1086 {
1087     return rb_ary_unshift_m(1,&item,ary);
1088 }
1089 
1090 /* faster version - use this if you don't need to treat negative offset */
1091 static inline VALUE
1092 rb_ary_elt(VALUE ary, long offset)
1093 {
1094     if (RARRAY_LEN(ary) == 0) return Qnil;
1095     if (offset < 0 || RARRAY_LEN(ary) <= offset) {
1096         return Qnil;
1097     }
1098     return RARRAY_PTR(ary)[offset];
1099 }
1100 
1101 VALUE
1102 rb_ary_entry(VALUE ary, long offset)
1103 {
1104     if (offset < 0) {
1105         offset += RARRAY_LEN(ary);
1106     }
1107     return rb_ary_elt(ary, offset);
1108 }
1109 
1110 VALUE
1111 rb_ary_subseq(VALUE ary, long beg, long len)
1112 {
1113     VALUE klass;
1114 
1115     if (beg > RARRAY_LEN(ary)) return Qnil;
1116     if (beg < 0 || len < 0) return Qnil;
1117 
1118     if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
1119         len = RARRAY_LEN(ary) - beg;
1120     }
1121     klass = rb_obj_class(ary);
1122     if (len == 0) return ary_new(klass, 0);
1123 
1124     return ary_make_partial(ary, klass, beg, len);
1125 }
1126 
1127 /*
1128  *  call-seq:
1129  *     ary[index]                -> obj     or nil
1130  *     ary[start, length]        -> new_ary or nil
1131  *     ary[range]                -> new_ary or nil
1132  *     ary.slice(index)          -> obj     or nil
1133  *     ary.slice(start, length)  -> new_ary or nil
1134  *     ary.slice(range)          -> new_ary or nil
1135  *
1136  *  Element Reference --- Returns the element at +index+, or returns a
1137  *  subarray starting at the +start+ index and continuing for +length+
1138  *  elements, or returns a subarray specified by +range+ of indices.
1139  *
1140  *  Negative indices count backward from the end of the array (-1 is the last
1141  *  element).  For +start+ and +range+ cases the starting index is just before
1142  *  an element.  Additionally, an empty array is returned when the starting
1143  *  index for an element range is at the end of the array.
1144  *
1145  *  Returns +nil+ if the index (or starting index) are out of range.
1146  *
1147  *     a = [ "a", "b", "c", "d", "e" ]
1148  *     a[2] +  a[0] + a[1]    #=> "cab"
1149  *     a[6]                   #=> nil
1150  *     a[1, 2]                #=> [ "b", "c" ]
1151  *     a[1..3]                #=> [ "b", "c", "d" ]
1152  *     a[4..7]                #=> [ "e" ]
1153  *     a[6..10]               #=> nil
1154  *     a[-3, 3]               #=> [ "c", "d", "e" ]
1155  *     # special cases
1156  *     a[5]                   #=> nil
1157  *     a[6, 1]                #=> nil
1158  *     a[5, 1]                #=> []
1159  *     a[5..10]               #=> []
1160  *
1161  */
1162 
1163 VALUE
1164 rb_ary_aref(int argc, VALUE *argv, VALUE ary)
1165 {
1166     VALUE arg;
1167     long beg, len;
1168 
1169     if (argc == 2) {
1170         beg = NUM2LONG(argv[0]);
1171         len = NUM2LONG(argv[1]);
1172         if (beg < 0) {
1173             beg += RARRAY_LEN(ary);
1174         }
1175         return rb_ary_subseq(ary, beg, len);
1176     }
1177     if (argc != 1) {
1178         rb_scan_args(argc, argv, "11", NULL, NULL);
1179     }
1180     arg = argv[0];
1181     /* special case - speeding up */
1182     if (FIXNUM_P(arg)) {
1183         return rb_ary_entry(ary, FIX2LONG(arg));
1184     }
1185     /* check if idx is Range */
1186     switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
1187       case Qfalse:
1188         break;
1189       case Qnil:
1190         return Qnil;
1191       default:
1192         return rb_ary_subseq(ary, beg, len);
1193     }
1194     return rb_ary_entry(ary, NUM2LONG(arg));
1195 }
1196 
1197 /*
1198  *  call-seq:
1199  *     ary.at(index)   ->   obj  or nil
1200  *
1201  *  Returns the element at +index+. A negative index counts from the end of
1202  *  +self+. Returns +nil+ if the index is out of range. See also
1203  *  Array#[].
1204  *
1205  *     a = [ "a", "b", "c", "d", "e" ]
1206  *     a.at(0)     #=> "a"
1207  *     a.at(-1)    #=> "e"
1208  */
1209 
1210 static VALUE
1211 rb_ary_at(VALUE ary, VALUE pos)
1212 {
1213     return rb_ary_entry(ary, NUM2LONG(pos));
1214 }
1215 
1216 /*
1217  *  call-seq:
1218  *     ary.first     ->   obj or nil
1219  *     ary.first(n)  ->   new_ary
1220  *
1221  *  Returns the first element, or the first +n+ elements, of the array.
1222  *  If the array is empty, the first form returns +nil+, and the
1223  *  second form returns an empty array. See also Array#last for
1224  *  the opposite effect.
1225  *
1226  *     a = [ "q", "r", "s", "t" ]
1227  *     a.first     #=> "q"
1228  *     a.first(2)  #=> ["q", "r"]
1229  */
1230 
1231 static VALUE
1232 rb_ary_first(int argc, VALUE *argv, VALUE ary)
1233 {
1234     if (argc == 0) {
1235         if (RARRAY_LEN(ary) == 0) return Qnil;
1236         return RARRAY_PTR(ary)[0];
1237     }
1238     else {
1239         return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
1240     }
1241 }
1242 
1243 /*
1244  *  call-seq:
1245  *     ary.last     ->  obj or nil
1246  *     ary.last(n)  ->  new_ary
1247  *
1248  *  Returns the last element(s) of +self+. If the array is empty,
1249  *  the first form returns +nil+.
1250  *
1251  *  See also Array#first for the opposite effect.
1252  *
1253  *     a = [ "w", "x", "y", "z" ]
1254  *     a.last     #=> "z"
1255  *     a.last(2)  #=> ["y", "z"]
1256  */
1257 
1258 VALUE
1259 rb_ary_last(int argc, VALUE *argv, VALUE ary)
1260 {
1261     if (argc == 0) {
1262         if (RARRAY_LEN(ary) == 0) return Qnil;
1263         return RARRAY_PTR(ary)[RARRAY_LEN(ary)-1];
1264     }
1265     else {
1266         return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
1267     }
1268 }
1269 
1270 /*
1271  *  call-seq:
1272  *     ary.fetch(index)                    -> obj
1273  *     ary.fetch(index, default)           -> obj
1274  *     ary.fetch(index) { |index| block }  -> obj
1275  *
1276  *  Tries to return the element at position +index+, but throws an IndexError
1277  *  exception if the referenced +index+ lies outside of the array bounds.  This
1278  *  error can be prevented by supplying a second argument, which will act as a
1279  *  +default+ value.
1280  *
1281  *  Alternatively, if a block is given it will only be executed when an
1282  *  invalid +index+ is referenced.  Negative values of +index+ count from the
1283  *  end of the array.
1284  *
1285  *     a = [ 11, 22, 33, 44 ]
1286  *     a.fetch(1)               #=> 22
1287  *     a.fetch(-1)              #=> 44
1288  *     a.fetch(4, 'cat')        #=> "cat"
1289  *     a.fetch(100) { |i| puts "#{i} is out of bounds" }
1290  *                              #=> "100 is out of bounds"
1291  */
1292 
1293 static VALUE
1294 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
1295 {
1296     VALUE pos, ifnone;
1297     long block_given;
1298     long idx;
1299 
1300     rb_scan_args(argc, argv, "11", &pos, &ifnone);
1301     block_given = rb_block_given_p();
1302     if (block_given && argc == 2) {
1303         rb_warn("block supersedes default value argument");
1304     }
1305     idx = NUM2LONG(pos);
1306 
1307     if (idx < 0) {
1308         idx +=  RARRAY_LEN(ary);
1309     }
1310     if (idx < 0 || RARRAY_LEN(ary) <= idx) {
1311         if (block_given) return rb_yield(pos);
1312         if (argc == 1) {
1313             rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
1314                         idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
1315         }
1316         return ifnone;
1317     }
1318     return RARRAY_PTR(ary)[idx];
1319 }
1320 
1321 /*
1322  *  call-seq:
1323  *     ary.find_index(obj)             ->  int or nil
1324  *     ary.find_index { |item| block } ->  int or nil
1325  *     ary.find_index                  ->  Enumerator
1326  *     ary.index(obj)             ->  int or nil
1327  *     ary.index { |item| block } ->  int or nil
1328  *     ary.index                  ->  Enumerator
1329  *
1330  *  Returns the _index_ of the first object in +ary+ such that the object is
1331  *  <code>==</code> to +obj+.
1332  *
1333  *  If a block is given instead of an argument, returns the _index_ of the
1334  *  first object for which the block returns +true+.  Returns +nil+ if no
1335  *  match is found.
1336  *
1337  *  See also Array#rindex.
1338  *
1339  *  An Enumerator is returned if neither a block nor argument is given.
1340  *
1341  *     a = [ "a", "b", "c" ]
1342  *     a.index("b")              #=> 1
1343  *     a.index("z")              #=> nil
1344  *     a.index { |x| x == "b" }  #=> 1
1345  *
1346  *  This is an alias of Array#find_index.
1347  */
1348 
1349 static VALUE
1350 rb_ary_index(int argc, VALUE *argv, VALUE ary)
1351 {
1352     VALUE val;
1353     long i;
1354 
1355     if (argc == 0) {
1356         RETURN_ENUMERATOR(ary, 0, 0);
1357         for (i=0; i<RARRAY_LEN(ary); i++) {
1358             if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
1359                 return LONG2NUM(i);
1360             }
1361         }
1362         return Qnil;
1363     }
1364     rb_scan_args(argc, argv, "1", &val);
1365     if (rb_block_given_p())
1366         rb_warn("given block not used");
1367     for (i=0; i<RARRAY_LEN(ary); i++) {
1368         if (rb_equal(RARRAY_PTR(ary)[i], val))
1369             return LONG2NUM(i);
1370     }
1371     return Qnil;
1372 }
1373 
1374 /*
1375  *  call-seq:
1376  *     ary.rindex(obj)             ->  int or nil
1377  *     ary.rindex { |item| block } ->  int or nil
1378  *     ary.rindex                  ->  Enumerator
1379  *
1380  *  Returns the _index_ of the last object in +self+ <code>==</code> to +obj+.
1381  *
1382  *  If a block is given instead of an argument, returns the _index_ of the
1383  *  first object for which the block returns +true+, starting from the last
1384  *  object.
1385  *
1386  *  Returns +nil+ if no match is found.
1387  *
1388  *  See also Array#index.
1389  *
1390  *  If neither block nor argument is given, an Enumerator is returned instead.
1391  *
1392  *     a = [ "a", "b", "b", "b", "c" ]
1393  *     a.rindex("b")             #=> 3
1394  *     a.rindex("z")             #=> nil
1395  *     a.rindex { |x| x == "b" } #=> 3
1396  */
1397 
1398 static VALUE
1399 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
1400 {
1401     VALUE val;
1402     long i = RARRAY_LEN(ary);
1403 
1404     if (argc == 0) {
1405         RETURN_ENUMERATOR(ary, 0, 0);
1406         while (i--) {
1407             if (RTEST(rb_yield(RARRAY_PTR(ary)[i])))
1408                 return LONG2NUM(i);
1409             if (i > RARRAY_LEN(ary)) {
1410                 i = RARRAY_LEN(ary);
1411             }
1412         }
1413         return Qnil;
1414     }
1415     rb_scan_args(argc, argv, "1", &val);
1416     if (rb_block_given_p())
1417         rb_warn("given block not used");
1418     while (i--) {
1419         if (rb_equal(RARRAY_PTR(ary)[i], val))
1420             return LONG2NUM(i);
1421         if (i > RARRAY_LEN(ary)) {
1422             i = RARRAY_LEN(ary);
1423         }
1424     }
1425     return Qnil;
1426 }
1427 
1428 VALUE
1429 rb_ary_to_ary(VALUE obj)
1430 {
1431     VALUE tmp = rb_check_array_type(obj);
1432 
1433     if (!NIL_P(tmp)) return tmp;
1434     return rb_ary_new3(1, obj);
1435 }
1436 
1437 static void
1438 rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
1439 {
1440     long rlen;
1441 
1442     if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
1443     if (beg < 0) {
1444         beg += RARRAY_LEN(ary);
1445         if (beg < 0) {
1446             rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
1447                      beg - RARRAY_LEN(ary), -RARRAY_LEN(ary));
1448         }
1449     }
1450     if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
1451         len = RARRAY_LEN(ary) - beg;
1452     }
1453 
1454     if (rpl == Qundef) {
1455         rlen = 0;
1456     }
1457     else {
1458         rpl = rb_ary_to_ary(rpl);
1459         rlen = RARRAY_LEN(rpl);
1460     }
1461     if (beg >= RARRAY_LEN(ary)) {
1462         if (beg > ARY_MAX_SIZE - rlen) {
1463             rb_raise(rb_eIndexError, "index %ld too big", beg);
1464         }
1465         ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
1466         len = beg + rlen;
1467         rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary));
1468         if (rlen > 0) {
1469             MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
1470         }
1471         ARY_SET_LEN(ary, len);
1472     }
1473     else {
1474         long alen;
1475 
1476         rb_ary_modify(ary);
1477         alen = RARRAY_LEN(ary) + rlen - len;
1478         if (alen >= ARY_CAPA(ary)) {
1479             ary_double_capa(ary, alen);
1480         }
1481 
1482         if (len != rlen) {
1483             MEMMOVE(RARRAY_PTR(ary) + beg + rlen, RARRAY_PTR(ary) + beg + len,
1484                     VALUE, RARRAY_LEN(ary) - (beg + len));
1485             ARY_SET_LEN(ary, alen);
1486         }
1487         if (rlen > 0) {
1488             MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
1489         }
1490     }
1491 }
1492 
1493 void
1494 rb_ary_set_len(VALUE ary, long len)
1495 {
1496     long capa;
1497 
1498     rb_ary_modify_check(ary);
1499     if (ARY_SHARED_P(ary)) {
1500         rb_raise(rb_eRuntimeError, "can't set length of shared ");
1501     }
1502     if (len > (capa = (long)ARY_CAPA(ary))) {
1503         rb_bug("probable buffer overflow: %ld for %ld", len, capa);
1504     }
1505     ARY_SET_LEN(ary, len);
1506 }
1507 
1508 /*!
1509  * expands or shrinks \a ary to \a len elements.
1510  * expanded region will be filled with Qnil.
1511  * \param ary  an array
1512  * \param len  new size
1513  * \return     \a ary
1514  * \post       the size of \a ary is \a len.
1515  */
1516 VALUE
1517 rb_ary_resize(VALUE ary, long len)
1518 {
1519     long olen;
1520 
1521     rb_ary_modify(ary);
1522     olen = RARRAY_LEN(ary);
1523     if (len == olen) return ary;
1524     if (len > ARY_MAX_SIZE) {
1525         rb_raise(rb_eIndexError, "index %ld too big", len);
1526     }
1527     if (len > olen) {
1528         if (len >= ARY_CAPA(ary)) {
1529             ary_double_capa(ary, len);
1530         }
1531         rb_mem_clear(RARRAY_PTR(ary) + olen, len - olen);
1532         ARY_SET_LEN(ary, len);
1533     }
1534     else if (ARY_EMBED_P(ary)) {
1535         ARY_SET_EMBED_LEN(ary, len);
1536     }
1537     else if (len <= RARRAY_EMBED_LEN_MAX) {
1538         VALUE tmp[RARRAY_EMBED_LEN_MAX];
1539         MEMCPY(tmp, ARY_HEAP_PTR(ary), VALUE, len);
1540         ary_discard(ary);
1541         MEMCPY(ARY_EMBED_PTR(ary), tmp, VALUE, len);
1542         ARY_SET_EMBED_LEN(ary, len);
1543     }
1544     else {
1545         if (olen > len + ARY_DEFAULT_SIZE) {
1546             REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, len);
1547             ARY_SET_CAPA(ary, len);
1548         }
1549         ARY_SET_HEAP_LEN(ary, len);
1550     }
1551     return ary;
1552 }
1553 
1554 /*
1555  *  call-seq:
1556  *     ary[index]         = obj                      ->  obj
1557  *     ary[start, length] = obj or other_ary or nil  ->  obj or other_ary or nil
1558  *     ary[range]         = obj or other_ary or nil  ->  obj or other_ary or nil
1559  *
1560  *  Element Assignment --- Sets the element at +index+, or replaces a subarray
1561  *  from the +start+ index for +length+ elements, or replaces a subarray
1562  *  specified by the +range+ of indices.
1563  *
1564  *  If indices are greater than the current capacity of the array, the array
1565  *  grows automatically.  Elements are inserted into the array at +start+ if
1566  *  +length+ is zero.
1567  *
1568  *  Negative indices will count backward from the end of the array.  For
1569  *  +start+ and +range+ cases the starting index is just before an element.
1570  *
1571  *  An IndexError is raised if a negative index points past the beginning of
1572  *  the array.
1573  *
1574  *  See also Array#push, and Array#unshift.
1575  *
1576  *     a = Array.new
1577  *     a[4] = "4";                 #=> [nil, nil, nil, nil, "4"]
1578  *     a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
1579  *     a[1..2] = [ 1, 2 ]          #=> ["a", 1, 2, nil, "4"]
1580  *     a[0, 2] = "?"               #=> ["?", 2, nil, "4"]
1581  *     a[0..2] = "A"               #=> ["A", "4"]
1582  *     a[-1]   = "Z"               #=> ["A", "Z"]
1583  *     a[1..-1] = nil              #=> ["A", nil]
1584  *     a[1..-1] = []               #=> ["A"]
1585  *     a[0, 0] = [ 1, 2 ]          #=> [1, 2, "A"]
1586  *     a[3, 0] = "B"               #=> [1, 2, "A", "B"]
1587  */
1588 
1589 static VALUE
1590 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
1591 {
1592     long offset, beg, len;
1593 
1594     if (argc == 3) {
1595         rb_ary_modify_check(ary);
1596         beg = NUM2LONG(argv[0]);
1597         len = NUM2LONG(argv[1]);
1598         rb_ary_splice(ary, beg, len, argv[2]);
1599         return argv[2];
1600     }
1601     rb_check_arity(argc, 2, 2);
1602     rb_ary_modify_check(ary);
1603     if (FIXNUM_P(argv[0])) {
1604         offset = FIX2LONG(argv[0]);
1605         goto fixnum;
1606     }
1607     if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
1608         /* check if idx is Range */
1609         rb_ary_splice(ary, beg, len, argv[1]);
1610         return argv[1];
1611     }
1612 
1613     offset = NUM2LONG(argv[0]);
1614 fixnum:
1615     rb_ary_store(ary, offset, argv[1]);
1616     return argv[1];
1617 }
1618 
1619 /*
1620  *  call-seq:
1621  *     ary.insert(index, obj...)  -> ary
1622  *
1623  *  Inserts the given values before the element with the given +index+.
1624  *
1625  *  Negative indices count backwards from the end of the array, where +-1+ is
1626  *  the last element.
1627  *
1628  *     a = %w{ a b c d }
1629  *     a.insert(2, 99)         #=> ["a", "b", 99, "c", "d"]
1630  *     a.insert(-2, 1, 2, 3)   #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
1631  */
1632 
1633 static VALUE
1634 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
1635 {
1636     long pos;
1637 
1638     rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
1639     rb_ary_modify_check(ary);
1640     if (argc == 1) return ary;
1641     pos = NUM2LONG(argv[0]);
1642     if (pos == -1) {
1643         pos = RARRAY_LEN(ary);
1644     }
1645     if (pos < 0) {
1646         pos++;
1647     }
1648     rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
1649     return ary;
1650 }
1651 
1652 static VALUE
1653 rb_ary_length(VALUE ary);
1654 
1655 /*
1656  *  call-seq:
1657  *     ary.each { |item| block }  -> ary
1658  *     ary.each                   -> Enumerator
1659  *
1660  *  Calls the given block once for each element in +self+, passing that element
1661  *  as a parameter.
1662  *
1663  *  An Enumerator is returned if no block is given.
1664  *
1665  *     a = [ "a", "b", "c" ]
1666  *     a.each {|x| print x, " -- " }
1667  *
1668  *  produces:
1669  *
1670  *     a -- b -- c --
1671  */
1672 
1673 VALUE
1674 rb_ary_each(VALUE array)
1675 {
1676     long i;
1677     volatile VALUE ary = array;
1678 
1679     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
1680     for (i=0; i<RARRAY_LEN(ary); i++) {
1681         rb_yield(RARRAY_PTR(ary)[i]);
1682     }
1683     return ary;
1684 }
1685 
1686 /*
1687  *  call-seq:
1688  *     ary.each_index { |index| block }  -> ary
1689  *     ary.each_index                    -> Enumerator
1690  *
1691  *  Same as Array#each, but passes the +index+ of the element instead of the
1692  *  element itself.
1693  *
1694  *  An Enumerator is returned if no block is given.
1695  *
1696  *     a = [ "a", "b", "c" ]
1697  *     a.each_index {|x| print x, " -- " }
1698  *
1699  *  produces:
1700  *
1701  *     0 -- 1 -- 2 --
1702  */
1703 
1704 static VALUE
1705 rb_ary_each_index(VALUE ary)
1706 {
1707     long i;
1708     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
1709 
1710     for (i=0; i<RARRAY_LEN(ary); i++) {
1711         rb_yield(LONG2NUM(i));
1712     }
1713     return ary;
1714 }
1715 
1716 /*
1717  *  call-seq:
1718  *     ary.reverse_each { |item| block }  -> ary
1719  *     ary.reverse_each                   -> Enumerator
1720  *
1721  *  Same as Array#each, but traverses +self+ in reverse order.
1722  *
1723  *     a = [ "a", "b", "c" ]
1724  *     a.reverse_each {|x| print x, " " }
1725  *
1726  *  produces:
1727  *
1728  *     c b a
1729  */
1730 
1731 static VALUE
1732 rb_ary_reverse_each(VALUE ary)
1733 {
1734     long len;
1735 
1736     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
1737     len = RARRAY_LEN(ary);
1738     while (len--) {
1739         rb_yield(RARRAY_PTR(ary)[len]);
1740         if (RARRAY_LEN(ary) < len) {
1741             len = RARRAY_LEN(ary);
1742         }
1743     }
1744     return ary;
1745 }
1746 
1747 /*
1748  *  call-seq:
1749  *     ary.length -> int
1750  *
1751  *  Returns the number of elements in +self+. May be zero.
1752  *
1753  *     [ 1, 2, 3, 4, 5 ].length   #=> 5
1754  *     [].length                  #=> 0
1755  */
1756 
1757 static VALUE
1758 rb_ary_length(VALUE ary)
1759 {
1760     long len = RARRAY_LEN(ary);
1761     return LONG2NUM(len);
1762 }
1763 
1764 /*
1765  *  call-seq:
1766  *     ary.empty?   -> true or false
1767  *
1768  *  Returns +true+ if +self+ contains no elements.
1769  *
1770  *     [].empty?   #=> true
1771  */
1772 
1773 static VALUE
1774 rb_ary_empty_p(VALUE ary)
1775 {
1776     if (RARRAY_LEN(ary) == 0)
1777         return Qtrue;
1778     return Qfalse;
1779 }
1780 
1781 VALUE
1782 rb_ary_dup(VALUE ary)
1783 {
1784     VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
1785     MEMCPY(RARRAY_PTR(dup), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
1786     ARY_SET_LEN(dup, RARRAY_LEN(ary));
1787     return dup;
1788 }
1789 
1790 VALUE
1791 rb_ary_resurrect(VALUE ary)
1792 {
1793     return rb_ary_new4(RARRAY_LEN(ary), RARRAY_PTR(ary));
1794 }
1795 
1796 extern VALUE rb_output_fs;
1797 
1798 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
1799 
1800 static VALUE
1801 recursive_join(VALUE obj, VALUE argp, int recur)
1802 {
1803     VALUE *arg = (VALUE *)argp;
1804     VALUE ary = arg[0];
1805     VALUE sep = arg[1];
1806     VALUE result = arg[2];
1807     int *first = (int *)arg[3];
1808 
1809     if (recur) {
1810         rb_raise(rb_eArgError, "recursive array join");
1811     }
1812     else {
1813         ary_join_1(obj, ary, sep, 0, result, first);
1814     }
1815     return Qnil;
1816 }
1817 
1818 static void
1819 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
1820 {
1821     long i;
1822     VALUE val;
1823 
1824     if (max > 0) rb_enc_copy(result, RARRAY_PTR(ary)[0]);
1825     for (i=0; i<max; i++) {
1826         val = RARRAY_PTR(ary)[i];
1827         if (i > 0 && !NIL_P(sep))
1828             rb_str_buf_append(result, sep);
1829         rb_str_buf_append(result, val);
1830         if (OBJ_TAINTED(val)) OBJ_TAINT(result);
1831         if (OBJ_UNTRUSTED(val)) OBJ_TAINT(result);
1832     }
1833 }
1834 
1835 static void
1836 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
1837 {
1838     VALUE val, tmp;
1839 
1840     for (; i<RARRAY_LEN(ary); i++) {
1841         if (i > 0 && !NIL_P(sep))
1842             rb_str_buf_append(result, sep);
1843 
1844         val = RARRAY_PTR(ary)[i];
1845         if (RB_TYPE_P(val, T_STRING)) {
1846           str_join:
1847             rb_str_buf_append(result, val);
1848             *first = FALSE;
1849         }
1850         else if (RB_TYPE_P(val, T_ARRAY)) {
1851             obj = val;
1852           ary_join:
1853             if (val == ary) {
1854                 rb_raise(rb_eArgError, "recursive array join");
1855             }
1856             else {
1857                 VALUE args[4];
1858 
1859                 args[0] = val;
1860                 args[1] = sep;
1861                 args[2] = result;
1862                 args[3] = (VALUE)first;
1863                 rb_exec_recursive(recursive_join, obj, (VALUE)args);
1864             }
1865         }
1866         else {
1867             tmp = rb_check_string_type(val);
1868             if (!NIL_P(tmp)) {
1869                 val = tmp;
1870                 goto str_join;
1871             }
1872             tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_ary");
1873             if (!NIL_P(tmp)) {
1874                 obj = val;
1875                 val = tmp;
1876                 goto ary_join;
1877             }
1878             val = rb_obj_as_string(val);
1879             if (*first) {
1880                 rb_enc_copy(result, val);
1881                 *first = FALSE;
1882             }
1883             goto str_join;
1884         }
1885     }
1886 }
1887 
1888 VALUE
1889 rb_ary_join(VALUE ary, VALUE sep)
1890 {
1891     long len = 1, i;
1892     int taint = FALSE;
1893     int untrust = FALSE;
1894     VALUE val, tmp, result;
1895 
1896     if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
1897     if (OBJ_TAINTED(ary)) taint = TRUE;
1898     if (OBJ_UNTRUSTED(ary)) untrust = TRUE;
1899 
1900     if (!NIL_P(sep)) {
1901         StringValue(sep);
1902         len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
1903     }
1904     for (i=0; i<RARRAY_LEN(ary); i++) {
1905         val = RARRAY_PTR(ary)[i];
1906         tmp = rb_check_string_type(val);
1907 
1908         if (NIL_P(tmp) || tmp != val) {
1909             int first;
1910             result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10);
1911             rb_enc_associate(result, rb_usascii_encoding());
1912             if (taint) OBJ_TAINT(result);
1913             if (untrust) OBJ_UNTRUST(result);
1914             ary_join_0(ary, sep, i, result);
1915             first = i == 0;
1916             ary_join_1(ary, ary, sep, i, result, &first);
1917             return result;
1918         }
1919 
1920         len += RSTRING_LEN(tmp);
1921     }
1922 
1923     result = rb_str_buf_new(len);
1924     if (taint) OBJ_TAINT(result);
1925     if (untrust) OBJ_UNTRUST(result);
1926     ary_join_0(ary, sep, RARRAY_LEN(ary), result);
1927 
1928     return result;
1929 }
1930 
1931 /*
1932  *  call-seq:
1933  *     ary.join(separator=$,)    -> str
1934  *
1935  *  Returns a string created by converting each element of the array to
1936  *  a string, separated by the given +separator+.
1937  *  If the +separator+ is +nil+, it uses current $,.
1938  *  If both the +separator+ and $, are nil, it uses empty string.
1939  *
1940  *     [ "a", "b", "c" ].join        #=> "abc"
1941  *     [ "a", "b", "c" ].join("-")   #=> "a-b-c"
1942  */
1943 
1944 static VALUE
1945 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
1946 {
1947     VALUE sep;
1948 
1949     rb_scan_args(argc, argv, "01", &sep);
1950     if (NIL_P(sep)) sep = rb_output_fs;
1951 
1952     return rb_ary_join(ary, sep);
1953 }
1954 
1955 static VALUE
1956 inspect_ary(VALUE ary, VALUE dummy, int recur)
1957 {
1958     int tainted = OBJ_TAINTED(ary);
1959     int untrust = OBJ_UNTRUSTED(ary);
1960     long i;
1961     VALUE s, str;
1962 
1963     if (recur) return rb_usascii_str_new_cstr("[...]");
1964     str = rb_str_buf_new2("[");
1965     for (i=0; i<RARRAY_LEN(ary); i++) {
1966         s = rb_inspect(RARRAY_PTR(ary)[i]);
1967         if (OBJ_TAINTED(s)) tainted = TRUE;
1968         if (OBJ_UNTRUSTED(s)) untrust = TRUE;
1969         if (i > 0) rb_str_buf_cat2(str, ", ");
1970         else rb_enc_copy(str, s);
1971         rb_str_buf_append(str, s);
1972     }
1973     rb_str_buf_cat2(str, "]");
1974     if (tainted) OBJ_TAINT(str);
1975     if (untrust) OBJ_UNTRUST(str);
1976     return str;
1977 }
1978 
1979 /*
1980  *  call-seq:
1981  *     ary.inspect  -> string
1982  *     ary.to_s     -> string
1983  *
1984  *  Creates a string representation of +self+.
1985  *
1986  *     [ "a", "b", "c" ].to_s     #=> "[\"a\", \"b\", \"c\"]"
1987  */
1988 
1989 static VALUE
1990 rb_ary_inspect(VALUE ary)
1991 {
1992     if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
1993     return rb_exec_recursive(inspect_ary, ary, 0);
1994 }
1995 
1996 VALUE
1997 rb_ary_to_s(VALUE ary)
1998 {
1999     return rb_ary_inspect(ary);
2000 }
2001 
2002 /*
2003  *  call-seq:
2004  *     ary.to_a     -> ary
2005  *
2006  *  Returns +self+.
2007  *
2008  *  If called on a subclass of Array, converts the receiver to an Array object.
2009  */
2010 
2011 static VALUE
2012 rb_ary_to_a(VALUE ary)
2013 {
2014     if (rb_obj_class(ary) != rb_cArray) {
2015         VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
2016         rb_ary_replace(dup, ary);
2017         return dup;
2018     }
2019     return ary;
2020 }
2021 
2022 /*
2023  *  call-seq:
2024  *     ary.to_ary -> ary
2025  *
2026  *  Returns +self+.
2027  */
2028 
2029 static VALUE
2030 rb_ary_to_ary_m(VALUE ary)
2031 {
2032     return ary;
2033 }
2034 
2035 static void
2036 ary_reverse(VALUE *p1, VALUE *p2)
2037 {
2038     while (p1 < p2) {
2039         VALUE tmp = *p1;
2040         *p1++ = *p2;
2041         *p2-- = tmp;
2042     }
2043 }
2044 
2045 VALUE
2046 rb_ary_reverse(VALUE ary)
2047 {
2048     VALUE *p1, *p2;
2049 
2050     rb_ary_modify(ary);
2051     if (RARRAY_LEN(ary) > 1) {
2052         p1 = RARRAY_PTR(ary);
2053         p2 = p1 + RARRAY_LEN(ary) - 1;  /* points last item */
2054         ary_reverse(p1, p2);
2055     }
2056     return ary;
2057 }
2058 
2059 /*
2060  *  call-seq:
2061  *     ary.reverse!   -> ary
2062  *
2063  *  Reverses +self+ in place.
2064  *
2065  *     a = [ "a", "b", "c" ]
2066  *     a.reverse!       #=> ["c", "b", "a"]
2067  *     a                #=> ["c", "b", "a"]
2068  */
2069 
2070 static VALUE
2071 rb_ary_reverse_bang(VALUE ary)
2072 {
2073     return rb_ary_reverse(ary);
2074 }
2075 
2076 /*
2077  *  call-seq:
2078  *     ary.reverse    -> new_ary
2079  *
2080  *  Returns a new array containing +self+'s elements in reverse order.
2081  *
2082  *     [ "a", "b", "c" ].reverse   #=> ["c", "b", "a"]
2083  *     [ 1 ].reverse               #=> [1]
2084  */
2085 
2086 static VALUE
2087 rb_ary_reverse_m(VALUE ary)
2088 {
2089     long len = RARRAY_LEN(ary);
2090     VALUE dup = rb_ary_new2(len);
2091 
2092     if (len > 0) {
2093         VALUE *p1 = RARRAY_PTR(ary);
2094         VALUE *p2 = RARRAY_PTR(dup) + len - 1;
2095         do *p2-- = *p1++; while (--len > 0);
2096     }
2097     ARY_SET_LEN(dup, RARRAY_LEN(ary));
2098     return dup;
2099 }
2100 
2101 static inline long
2102 rotate_count(long cnt, long len)
2103 {
2104     return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
2105 }
2106 
2107 VALUE
2108 rb_ary_rotate(VALUE ary, long cnt)
2109 {
2110     rb_ary_modify(ary);
2111 
2112     if (cnt != 0) {
2113         VALUE *ptr = RARRAY_PTR(ary);
2114         long len = RARRAY_LEN(ary);
2115 
2116         if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
2117             --len;
2118             if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
2119             if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
2120             if (len > 0) ary_reverse(ptr, ptr + len);
2121             return ary;
2122         }
2123     }
2124 
2125     return Qnil;
2126 }
2127 
2128 /*
2129  *  call-seq:
2130  *     ary.rotate!(count=1)   -> ary
2131  *
2132  *  Rotates +self+ in place so that the element at +count+ comes first, and
2133  *  returns +self+.
2134  *
2135  *  If +count+ is negative then it rotates in the opposite direction, starting
2136  *  from the end of the array where +-1+ is the last element.
2137  *
2138  *     a = [ "a", "b", "c", "d" ]
2139  *     a.rotate!        #=> ["b", "c", "d", "a"]
2140  *     a                #=> ["b", "c", "d", "a"]
2141  *     a.rotate!(2)     #=> ["d", "a", "b", "c"]
2142  *     a.rotate!(-3)    #=> ["a", "b", "c", "d"]
2143  */
2144 
2145 static VALUE
2146 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
2147 {
2148     long n = 1;
2149 
2150     switch (argc) {
2151       case 1: n = NUM2LONG(argv[0]);
2152       case 0: break;
2153       default: rb_scan_args(argc, argv, "01", NULL);
2154     }
2155     rb_ary_rotate(ary, n);
2156     return ary;
2157 }
2158 
2159 /*
2160  *  call-seq:
2161  *     ary.rotate(count=1)    -> new_ary
2162  *
2163  *  Returns a new array by rotating +self+ so that the element at +count+ is
2164  *  the first element of the new array.
2165  *
2166  *  If +count+ is negative then it rotates in the opposite direction, starting
2167  *  from the end of +self+ where +-1+ is the last element.
2168  *
2169  *     a = [ "a", "b", "c", "d" ]
2170  *     a.rotate         #=> ["b", "c", "d", "a"]
2171  *     a                #=> ["a", "b", "c", "d"]
2172  *     a.rotate(2)      #=> ["c", "d", "a", "b"]
2173  *     a.rotate(-3)     #=> ["b", "c", "d", "a"]
2174  */
2175 
2176 static VALUE
2177 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
2178 {
2179     VALUE rotated, *ptr, *ptr2;
2180     long len, cnt = 1;
2181 
2182     switch (argc) {
2183       case 1: cnt = NUM2LONG(argv[0]);
2184       case 0: break;
2185       default: rb_scan_args(argc, argv, "01", NULL);
2186     }
2187 
2188     len = RARRAY_LEN(ary);
2189     rotated = rb_ary_new2(len);
2190     if (len > 0) {
2191         cnt = rotate_count(cnt, len);
2192         ptr = RARRAY_PTR(ary);
2193         ptr2 = RARRAY_PTR(rotated);
2194         len -= cnt;
2195         MEMCPY(ptr2, ptr + cnt, VALUE, len);
2196         MEMCPY(ptr2 + len, ptr, VALUE, cnt);
2197     }
2198     ARY_SET_LEN(rotated, RARRAY_LEN(ary));
2199     return rotated;
2200 }
2201 
2202 struct ary_sort_data {
2203     VALUE ary;
2204     int opt_methods;
2205     int opt_inited;
2206 };
2207 
2208 enum {
2209     sort_opt_Fixnum,
2210     sort_opt_String,
2211     sort_optimizable_count
2212 };
2213 
2214 #define STRING_P(s) (RB_TYPE_P((s), T_STRING) && CLASS_OF(s) == rb_cString)
2215 
2216 #define SORT_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(sort_opt_,type))
2217 #define SORT_OPTIMIZABLE(data, type) \
2218     (((data)->opt_inited & SORT_OPTIMIZABLE_BIT(type)) ? \
2219      ((data)->opt_methods & SORT_OPTIMIZABLE_BIT(type)) : \
2220      (((data)->opt_inited |= SORT_OPTIMIZABLE_BIT(type)), \
2221       rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \
2222       ((data)->opt_methods |= SORT_OPTIMIZABLE_BIT(type))))
2223 
2224 static VALUE
2225 sort_reentered(VALUE ary)
2226 {
2227     if (RBASIC(ary)->klass) {
2228         rb_raise(rb_eRuntimeError, "sort reentered");
2229     }
2230     return Qnil;
2231 }
2232 
2233 static int
2234 sort_1(const void *ap, const void *bp, void *dummy)
2235 {
2236     struct ary_sort_data *data = dummy;
2237     VALUE retval = sort_reentered(data->ary);
2238     VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
2239     int n;
2240 
2241     retval = rb_yield_values(2, a, b);
2242     n = rb_cmpint(retval, a, b);
2243     sort_reentered(data->ary);
2244     return n;
2245 }
2246 
2247 static int
2248 sort_2(const void *ap, const void *bp, void *dummy)
2249 {
2250     struct ary_sort_data *data = dummy;
2251     VALUE retval = sort_reentered(data->ary);
2252     VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
2253     int n;
2254 
2255     if (FIXNUM_P(a) && FIXNUM_P(b) && SORT_OPTIMIZABLE(data, Fixnum)) {
2256         if ((long)a > (long)b) return 1;
2257         if ((long)a < (long)b) return -1;
2258         return 0;
2259     }
2260     if (STRING_P(a) && STRING_P(b) && SORT_OPTIMIZABLE(data, String)) {
2261         return rb_str_cmp(a, b);
2262     }
2263 
2264     retval = rb_funcall(a, id_cmp, 1, b);
2265     n = rb_cmpint(retval, a, b);
2266     sort_reentered(data->ary);
2267 
2268     return n;
2269 }
2270 
2271 /*
2272  *  call-seq:
2273  *     ary.sort!                   -> ary
2274  *     ary.sort! { |a, b| block }  -> ary
2275  *
2276  *  Sorts +self+ in place.
2277  *
2278  *  Comparisons for the sort will be done using the <code><=></code> operator
2279  *  or using an optional code block.
2280  *
2281  *  The block must implement a comparison between +a+ and +b+, and return
2282  *  +-1+, when +a+ follows +b+, +0+ when +a+ and +b+ are equivalent, or ++1+
2283  *  if +b+ follows +a+.
2284  *
2285  *  See also Enumerable#sort_by.
2286  *
2287  *     a = [ "d", "a", "e", "c", "b" ]
2288  *     a.sort!                    #=> ["a", "b", "c", "d", "e"]
2289  *     a.sort! { |x,y| y <=> x }  #=> ["e", "d", "c", "b", "a"]
2290  */
2291 
2292 VALUE
2293 rb_ary_sort_bang(VALUE ary)
2294 {
2295     rb_ary_modify(ary);
2296     assert(!ARY_SHARED_P(ary));
2297     if (RARRAY_LEN(ary) > 1) {
2298         VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
2299         struct ary_sort_data data;
2300         long len = RARRAY_LEN(ary);
2301 
2302         RBASIC(tmp)->klass = 0;
2303         data.ary = tmp;
2304         data.opt_methods = 0;
2305         data.opt_inited = 0;
2306         ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE),
2307                    rb_block_given_p()?sort_1:sort_2, &data);
2308 
2309         if (ARY_EMBED_P(tmp)) {
2310             assert(ARY_EMBED_P(tmp));
2311             if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
2312                 rb_ary_unshare(ary);
2313             }
2314             FL_SET_EMBED(ary);
2315             MEMCPY(RARRAY_PTR(ary), ARY_EMBED_PTR(tmp), VALUE, ARY_EMBED_LEN(tmp));
2316             ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
2317         }
2318         else {
2319             assert(!ARY_EMBED_P(tmp));
2320             if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
2321                 assert(!ARY_EMBED_P(ary));
2322                 FL_UNSET_SHARED(ary);
2323                 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
2324             }
2325             else {
2326                 assert(!ARY_SHARED_P(tmp));
2327                 if (ARY_EMBED_P(ary)) {
2328                     FL_UNSET_EMBED(ary);
2329                 }
2330                 else if (ARY_SHARED_P(ary)) {
2331                     /* ary might be destructively operated in the given block */
2332                     rb_ary_unshare(ary);
2333                 }
2334                 else {
2335                     xfree(ARY_HEAP_PTR(ary));
2336                 }
2337                 ARY_SET_PTR(ary, RARRAY_PTR(tmp));
2338                 ARY_SET_HEAP_LEN(ary, len);
2339                 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
2340             }
2341             /* tmp was lost ownership for the ptr */
2342             FL_UNSET(tmp, FL_FREEZE);
2343             FL_SET_EMBED(tmp);
2344             ARY_SET_EMBED_LEN(tmp, 0);
2345             FL_SET(tmp, FL_FREEZE);
2346         }
2347         /* tmp will be GC'ed. */
2348         RBASIC(tmp)->klass = rb_cArray;
2349     }
2350     return ary;
2351 }
2352 
2353 /*
2354  *  call-seq:
2355  *     ary.sort                   -> new_ary
2356  *     ary.sort { |a, b| block }  -> new_ary
2357  *
2358  *  Returns a new array created by sorting +self+.
2359  *
2360  *  Comparisons for the sort will be done using the <code><=></code> operator
2361  *  or using an optional code block.
2362  *
2363  *  The block must implement a comparison between +a+ and +b+, and return
2364  *  +-1+, when +a+ follows +b+, +0+ when +a+ and +b+ are equivalent, or ++1+
2365  *  if +b+ follows +a+.
2366  *
2367  *
2368  *  See also Enumerable#sort_by.
2369  *
2370  *     a = [ "d", "a", "e", "c", "b" ]
2371  *     a.sort                    #=> ["a", "b", "c", "d", "e"]
2372  *     a.sort { |x,y| y <=> x }  #=> ["e", "d", "c", "b", "a"]
2373  */
2374 
2375 VALUE
2376 rb_ary_sort(VALUE ary)
2377 {
2378     ary = rb_ary_dup(ary);
2379     rb_ary_sort_bang(ary);
2380     return ary;
2381 }
2382 
2383 /*
2384  *  call-seq:
2385  *     ary.bsearch {|x| block }  -> elem
2386  *
2387  *  By using binary search, finds a value from this array which meets
2388  *  the given condition in O(log n) where n is the size of the array.
2389  *
2390  *  You can use this method in two use cases: a find-minimum mode and
2391  *  a find-any mode.  In either case, the elements of the array must be
2392  *  monotone (or sorted) with respect to the block.
2393  *
2394  *  In find-minimum mode (this is a good choice for typical use case),
2395  *  the block must return true or false, and there must be an index i
2396  *  (0 <= i <= ary.size) so that:
2397  *
2398  *  - the block returns false for any element whose index is less than
2399  *    i, and
2400  *  - the block returns true for any element whose index is greater
2401  *    than or equal to i.
2402  *
2403  *  This method returns the i-th element.  If i is equal to ary.size,
2404  *  it returns nil.
2405  *
2406  *     ary = [0, 4, 7, 10, 12]
2407  *     ary.bsearch {|x| x >=   4 } #=> 4
2408  *     ary.bsearch {|x| x >=   6 } #=> 7
2409  *     ary.bsearch {|x| x >=  -1 } #=> 0
2410  *     ary.bsearch {|x| x >= 100 } #=> nil
2411  *
2412  *  In find-any mode (this behaves like libc's bsearch(3)), the block
2413  *  must return a number, and there must be two indices i and j
2414  *  (0 <= i <= j <= ary.size) so that:
2415  *
2416  *  - the block returns a positive number for ary[k] if 0 <= k < i,
2417  *  - the block returns zero for ary[k] if i <= k < j, and
2418  *  - the block returns a negative number for ary[k] if
2419  *    j <= k < ary.size.
2420  *
2421  *  Under this condition, this method returns any element whose index
2422  *  is within i...j.  If i is equal to j (i.e., there is no element
2423  *  that satisfies the block), this method returns nil.
2424  *
2425  *     ary = [0, 4, 7, 10, 12]
2426  *     # try to find v such that 4 <= v < 8
2427  *     ary.bsearch {|x| 1 - x / 4 } #=> 4 or 7
2428  *     # try to find v such that 8 <= v < 10
2429  *     ary.bsearch {|x| 4 - x / 2 } #=> nil
2430  *
2431  *  You must not mix the two modes at a time; the block must always
2432  *  return either true/false, or always return a number.  It is
2433  *  undefined which value is actually picked up at each iteration.
2434  */
2435 
2436 static VALUE
2437 rb_ary_bsearch(VALUE ary)
2438 {
2439     long low = 0, high = RARRAY_LEN(ary), mid;
2440     int smaller = 0, satisfied = 0;
2441     VALUE v, val;
2442 
2443     RETURN_ENUMERATOR(ary, 0, 0);
2444     while (low < high) {
2445         mid = low + ((high - low) / 2);
2446         val = rb_ary_entry(ary, mid);
2447         v = rb_yield(val);
2448         if (FIXNUM_P(v)) {
2449             if (FIX2INT(v) == 0) return val;
2450             smaller = FIX2INT(v) < 0;
2451         }
2452         else if (v == Qtrue) {
2453             satisfied = 1;
2454             smaller = 1;
2455         }
2456         else if (v == Qfalse || v == Qnil) {
2457             smaller = 0;
2458         }
2459         else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
2460             switch (rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0))) {
2461                 case 0: return val;
2462                 case 1: smaller = 1; break;
2463                 case -1: smaller = 0;
2464             }
2465         }
2466         else {
2467             rb_raise(rb_eTypeError, "wrong argument type %s"
2468                 " (must be numeric, true, false or nil)",
2469                 rb_obj_classname(v));
2470         }
2471         if (smaller) {
2472             high = mid;
2473         }
2474         else {
2475             low = mid + 1;
2476         }
2477     }
2478     if (low == RARRAY_LEN(ary)) return Qnil;
2479     if (!satisfied) return Qnil;
2480     return rb_ary_entry(ary, low);
2481 }
2482 
2483 
2484 static VALUE
2485 sort_by_i(VALUE i)
2486 {
2487     return rb_yield(i);
2488 }
2489 
2490 /*
2491  *  call-seq:
2492  *     ary.sort_by! { |obj| block }    -> ary
2493  *     ary.sort_by!                    -> Enumerator
2494  *
2495  *  Sorts +self+ in place using a set of keys generated by mapping the
2496  *  values in +self+ through the given block.
2497  *
2498  *  If no block is given, an Enumerator is returned instead.
2499  *
2500  */
2501 
2502 static VALUE
2503 rb_ary_sort_by_bang(VALUE ary)
2504 {
2505     VALUE sorted;
2506 
2507     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
2508     rb_ary_modify(ary);
2509     sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
2510     rb_ary_replace(ary, sorted);
2511     return ary;
2512 }
2513 
2514 
2515 /*
2516  *  call-seq:
2517  *     ary.collect { |item| block }  -> new_ary
2518  *     ary.map     { |item| block }  -> new_ary
2519  *     ary.collect                   -> Enumerator
2520  *     ary.map                       -> Enumerator
2521  *
2522  *  Invokes the given block once for each element of +self+.
2523  *
2524  *  Creates a new array containing the values returned by the block.
2525  *
2526  *  See also Enumerable#collect.
2527  *
2528  *  If no block is given, an Enumerator is returned instead.
2529  *
2530  *     a = [ "a", "b", "c", "d" ]
2531  *     a.map { |x| x + "!" }   #=> ["a!", "b!", "c!", "d!"]
2532  *     a                       #=> ["a", "b", "c", "d"]
2533  */
2534 
2535 static VALUE
2536 rb_ary_collect(VALUE ary)
2537 {
2538     long i;
2539     VALUE collect;
2540 
2541     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
2542     collect = rb_ary_new2(RARRAY_LEN(ary));
2543     for (i = 0; i < RARRAY_LEN(ary); i++) {
2544         rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
2545     }
2546     return collect;
2547 }
2548 
2549 
2550 /*
2551  *  call-seq:
2552  *     ary.collect! {|item| block }   -> ary
2553  *     ary.map!     {|item| block }   -> ary
2554  *     ary.collect!                   -> Enumerator
2555  *     ary.map!                       -> Enumerator
2556  *
2557  *  Invokes the given block once for each element of +self+, replacing the
2558  *  element with the value returned by the block.
2559  *
2560  *  See also Enumerable#collect.
2561  *
2562  *  If no block is given, an Enumerator is returned instead.
2563  *
2564  *     a = [ "a", "b", "c", "d" ]
2565  *     a.map! {|x| x + "!" }
2566  *     a #=>  [ "a!", "b!", "c!", "d!" ]
2567  */
2568 
2569 static VALUE
2570 rb_ary_collect_bang(VALUE ary)
2571 {
2572     long i;
2573 
2574     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
2575     rb_ary_modify(ary);
2576     for (i = 0; i < RARRAY_LEN(ary); i++) {
2577         rb_ary_store(ary, i, rb_yield(RARRAY_PTR(ary)[i]));
2578     }
2579     return ary;
2580 }
2581 
2582 VALUE
2583 rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, VALUE (*func) (VALUE, long))
2584 {
2585     VALUE result = rb_ary_new2(argc);
2586     long beg, len, i, j;
2587 
2588     for (i=0; i<argc; i++) {
2589         if (FIXNUM_P(argv[i])) {
2590             rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
2591             continue;
2592         }
2593         /* check if idx is Range */
2594         if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
2595             long end = olen < beg+len ? olen : beg+len;
2596             for (j = beg; j < end; j++) {
2597                 rb_ary_push(result, (*func)(obj, j));
2598             }
2599             if (beg + len > j)
2600                 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
2601             continue;
2602         }
2603         rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
2604     }
2605     return result;
2606 }
2607 
2608 /*
2609  *  call-seq:
2610  *     ary.values_at(selector, ...)  -> new_ary
2611  *
2612  *  Returns an array containing the elements in +self+ corresponding to the
2613  *  given +selector+(s).
2614  *
2615  *  The selectors may be either integer indices or ranges.
2616  *
2617  *  See also Array#select.
2618  *
2619  *     a = %w{ a b c d e f }
2620  *     a.values_at(1, 3, 5)          # => ["b", "d", "f"]
2621  *     a.values_at(1, 3, 5, 7)       # => ["b", "d", "f", nil]
2622  *     a.values_at(-1, -2, -2, -7)   # => ["f", "e", "e", nil]
2623  *     a.values_at(4..6, 3...6)      # => ["e", "f", nil, "d", "e", "f"]
2624  */
2625 
2626 static VALUE
2627 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
2628 {
2629     return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
2630 }
2631 
2632 
2633 /*
2634  *  call-seq:
2635  *     ary.select { |item| block } -> new_ary
2636  *     ary.select                  -> Enumerator
2637  *
2638  *  Returns a new array containing all elements of +ary+
2639  *  for which the given +block+ returns a true value.
2640  *
2641  *  If no block is given, an Enumerator is returned instead.
2642  *
2643  *     [1,2,3,4,5].select { |num|  num.even?  }   #=> [2, 4]
2644  *
2645  *     a = %w{ a b c d e f }
2646  *     a.select { |v| v =~ /[aeiou]/ }  #=> ["a", "e"]
2647  *
2648  *  See also Enumerable#select.
2649  */
2650 
2651 static VALUE
2652 rb_ary_select(VALUE ary)
2653 {
2654     VALUE result;
2655     long i;
2656 
2657     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
2658     result = rb_ary_new2(RARRAY_LEN(ary));
2659     for (i = 0; i < RARRAY_LEN(ary); i++) {
2660         if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
2661             rb_ary_push(result, rb_ary_elt(ary, i));
2662         }
2663     }
2664     return result;
2665 }
2666 
2667 /*
2668  *  call-seq:
2669  *     ary.select!  {|item| block } -> ary or nil
2670  *     ary.select!                  -> Enumerator
2671  *
2672  *  Invokes the given block passing in successive elements from +self+,
2673  *  deleting elements for which the block returns a +false+ value.
2674  *
2675  *  If changes were made, it will return +self+, otherwise it returns +nil+.
2676  *
2677  *  See also Array#keep_if
2678  *
2679  *  If no block is given, an Enumerator is returned instead.
2680  *
2681  */
2682 
2683 static VALUE
2684 rb_ary_select_bang(VALUE ary)
2685 {
2686     long i1, i2;
2687 
2688     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
2689     rb_ary_modify(ary);
2690     for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
2691         VALUE v = RARRAY_PTR(ary)[i1];
2692         if (!RTEST(rb_yield(v))) continue;
2693         if (i1 != i2) {
2694             rb_ary_store(ary, i2, v);
2695         }
2696         i2++;
2697     }
2698 
2699     if (RARRAY_LEN(ary) == i2) return Qnil;
2700     if (i2 < RARRAY_LEN(ary))
2701         ARY_SET_LEN(ary, i2);
2702     return ary;
2703 }
2704 
2705 /*
2706  *  call-seq:
2707  *     ary.keep_if { |item| block } -> ary
2708  *     ary.keep_if                  -> Enumerator
2709  *
2710  *  Deletes every element of +self+ for which the given block evaluates to
2711  *  +false+.
2712  *
2713  *  See also Array#select!
2714  *
2715  *  If no block is given, an Enumerator is returned instead.
2716  *
2717  *     a = %w{ a b c d e f }
2718  *     a.keep_if { |v| v =~ /[aeiou]/ }  #=> ["a", "e"]
2719  */
2720 
2721 static VALUE
2722 rb_ary_keep_if(VALUE ary)
2723 {
2724     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
2725     rb_ary_select_bang(ary);
2726     return ary;
2727 }
2728 
2729 static void
2730 ary_resize_smaller(VALUE ary, long len)
2731 {
2732     rb_ary_modify(ary);
2733     if (RARRAY_LEN(ary) > len) {
2734         ARY_SET_LEN(ary, len);
2735         if (len * 2 < ARY_CAPA(ary) &&
2736             ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
2737             ary_resize_capa(ary, len * 2);
2738         }
2739     }
2740 }
2741 
2742 /*
2743  *  call-seq:
2744  *     ary.delete(obj)            -> item or nil
2745  *     ary.delete(obj) { block }  -> item or result of block
2746  *
2747  *  Deletes all items from +self+ that are equal to +obj+.
2748  *
2749  *  Returns the last deleted item, or +nil+ if no matching item is found.
2750  *
2751  *  If the optional code block is given, the result of the block is returned if
2752  *  the item is not found.  (To remove +nil+ elements and get an informative
2753  *  return value, use Array#compact!)
2754  *
2755  *     a = [ "a", "b", "b", "b", "c" ]
2756  *     a.delete("b")                   #=> "b"
2757  *     a                               #=> ["a", "c"]
2758  *     a.delete("z")                   #=> nil
2759  *     a.delete("z") { "not found" }   #=> "not found"
2760  */
2761 
2762 VALUE
2763 rb_ary_delete(VALUE ary, VALUE item)
2764 {
2765     VALUE v = item;
2766     long i1, i2;
2767 
2768     for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
2769         VALUE e = RARRAY_PTR(ary)[i1];
2770 
2771         if (rb_equal(e, item)) {
2772             v = e;
2773             continue;
2774         }
2775         if (i1 != i2) {
2776             rb_ary_store(ary, i2, e);
2777         }
2778         i2++;
2779     }
2780     if (RARRAY_LEN(ary) == i2) {
2781         if (rb_block_given_p()) {
2782             return rb_yield(item);
2783         }
2784         return Qnil;
2785     }
2786 
2787     ary_resize_smaller(ary, i2);
2788 
2789     return v;
2790 }
2791 
2792 void
2793 rb_ary_delete_same(VALUE ary, VALUE item)
2794 {
2795     long i1, i2;
2796 
2797     for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
2798         VALUE e = RARRAY_PTR(ary)[i1];
2799 
2800         if (e == item) {
2801             continue;
2802         }
2803         if (i1 != i2) {
2804             rb_ary_store(ary, i2, e);
2805         }
2806         i2++;
2807     }
2808     if (RARRAY_LEN(ary) == i2) {
2809         return;
2810     }
2811 
2812     ary_resize_smaller(ary, i2);
2813 }
2814 
2815 VALUE
2816 rb_ary_delete_at(VALUE ary, long pos)
2817 {
2818     long len = RARRAY_LEN(ary);
2819     VALUE del;
2820 
2821     if (pos >= len) return Qnil;
2822     if (pos < 0) {
2823         pos += len;
2824         if (pos < 0) return Qnil;
2825     }
2826 
2827     rb_ary_modify(ary);
2828     del = RARRAY_PTR(ary)[pos];
2829     MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
2830             RARRAY_LEN(ary)-pos-1);
2831     ARY_INCREASE_LEN(ary, -1);
2832 
2833     return del;
2834 }
2835 
2836 /*
2837  *  call-seq:
2838  *     ary.delete_at(index)  -> obj or nil
2839  *
2840  *  Deletes the element at the specified +index+, returning that element, or
2841  *  +nil+ if the +index+ is out of range.
2842  *
2843  *  See also Array#slice!
2844  *
2845  *     a = ["ant", "bat", "cat", "dog"]
2846  *     a.delete_at(2)    #=> "cat"
2847  *     a                 #=> ["ant", "bat", "dog"]
2848  *     a.delete_at(99)   #=> nil
2849  */
2850 
2851 static VALUE
2852 rb_ary_delete_at_m(VALUE ary, VALUE pos)
2853 {
2854     return rb_ary_delete_at(ary, NUM2LONG(pos));
2855 }
2856 
2857 /*
2858  *  call-seq:
2859  *     ary.slice!(index)         -> obj or nil
2860  *     ary.slice!(start, length) -> new_ary or nil
2861  *     ary.slice!(range)         -> new_ary or nil
2862  *
2863  *  Deletes the element(s) given by an +index+ (optionally up to +length+
2864  *  elements) or by a +range+.
2865  *
2866  *  Returns the deleted object (or objects), or +nil+ if the +index+ is out of
2867  *  range.
2868  *
2869  *     a = [ "a", "b", "c" ]
2870  *     a.slice!(1)     #=> "b"
2871  *     a               #=> ["a", "c"]
2872  *     a.slice!(-1)    #=> "c"
2873  *     a               #=> ["a"]
2874  *     a.slice!(100)   #=> nil
2875  *     a               #=> ["a"]
2876  */
2877 
2878 static VALUE
2879 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
2880 {
2881     VALUE arg1, arg2;
2882     long pos, len, orig_len;
2883 
2884     rb_ary_modify_check(ary);
2885     if (argc == 2) {
2886         pos = NUM2LONG(argv[0]);
2887         len = NUM2LONG(argv[1]);
2888       delete_pos_len:
2889         if (len < 0) return Qnil;
2890         orig_len = RARRAY_LEN(ary);
2891         if (pos < 0) {
2892             pos += orig_len;
2893             if (pos < 0) return Qnil;
2894         }
2895         else if (orig_len < pos) return Qnil;
2896         if (orig_len < pos + len) {
2897             len = orig_len - pos;
2898         }
2899         if (len == 0) return rb_ary_new2(0);
2900         arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
2901         RBASIC(arg2)->klass = rb_obj_class(ary);
2902         rb_ary_splice(ary, pos, len, Qundef);
2903         return arg2;
2904     }
2905 
2906     if (argc != 1) {
2907         /* error report */
2908         rb_scan_args(argc, argv, "11", NULL, NULL);
2909     }
2910     arg1 = argv[0];
2911 
2912     if (!FIXNUM_P(arg1)) {
2913         switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
2914           case Qtrue:
2915             /* valid range */
2916             goto delete_pos_len;
2917           case Qnil:
2918             /* invalid range */
2919             return Qnil;
2920           default:
2921             /* not a range */
2922             break;
2923         }
2924     }
2925 
2926     return rb_ary_delete_at(ary, NUM2LONG(arg1));
2927 }
2928 
2929 static VALUE
2930 ary_reject(VALUE orig, VALUE result)
2931 {
2932     long i;
2933 
2934     for (i = 0; i < RARRAY_LEN(orig); i++) {
2935         VALUE v = RARRAY_PTR(orig)[i];
2936         if (!RTEST(rb_yield(v))) {
2937             rb_ary_push_1(result, v);
2938         }
2939     }
2940     return result;
2941 }
2942 
2943 static VALUE
2944 ary_reject_bang(VALUE ary)
2945 {
2946     long i;
2947     VALUE result = Qnil;
2948 
2949     rb_ary_modify_check(ary);
2950     for (i = 0; i < RARRAY_LEN(ary); ) {
2951         VALUE v = RARRAY_PTR(ary)[i];
2952         if (RTEST(rb_yield(v))) {
2953             rb_ary_delete_at(ary, i);
2954             result = ary;
2955         }
2956         else {
2957             i++;
2958         }
2959     }
2960     return result;
2961 }
2962 
2963 /*
2964  *  call-seq:
2965  *     ary.reject! { |item| block }  -> ary or nil
2966  *     ary.reject!                   -> Enumerator
2967  *
2968  *  Equivalent to Array#delete_if, deleting elements from +self+ for which the
2969  *  block evaluates to +true+, but returns +nil+ if no changes were made.
2970  *
2971  *  The array is changed instantly every time the block is called, not after
2972  *  the iteration is over.
2973  *
2974  *  See also Enumerable#reject and Array#delete_if.
2975  *
2976  *  If no block is given, an Enumerator is returned instead.
2977  */
2978 
2979 static VALUE
2980 rb_ary_reject_bang(VALUE ary)
2981 {
2982     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
2983     return ary_reject_bang(ary);
2984 }
2985 
2986 /*
2987  *  call-seq:
2988  *     ary.reject  {|item| block }  -> new_ary
2989  *     ary.reject                   -> Enumerator
2990  *
2991  *  Returns a new array containing the items in +self+ for which the given
2992  *  block is not +true+.
2993  *
2994  *  See also Array#delete_if
2995  *
2996  *  If no block is given, an Enumerator is returned instead.
2997  */
2998 
2999 static VALUE
3000 rb_ary_reject(VALUE ary)
3001 {
3002     VALUE rejected_ary;
3003 
3004     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
3005     rejected_ary = rb_ary_new();
3006     ary_reject(ary, rejected_ary);
3007     return rejected_ary;
3008 }
3009 
3010 /*
3011  *  call-seq:
3012  *     ary.delete_if { |item| block }  -> ary
3013  *     ary.delete_if                   -> Enumerator
3014  *
3015  *  Deletes every element of +self+ for which block evaluates to +true+.
3016  *
3017  *  The array is changed instantly every time the block is called, not after
3018  *  the iteration is over.
3019  *
3020  *  See also Array#reject!
3021  *
3022  *  If no block is given, an Enumerator is returned instead.
3023  *
3024  *     a = [ "a", "b", "c" ]
3025  *     a.delete_if {|x| x >= "b" }   #=> ["a"]
3026  */
3027 
3028 static VALUE
3029 rb_ary_delete_if(VALUE ary)
3030 {
3031     RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
3032     ary_reject_bang(ary);
3033     return ary;
3034 }
3035 
3036 static VALUE
3037 take_i(VALUE val, VALUE *args, int argc, VALUE *argv)
3038 {
3039     if (args[1]-- == 0) rb_iter_break();
3040     if (argc > 1) val = rb_ary_new4(argc, argv);
3041     rb_ary_push(args[0], val);
3042     return Qnil;
3043 }
3044 
3045 static VALUE
3046 take_items(VALUE obj, long n)
3047 {
3048     VALUE result = rb_check_array_type(obj);
3049     VALUE args[2];
3050 
3051     if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
3052     result = rb_ary_new2(n);
3053     args[0] = result; args[1] = (VALUE)n;
3054     if (rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args) == Qundef)
3055         rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
3056                  rb_obj_class(obj));
3057     return result;
3058 }
3059 
3060 
3061 /*
3062  *  call-seq:
3063  *     ary.zip(arg, ...)                  -> new_ary
3064  *     ary.zip(arg, ...) { |arr| block }  -> nil
3065  *
3066  *  Converts any arguments to arrays, then merges elements of +self+ with
3067  *  corresponding elements from each argument.
3068  *
3069  *  This generates a sequence of <code>ary.size</code> _n_-element arrays,
3070  *  where _n_ is one more that the count of arguments.
3071  *
3072  *  If the size of any argument is less than the size of the initial array,
3073  *  +nil+ values are supplied.
3074  *
3075  *  If a block is given, it is invoked for each output +array+, otherwise an
3076  *  array of arrays is returned.
3077  *
3078  *     a = [ 4, 5, 6 ]
3079  *     b = [ 7, 8, 9 ]
3080  *     [1, 2, 3].zip(a, b)   #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
3081  *     [1, 2].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8]]
3082  *     a.zip([1, 2], [8])    #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
3083  */
3084 
3085 static VALUE
3086 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
3087 {
3088     int i, j;
3089     long len;
3090     VALUE result = Qnil;
3091 
3092     len = RARRAY_LEN(ary);
3093     for (i=0; i<argc; i++) {
3094         argv[i] = take_items(argv[i], len);
3095     }
3096     if (!rb_block_given_p()) {
3097         result = rb_ary_new2(len);
3098     }
3099 
3100     for (i=0; i<RARRAY_LEN(ary); i++) {
3101         VALUE tmp = rb_ary_new2(argc+1);
3102 
3103         rb_ary_push(tmp, rb_ary_elt(ary, i));
3104         for (j=0; j<argc; j++) {
3105             rb_ary_push(tmp, rb_ary_elt(argv[j], i));
3106         }
3107         if (NIL_P(result)) {
3108             rb_yield(tmp);
3109         }
3110         else {
3111             rb_ary_push(result, tmp);
3112         }
3113     }
3114     return result;
3115 }
3116 
3117 /*
3118  *  call-seq:
3119  *     ary.transpose -> new_ary
3120  *
3121  *  Assumes that +self+ is an array of arrays and transposes the rows and
3122  *  columns.
3123  *
3124  *     a = [[1,2], [3,4], [5,6]]
3125  *     a.transpose   #=> [[1, 3, 5], [2, 4, 6]]
3126  *
3127  *  If the length of the subarrays don't match, an IndexError is raised.
3128  */
3129 
3130 static VALUE
3131 rb_ary_transpose(VALUE ary)
3132 {
3133     long elen = -1, alen, i, j;
3134     VALUE tmp, result = 0;
3135 
3136     alen = RARRAY_LEN(ary);
3137     if (alen == 0) return rb_ary_dup(ary);
3138     for (i=0; i<alen; i++) {
3139         tmp = to_ary(rb_ary_elt(ary, i));
3140         if (elen < 0) {         /* first element */
3141             elen = RARRAY_LEN(tmp);
3142             result = rb_ary_new2(elen);
3143             for (j=0; j<elen; j++) {
3144                 rb_ary_store(result, j, rb_ary_new2(alen));
3145             }
3146         }
3147         else if (elen != RARRAY_LEN(tmp)) {
3148             rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
3149                      RARRAY_LEN(tmp), elen);
3150         }
3151         for (j=0; j<elen; j++) {
3152             rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
3153         }
3154     }
3155     return result;
3156 }
3157 
3158 /*
3159  *  call-seq:
3160  *     ary.replace(other_ary)  -> ary
3161  *
3162  *  Replaces the contents of +self+ with the contents of +other_ary+,
3163  *  truncating or expanding if necessary.
3164  *
3165  *     a = [ "a", "b", "c", "d", "e" ]
3166  *     a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
3167  *     a                              #=> ["x", "y", "z"]
3168  */
3169 
3170 VALUE
3171 rb_ary_replace(VALUE copy, VALUE orig)
3172 {
3173     rb_ary_modify_check(copy);
3174     orig = to_ary(orig);
3175     if (copy == orig) return copy;
3176 
3177     if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
3178         VALUE *ptr;
3179         VALUE shared = 0;
3180 
3181         if (ARY_OWNS_HEAP_P(copy)) {
3182             xfree(RARRAY_PTR(copy));
3183         }
3184         else if (ARY_SHARED_P(copy)) {
3185             shared = ARY_SHARED(copy);
3186             FL_UNSET_SHARED(copy);
3187         }
3188         FL_SET_EMBED(copy);
3189         ptr = RARRAY_PTR(orig);
3190         MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
3191         if (shared) {
3192             rb_ary_decrement_share(shared);
3193         }
3194         ARY_SET_LEN(copy, RARRAY_LEN(orig));
3195     }
3196     else {
3197         VALUE shared = ary_make_shared(orig);
3198         if (ARY_OWNS_HEAP_P(copy)) {
3199             xfree(RARRAY_PTR(copy));
3200         }
3201         else {
3202             rb_ary_unshare_safe(copy);
3203         }
3204         FL_UNSET_EMBED(copy);
3205         ARY_SET_PTR(copy, RARRAY_PTR(orig));
3206         ARY_SET_LEN(copy, RARRAY_LEN(orig));
3207         rb_ary_set_shared(copy, shared);
3208     }
3209     return copy;
3210 }
3211 
3212 /*
3213  *  call-seq:
3214  *     ary.clear    -> ary
3215  *
3216  *  Removes all elements from +self+.
3217  *
3218  *     a = [ "a", "b", "c", "d", "e" ]
3219  *     a.clear    #=> [ ]
3220  */
3221 
3222 VALUE
3223 rb_ary_clear(VALUE ary)
3224 {
3225     rb_ary_modify_check(ary);
3226     ARY_SET_LEN(ary, 0);
3227     if (ARY_SHARED_P(ary)) {
3228         if (!ARY_EMBED_P(ary)) {
3229             rb_ary_unshare(ary);
3230             FL_SET_EMBED(ary);
3231         }
3232     }
3233     else if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
3234         ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
3235     }
3236     return ary;
3237 }
3238 
3239 /*
3240  *  call-seq:
3241  *     ary.fill(obj)                                 -> ary
3242  *     ary.fill(obj, start [, length])               -> ary
3243  *     ary.fill(obj, range )                         -> ary
3244  *     ary.fill { |index| block }                    -> ary
3245  *     ary.fill(start [, length] ) { |index| block } -> ary
3246  *     ary.fill(range) { |index| block }             -> ary
3247  *
3248  *  The first three forms set the selected elements of +self+ (which
3249  *  may be the entire array) to +obj+.
3250  *
3251  *  A +start+ of +nil+ is equivalent to zero.
3252  *
3253  *  A +length+ of +nil+ is equivalent to the length of the array.
3254  *
3255  *  The last three forms fill the array with the value of the given block,
3256  *  which is passed the absolute index of each element to be filled.
3257  *
3258  *  Negative values of +start+ count from the end of the array, where +-1+ is
3259  *  the last element.
3260  *
3261  *     a = [ "a", "b", "c", "d" ]
3262  *     a.fill("x")              #=> ["x", "x", "x", "x"]
3263  *     a.fill("z", 2, 2)        #=> ["x", "x", "z", "z"]
3264  *     a.fill("y", 0..1)        #=> ["y", "y", "z", "z"]
3265  *     a.fill { |i| i*i }       #=> [0, 1, 4, 9]
3266  *     a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]
3267  */
3268 
3269 static VALUE
3270 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
3271 {
3272     VALUE item, arg1, arg2;
3273     long beg = 0, end = 0, len = 0;
3274     VALUE *p, *pend;
3275     int block_p = FALSE;
3276 
3277     if (rb_block_given_p()) {
3278         block_p = TRUE;
3279         rb_scan_args(argc, argv, "02", &arg1, &arg2);
3280         argc += 1;              /* hackish */
3281     }
3282     else {
3283         rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
3284     }
3285     switch (argc) {
3286       case 1:
3287         beg = 0;
3288         len = RARRAY_LEN(ary);
3289         break;
3290       case 2:
3291         if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
3292             break;
3293         }
3294         /* fall through */
3295       case 3:
3296         beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
3297         if (beg < 0) {
3298             beg = RARRAY_LEN(ary) + beg;
3299             if (beg < 0) beg = 0;
3300         }
3301         len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
3302         break;
3303     }
3304     rb_ary_modify(ary);
3305     if (len < 0) {
3306         return ary;
3307     }
3308     if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
3309         rb_raise(rb_eArgError, "argument too big");
3310     }
3311     end = beg + len;
3312     if (RARRAY_LEN(ary) < end) {
3313         if (end >= ARY_CAPA(ary)) {
3314             ary_resize_capa(ary, end);
3315         }
3316         rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
3317         ARY_SET_LEN(ary, end);
3318     }
3319 
3320     if (block_p) {
3321         VALUE v;
3322         long i;
3323 
3324         for (i=beg; i<end; i++) {
3325             v = rb_yield(LONG2NUM(i));
3326             if (i>=RARRAY_LEN(ary)) break;
3327             RARRAY_PTR(ary)[i] = v;
3328         }
3329     }
3330     else {
3331         p = RARRAY_PTR(ary) + beg;
3332         pend = p + len;
3333         while (p < pend) {
3334             *p++ = item;
3335         }
3336     }
3337     return ary;
3338 }
3339 
3340 /*
3341  *  call-seq:
3342  *     ary + other_ary   -> new_ary
3343  *
3344  *  Concatenation --- Returns a new array built by concatenating the
3345  *  two arrays together to produce a third array.
3346  *
3347  *     [ 1, 2, 3 ] + [ 4, 5 ]    #=> [ 1, 2, 3, 4, 5 ]
3348  *     a = [ "a", "b", "c" ]
3349  *     a + [ "d", "e", "f" ]
3350  *     a                         #=> [ "a", "b", "c", "d", "e", "f" ]
3351  *
3352  *  See also Array#concat.
3353  */
3354 
3355 VALUE
3356 rb_ary_plus(VALUE x, VALUE y)
3357 {
3358     VALUE z;
3359     long len;
3360 
3361     y = to_ary(y);
3362     len = RARRAY_LEN(x) + RARRAY_LEN(y);
3363     z = rb_ary_new2(len);
3364     MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
3365     MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
3366     ARY_SET_LEN(z, len);
3367     return z;
3368 }
3369 
3370 /*
3371  *  call-seq:
3372  *     ary.concat(other_ary)   -> ary
3373  *
3374  *  Appends the elements of +other_ary+ to +self+.
3375  *
3376  *     [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
3377  *     a = [ 1, 2, 3 ]
3378  *     a.concat( [ 4, 5 ] )
3379  *     a                                 #=> [ 1, 2, 3, 4, 5 ]
3380  *
3381  *  See also Array#+.
3382  */
3383 
3384 VALUE
3385 rb_ary_concat(VALUE x, VALUE y)
3386 {
3387     rb_ary_modify_check(x);
3388     y = to_ary(y);
3389     if (RARRAY_LEN(y) > 0) {
3390         rb_ary_splice(x, RARRAY_LEN(x), 0, y);
3391     }
3392     return x;
3393 }
3394 
3395 
3396 /*
3397  *  call-seq:
3398  *     ary * int     -> new_ary
3399  *     ary * str     -> new_string
3400  *
3401  *  Repetition --- With a String argument, equivalent to
3402  *  <code>ary.join(str)</code>.
3403  *
3404  *  Otherwise, returns a new array built by concatenating the +int+ copies of
3405  *  +self+.
3406  *
3407  *
3408  *     [ 1, 2, 3 ] * 3    #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
3409  *     [ 1, 2, 3 ] * ","  #=> "1,2,3"
3410  *
3411  */
3412 
3413 static VALUE
3414 rb_ary_times(VALUE ary, VALUE times)
3415 {
3416     VALUE ary2, tmp, *ptr, *ptr2;
3417     long t, len;
3418 
3419     tmp = rb_check_string_type(times);
3420     if (!NIL_P(tmp)) {
3421         return rb_ary_join(ary, tmp);
3422     }
3423 
3424     len = NUM2LONG(times);
3425     if (len == 0) {
3426         ary2 = ary_new(rb_obj_class(ary), 0);
3427         goto out;
3428     }
3429     if (len < 0) {
3430         rb_raise(rb_eArgError, "negative argument");
3431     }
3432     if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
3433         rb_raise(rb_eArgError, "argument too big");
3434     }
3435     len *= RARRAY_LEN(ary);
3436 
3437     ary2 = ary_new(rb_obj_class(ary), len);
3438     ARY_SET_LEN(ary2, len);
3439 
3440     ptr = RARRAY_PTR(ary);
3441     ptr2 = RARRAY_PTR(ary2);
3442     t = RARRAY_LEN(ary);
3443     if (0 < t) {
3444         MEMCPY(ptr2, ptr, VALUE, t);
3445         while (t <= len/2) {
3446             MEMCPY(ptr2+t, ptr2, VALUE, t);
3447             t *= 2;
3448         }
3449         if (t < len) {
3450             MEMCPY(ptr2+t, ptr2, VALUE, len-t);
3451         }
3452     }
3453   out:
3454     OBJ_INFECT(ary2, ary);
3455 
3456     return ary2;
3457 }
3458 
3459 /*
3460  *  call-seq:
3461  *     ary.assoc(obj)   -> new_ary  or  nil
3462  *
3463  *  Searches through an array whose elements are also arrays comparing +obj+
3464  *  with the first element of each contained array using <code>obj.==</code>.
3465  *
3466  *  Returns the first contained array that matches (that is, the first
3467  *  associated array), or +nil+ if no match is found.
3468  *
3469  *  See also Array#rassoc
3470  *
3471  *     s1 = [ "colors", "red", "blue", "green" ]
3472  *     s2 = [ "letters", "a", "b", "c" ]
3473  *     s3 = "foo"
3474  *     a  = [ s1, s2, s3 ]
3475  *     a.assoc("letters")  #=> [ "letters", "a", "b", "c" ]
3476  *     a.assoc("foo")      #=> nil
3477  */
3478 
3479 VALUE
3480 rb_ary_assoc(VALUE ary, VALUE key)
3481 {
3482     long i;
3483     VALUE v;
3484 
3485     for (i = 0; i < RARRAY_LEN(ary); ++i) {
3486         v = rb_check_array_type(RARRAY_PTR(ary)[i]);
3487         if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
3488             rb_equal(RARRAY_PTR(v)[0], key))
3489             return v;
3490     }
3491     return Qnil;
3492 }
3493 
3494 /*
3495  *  call-seq:
3496  *     ary.rassoc(obj) -> new_ary or nil
3497  *
3498  *  Searches through the array whose elements are also arrays.
3499  *
3500  *  Compares +obj+ with the second element of each contained array using
3501  *  <code>obj.==</code>.
3502  *
3503  *  Returns the first contained array that matches +obj+.
3504  *
3505  *  See also Array#assoc.
3506  *
3507  *     a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
3508  *     a.rassoc("two")    #=> [2, "two"]
3509  *     a.rassoc("four")   #=> nil
3510  */
3511 
3512 VALUE
3513 rb_ary_rassoc(VALUE ary, VALUE value)
3514 {
3515     long i;
3516     VALUE v;
3517 
3518     for (i = 0; i < RARRAY_LEN(ary); ++i) {
3519         v = RARRAY_PTR(ary)[i];
3520         if (RB_TYPE_P(v, T_ARRAY) &&
3521             RARRAY_LEN(v) > 1 &&
3522             rb_equal(RARRAY_PTR(v)[1], value))
3523             return v;
3524     }
3525     return Qnil;
3526 }
3527 
3528 static VALUE
3529 recursive_equal(VALUE ary1, VALUE ary2, int recur)
3530 {
3531     long i, len1;
3532     VALUE *p1, *p2;
3533 
3534     if (recur) return Qtrue; /* Subtle! */
3535 
3536     p1 = RARRAY_PTR(ary1);
3537     p2 = RARRAY_PTR(ary2);
3538     len1 = RARRAY_LEN(ary1);
3539 
3540     for (i = 0; i < len1; i++) {
3541         if (*p1 != *p2) {
3542             if (rb_equal(*p1, *p2)) {
3543                 len1 = RARRAY_LEN(ary1);
3544                 if (len1 != RARRAY_LEN(ary2))
3545                     return Qfalse;
3546                 if (len1 < i)
3547                     return Qtrue;
3548                 p1 = RARRAY_PTR(ary1) + i;
3549                 p2 = RARRAY_PTR(ary2) + i;
3550             }
3551             else {
3552                 return Qfalse;
3553             }
3554         }
3555         p1++;
3556         p2++;
3557     }
3558     return Qtrue;
3559 }
3560 
3561 /*
3562  *  call-seq:
3563  *     ary == other_ary   ->   bool
3564  *
3565  *  Equality --- Two arrays are equal if they contain the same number of
3566  *  elements and if each element is equal to (according to Object#==) the
3567  *  corresponding element in +other_ary+.
3568  *
3569  *     [ "a", "c" ]    == [ "a", "c", 7 ]     #=> false
3570  *     [ "a", "c", 7 ] == [ "a", "c", 7 ]     #=> true
3571  *     [ "a", "c", 7 ] == [ "a", "d", "f" ]   #=> false
3572  *
3573  */
3574 
3575 static VALUE
3576 rb_ary_equal(VALUE ary1, VALUE ary2)
3577 {
3578     if (ary1 == ary2) return Qtrue;
3579     if (!RB_TYPE_P(ary2, T_ARRAY)) {
3580         if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
3581             return Qfalse;
3582         }
3583         return rb_equal(ary2, ary1);
3584     }
3585     if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
3586     return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
3587 }
3588 
3589 static VALUE
3590 recursive_eql(VALUE ary1, VALUE ary2, int recur)
3591 {
3592     long i;
3593 
3594     if (recur) return Qtrue; /* Subtle! */
3595     for (i=0; i<RARRAY_LEN(ary1); i++) {
3596         if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
3597             return Qfalse;
3598     }
3599     return Qtrue;
3600 }
3601 
3602 /*
3603  *  call-seq:
3604  *     ary.eql?(other)  -> true or false
3605  *
3606  *  Returns +true+ if +self+ and +other+ are the same object,
3607  *  or are both arrays with the same content.
3608  */
3609 
3610 static VALUE
3611 rb_ary_eql(VALUE ary1, VALUE ary2)
3612 {
3613     if (ary1 == ary2) return Qtrue;
3614     if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
3615     if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
3616     return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
3617 }
3618 
3619 static VALUE
3620 recursive_hash(VALUE ary, VALUE dummy, int recur)
3621 {
3622     long i;
3623     st_index_t h;
3624     VALUE n;
3625 
3626     h = rb_hash_start(RARRAY_LEN(ary));
3627     if (recur) {
3628         h = rb_hash_uint(h, NUM2LONG(rb_hash(rb_cArray)));
3629     }
3630     else {
3631         for (i=0; i<RARRAY_LEN(ary); i++) {
3632             n = rb_hash(RARRAY_PTR(ary)[i]);
3633             h = rb_hash_uint(h, NUM2LONG(n));
3634         }
3635     }
3636     h = rb_hash_end(h);
3637     return LONG2FIX(h);
3638 }
3639 
3640 /*
3641  *  call-seq:
3642  *     ary.hash   -> fixnum
3643  *
3644  *  Compute a hash-code for this array.
3645  *
3646  *  Two arrays with the same content will have the same hash code (and will
3647  *  compare using #eql?).
3648  */
3649 
3650 static VALUE
3651 rb_ary_hash(VALUE ary)
3652 {
3653     return rb_exec_recursive_outer(recursive_hash, ary, 0);
3654 }
3655 
3656 /*
3657  *  call-seq:
3658  *     ary.include?(object)   -> true or false
3659  *
3660  *  Returns +true+ if the given +object+ is present in +self+ (that is, if any
3661  *  element <code>==</code> +object+), otherwise returns +false+.
3662  *
3663  *     a = [ "a", "b", "c" ]
3664  *     a.include?("b")   #=> true
3665  *     a.include?("z")   #=> false
3666  */
3667 
3668 VALUE
3669 rb_ary_includes(VALUE ary, VALUE item)
3670 {
3671     long i;
3672 
3673     for (i=0; i<RARRAY_LEN(ary); i++) {
3674         if (rb_equal(RARRAY_PTR(ary)[i], item)) {
3675             return Qtrue;
3676         }
3677     }
3678     return Qfalse;
3679 }
3680 
3681 
3682 static VALUE
3683 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
3684 {
3685     long i, len;
3686 
3687     if (recur) return Qundef;   /* Subtle! */
3688     len = RARRAY_LEN(ary1);
3689     if (len > RARRAY_LEN(ary2)) {
3690         len = RARRAY_LEN(ary2);
3691     }
3692     for (i=0; i<len; i++) {
3693         VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
3694         if (v != INT2FIX(0)) {
3695             return v;
3696         }
3697     }
3698     return Qundef;
3699 }
3700 
3701 /*
3702  *  call-seq:
3703  *     ary <=> other_ary   ->  -1, 0, +1 or nil
3704  *
3705  *  Comparison --- Returns an integer (+-1+, +0+, or <code>+1</code>) if this
3706  *  array is less than, equal to, or greater than +other_ary+.
3707  *
3708  *  +nil+ is returned if the two values are incomparable.
3709  *
3710  *  Each object in each array is compared (using the <=> operator).
3711  *
3712  *  Arrays are compared in an "element-wise" manner; the first two elements
3713  *  that are not equal will determine the return value for the whole
3714  *  comparison.
3715  *
3716  *  If all the values are equal, then the return is based on a comparison of
3717  *  the array lengths. Thus, two arrays are "equal" according to Array#<=> if,
3718  *  and only if, they have the same length and the value of each element is
3719  *  equal to the value of the corresponding element in the other array.
3720  *
3721  *     [ "a", "a", "c" ]    <=> [ "a", "b", "c" ]   #=> -1
3722  *     [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ]            #=> +1
3723  *
3724  */
3725 
3726 VALUE
3727 rb_ary_cmp(VALUE ary1, VALUE ary2)
3728 {
3729     long len;
3730     VALUE v;
3731 
3732     ary2 = rb_check_array_type(ary2);
3733     if (NIL_P(ary2)) return Qnil;
3734     if (ary1 == ary2) return INT2FIX(0);
3735     v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
3736     if (v != Qundef) return v;
3737     len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
3738     if (len == 0) return INT2FIX(0);
3739     if (len > 0) return INT2FIX(1);
3740     return INT2FIX(-1);
3741 }
3742 
3743 static VALUE
3744 ary_add_hash(VALUE hash, VALUE ary)
3745 {
3746     long i;
3747 
3748     for (i=0; i<RARRAY_LEN(ary); i++) {
3749         rb_hash_aset(hash, RARRAY_PTR(ary)[i], Qtrue);
3750     }
3751     return hash;
3752 }
3753 
3754 static inline VALUE
3755 ary_tmp_hash_new(void)
3756 {
3757     VALUE hash = rb_hash_new();
3758 
3759     RBASIC(hash)->klass = 0;
3760     return hash;
3761 }
3762 
3763 static VALUE
3764 ary_make_hash(VALUE ary)
3765 {
3766     VALUE hash = ary_tmp_hash_new();
3767     return ary_add_hash(hash, ary);
3768 }
3769 
3770 static VALUE
3771 ary_add_hash_by(VALUE hash, VALUE ary)
3772 {
3773     long i;
3774 
3775     for (i = 0; i < RARRAY_LEN(ary); ++i) {
3776         VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
3777         if (rb_hash_lookup2(hash, k, Qundef) == Qundef) {
3778             rb_hash_aset(hash, k, v);
3779         }
3780     }
3781     return hash;
3782 }
3783 
3784 static VALUE
3785 ary_make_hash_by(VALUE ary)
3786 {
3787     VALUE hash = ary_tmp_hash_new();
3788     return ary_add_hash_by(hash, ary);
3789 }
3790 
3791 static inline void
3792 ary_recycle_hash(VALUE hash)
3793 {
3794     if (RHASH(hash)->ntbl) {
3795         st_table *tbl = RHASH(hash)->ntbl;
3796         RHASH(hash)->ntbl = 0;
3797         st_free_table(tbl);
3798     }
3799 }
3800 
3801 /*
3802  *  call-seq:
3803  *     ary - other_ary    -> new_ary
3804  *
3805  *  Array Difference
3806  *
3807  *  Returns a new array that is a copy of the original array, removing any
3808  *  items that also appear in +other_ary+. The order is preserved from the
3809  *  original array.
3810  *
3811  *  It compares elements using their #hash and #eql? methods for efficiency.
3812  *
3813  *     [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]
3814  *
3815  *  If you need set-like behavior, see the library class Set.
3816  */
3817 
3818 static VALUE
3819 rb_ary_diff(VALUE ary1, VALUE ary2)
3820 {
3821     VALUE ary3;
3822     volatile VALUE hash;
3823     long i;
3824 
3825     hash = ary_make_hash(to_ary(ary2));
3826     ary3 = rb_ary_new();
3827 
3828     for (i=0; i<RARRAY_LEN(ary1); i++) {
3829         if (st_lookup(RHASH_TBL(hash), RARRAY_PTR(ary1)[i], 0)) continue;
3830         rb_ary_push(ary3, rb_ary_elt(ary1, i));
3831     }
3832     ary_recycle_hash(hash);
3833     return ary3;
3834 }
3835 
3836 /*
3837  *  call-seq:
3838  *     ary & other_ary      -> new_ary
3839  *
3840  *  Set Intersection --- Returns a new array containing elements common to the
3841  *  two arrays, excluding any duplicates. The order is preserved from the
3842  *  original array.
3843  *
3844  *  It compares elements using their #hash and #eql? methods for efficiency.
3845  *
3846  *     [ 1, 1, 3, 5 ] & [ 1, 2, 3 ]                 #=> [ 1, 3 ]
3847  *     [ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ]   #=> [ 'a', 'b' ]
3848  *
3849  *  See also Array#uniq.
3850  */
3851 
3852 
3853 static VALUE
3854 rb_ary_and(VALUE ary1, VALUE ary2)
3855 {
3856     VALUE hash, ary3, v;
3857     st_data_t vv;
3858     long i;
3859 
3860     ary2 = to_ary(ary2);
3861     ary3 = rb_ary_new2(RARRAY_LEN(ary1) < RARRAY_LEN(ary2) ?
3862             RARRAY_LEN(ary1) : RARRAY_LEN(ary2));
3863     hash = ary_make_hash(ary2);
3864 
3865     if (RHASH_EMPTY_P(hash))
3866         return ary3;
3867 
3868     for (i=0; i<RARRAY_LEN(ary1); i++) {
3869         vv = (st_data_t)(v = rb_ary_elt(ary1, i));
3870         if (st_delete(RHASH_TBL(hash), &vv, 0)) {
3871             rb_ary_push(ary3, v);
3872         }
3873     }
3874     ary_recycle_hash(hash);
3875 
3876     return ary3;
3877 }
3878 
3879 /*
3880  *  call-seq:
3881  *     ary | other_ary     -> new_ary
3882  *
3883  *  Set Union --- Returns a new array by joining +ary+ with +other_ary+,
3884  *  excluding any duplicates and preserving the order from the original array.
3885  *
3886  *  It compares elements using their #hash and #eql? methods for efficiency.
3887  *
3888  *     [ "a", "b", "c" ] | [ "c", "d", "a" ]    #=> [ "a", "b", "c", "d" ]
3889  *
3890  *  See also Array#uniq.
3891  */
3892 
3893 static VALUE
3894 rb_ary_or(VALUE ary1, VALUE ary2)
3895 {
3896     VALUE hash, ary3, v;
3897     st_data_t vv;
3898     long i;
3899 
3900     ary2 = to_ary(ary2);
3901     ary3 = rb_ary_new2(RARRAY_LEN(ary1)+RARRAY_LEN(ary2));
3902     hash = ary_add_hash(ary_make_hash(ary1), ary2);
3903 
3904     for (i=0; i<RARRAY_LEN(ary1); i++) {
3905         vv = (st_data_t)(v = rb_ary_elt(ary1, i));
3906         if (st_delete(RHASH_TBL(hash), &vv, 0)) {
3907             rb_ary_push(ary3, v);
3908         }
3909     }
3910     for (i=0; i<RARRAY_LEN(ary2); i++) {
3911         vv = (st_data_t)(v = rb_ary_elt(ary2, i));
3912         if (st_delete(RHASH_TBL(hash), &vv, 0)) {
3913             rb_ary_push(ary3, v);
3914         }
3915     }
3916     ary_recycle_hash(hash);
3917     return ary3;
3918 }
3919 
3920 static int
3921 push_value(st_data_t key, st_data_t val, st_data_t ary)
3922 {
3923     rb_ary_push((VALUE)ary, (VALUE)val);
3924     return ST_CONTINUE;
3925 }
3926 
3927 /*
3928  *  call-seq:
3929  *     ary.uniq!                -> ary or nil
3930  *     ary.uniq! { |item| ... } -> ary or nil
3931  *
3932  *  Removes duplicate elements from +self+.
3933  *
3934  *  If a block is given, it will use the return value of the block for
3935  *  comparison.
3936  *
3937  *  It compares values using their #hash and #eql? methods for efficiency.
3938  *
3939  *  Returns +nil+ if no changes are made (that is, no duplicates are found).
3940  *
3941  *     a = [ "a", "a", "b", "b", "c" ]
3942  *     a.uniq!   # => ["a", "b", "c"]
3943  *
3944  *     b = [ "a", "b", "c" ]
3945  *     b.uniq!   # => nil
3946  *
3947  *     c = [["student","sam"], ["student","george"], ["teacher","matz"]]
3948  *     c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
3949  *
3950  */
3951 
3952 static VALUE
3953 rb_ary_uniq_bang(VALUE ary)
3954 {
3955     VALUE hash, v;
3956     long i, j;
3957 
3958     rb_ary_modify_check(ary);
3959     if (RARRAY_LEN(ary) <= 1)
3960         return Qnil;
3961     if (rb_block_given_p()) {
3962         hash = ary_make_hash_by(ary);
3963         if (RARRAY_LEN(ary) == (i = RHASH_SIZE(hash))) {
3964             return Qnil;
3965         }
3966         ARY_SET_LEN(ary, 0);
3967         if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
3968             rb_ary_unshare(ary);
3969             FL_SET_EMBED(ary);
3970         }
3971         ary_resize_capa(ary, i);
3972         st_foreach(RHASH_TBL(hash), push_value, ary);
3973     }
3974     else {
3975         hash = ary_make_hash(ary);
3976         if (RARRAY_LEN(ary) == (long)RHASH_SIZE(hash)) {
3977             return Qnil;
3978         }
3979         for (i=j=0; i<RARRAY_LEN(ary); i++) {
3980             st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
3981             if (st_delete(RHASH_TBL(hash), &vv, 0)) {
3982                 rb_ary_store(ary, j++, v);
3983             }
3984         }
3985         ARY_SET_LEN(ary, j);
3986     }
3987     ary_recycle_hash(hash);
3988 
3989     return ary;
3990 }
3991 
3992 /*
3993  *  call-seq:
3994  *     ary.uniq                -> new_ary
3995  *     ary.uniq { |item| ... } -> new_ary
3996  *
3997  *  Returns a new array by removing duplicate values in +self+.
3998  *
3999  *  If a block is given, it will use the return value of the block for comparison.
4000  *
4001  *  It compares values using their #hash and #eql? methods for efficiency.
4002  *
4003  *     a = [ "a", "a", "b", "b", "c" ]
4004  *     a.uniq   # => ["a", "b", "c"]
4005  *
4006  *     b = [["student","sam"], ["student","george"], ["teacher","matz"]]
4007  *     b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
4008  *
4009  */
4010 
4011 static VALUE
4012 rb_ary_uniq(VALUE ary)
4013 {
4014     VALUE hash, uniq, v;
4015     long i;
4016 
4017     if (RARRAY_LEN(ary) <= 1)
4018         return rb_ary_dup(ary);
4019     if (rb_block_given_p()) {
4020         hash = ary_make_hash_by(ary);
4021         uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
4022         st_foreach(RHASH_TBL(hash), push_value, uniq);
4023     }
4024     else {
4025         hash = ary_make_hash(ary);
4026         uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
4027         for (i=0; i<RARRAY_LEN(ary); i++) {
4028             st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
4029             if (st_delete(RHASH_TBL(hash), &vv, 0)) {
4030                 rb_ary_push(uniq, v);
4031             }
4032         }
4033     }
4034     ary_recycle_hash(hash);
4035 
4036     return uniq;
4037 }
4038 
4039 /*
4040  *  call-seq:
4041  *     ary.compact!    -> ary  or  nil
4042  *
4043  *  Removes +nil+ elements from the array.
4044  *
4045  *  Returns +nil+ if no changes were made, otherwise returns the array.
4046  *
4047  *     [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
4048  *     [ "a", "b", "c" ].compact!           #=> nil
4049  */
4050 
4051 static VALUE
4052 rb_ary_compact_bang(VALUE ary)
4053 {
4054     VALUE *p, *t, *end;
4055     long n;
4056 
4057     rb_ary_modify(ary);
4058     p = t = RARRAY_PTR(ary);
4059     end = p + RARRAY_LEN(ary);
4060 
4061     while (t < end) {
4062         if (NIL_P(*t)) t++;
4063         else *p++ = *t++;
4064     }
4065     n = p - RARRAY_PTR(ary);
4066     if (RARRAY_LEN(ary) == n) {
4067         return Qnil;
4068     }
4069     ARY_SET_LEN(ary, n);
4070     if (n * 2 < ARY_CAPA(ary) && ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
4071         ary_resize_capa(ary, n * 2);
4072     }
4073 
4074     return ary;
4075 }
4076 
4077 /*
4078  *  call-seq:
4079  *     ary.compact     -> new_ary
4080  *
4081  *  Returns a copy of +self+ with all +nil+ elements removed.
4082  *
4083  *     [ "a", nil, "b", nil, "c", nil ].compact
4084  *                       #=> [ "a", "b", "c" ]
4085  */
4086 
4087 static VALUE
4088 rb_ary_compact(VALUE ary)
4089 {
4090     ary = rb_ary_dup(ary);
4091     rb_ary_compact_bang(ary);
4092     return ary;
4093 }
4094 
4095 /*
4096  *  call-seq:
4097  *     ary.count                   -> int
4098  *     ary.count(obj)              -> int
4099  *     ary.count { |item| block }  -> int
4100  *
4101  *  Returns the number of elements.
4102  *
4103  *  If an argument is given, counts the number of elements which equal +obj+
4104  *  using <code>===</code>.
4105  *
4106  *  If a block is given, counts the number of elements for which the block
4107  *  returns a true value.
4108  *
4109  *     ary = [1, 2, 4, 2]
4110  *     ary.count                  #=> 4
4111  *     ary.count(2)               #=> 2
4112  *     ary.count { |x| x%2 == 0 } #=> 3
4113  *
4114  */
4115 
4116 static VALUE
4117 rb_ary_count(int argc, VALUE *argv, VALUE ary)
4118 {
4119     long n = 0;
4120 
4121     if (argc == 0) {
4122         VALUE *p, *pend;
4123 
4124         if (!rb_block_given_p())
4125             return LONG2NUM(RARRAY_LEN(ary));
4126 
4127         for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
4128             if (RTEST(rb_yield(*p))) n++;
4129         }
4130     }
4131     else {
4132         VALUE obj, *p, *pend;
4133 
4134         rb_scan_args(argc, argv, "1", &obj);
4135         if (rb_block_given_p()) {
4136             rb_warn("given block not used");
4137         }
4138         for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
4139             if (rb_equal(*p, obj)) n++;
4140         }
4141     }
4142 
4143     return LONG2NUM(n);
4144 }
4145 
4146 static VALUE
4147 flatten(VALUE ary, int level, int *modified)
4148 {
4149     long i = 0;
4150     VALUE stack, result, tmp, elt;
4151     st_table *memo;
4152     st_data_t id;
4153 
4154     stack = ary_new(0, ARY_DEFAULT_SIZE);
4155     result = ary_new(0, RARRAY_LEN(ary));
4156     memo = st_init_numtable();
4157     st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
4158     *modified = 0;
4159 
4160     while (1) {
4161         while (i < RARRAY_LEN(ary)) {
4162             elt = RARRAY_PTR(ary)[i++];
4163             tmp = rb_check_array_type(elt);
4164             if (RBASIC(result)->klass) {
4165                 rb_raise(rb_eRuntimeError, "flatten reentered");
4166             }
4167             if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
4168                 rb_ary_push(result, elt);
4169             }
4170             else {
4171                 *modified = 1;
4172                 id = (st_data_t)tmp;
4173                 if (st_lookup(memo, id, 0)) {
4174                     st_free_table(memo);
4175                     rb_raise(rb_eArgError, "tried to flatten recursive array");
4176                 }
4177                 st_insert(memo, id, (st_data_t)Qtrue);
4178                 rb_ary_push(stack, ary);
4179                 rb_ary_push(stack, LONG2NUM(i));
4180                 ary = tmp;
4181                 i = 0;
4182             }
4183         }
4184         if (RARRAY_LEN(stack) == 0) {
4185             break;
4186         }
4187         id = (st_data_t)ary;
4188         st_delete(memo, &id, 0);
4189         tmp = rb_ary_pop(stack);
4190         i = NUM2LONG(tmp);
4191         ary = rb_ary_pop(stack);
4192     }
4193 
4194     st_free_table(memo);
4195 
4196     RBASIC(result)->klass = rb_class_of(ary);
4197     return result;
4198 }
4199 
4200 /*
4201  *  call-seq:
4202  *     ary.flatten!        -> ary or nil
4203  *     ary.flatten!(level) -> ary or nil
4204  *
4205  *  Flattens +self+ in place.
4206  *
4207  *  Returns +nil+ if no modifications were made (i.e., the array contains no
4208  *  subarrays.)
4209  *
4210  *  The optional +level+ argument determines the level of recursion to flatten.
4211  *
4212  *     a = [ 1, 2, [3, [4, 5] ] ]
4213  *     a.flatten!   #=> [1, 2, 3, 4, 5]
4214  *     a.flatten!   #=> nil
4215  *     a            #=> [1, 2, 3, 4, 5]
4216  *     a = [ 1, 2, [3, [4, 5] ] ]
4217  *     a.flatten!(1) #=> [1, 2, 3, [4, 5]]
4218  */
4219 
4220 static VALUE
4221 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
4222 {
4223     int mod = 0, level = -1;
4224     VALUE result, lv;
4225 
4226     rb_scan_args(argc, argv, "01", &lv);
4227     rb_ary_modify_check(ary);
4228     if (!NIL_P(lv)) level = NUM2INT(lv);
4229     if (level == 0) return Qnil;
4230 
4231     result = flatten(ary, level, &mod);
4232     if (mod == 0) {
4233         ary_discard(result);
4234         return Qnil;
4235     }
4236     if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
4237     rb_ary_replace(ary, result);
4238     if (mod) ARY_SET_EMBED_LEN(result, 0);
4239 
4240     return ary;
4241 }
4242 
4243 /*
4244  *  call-seq:
4245  *     ary.flatten -> new_ary
4246  *     ary.flatten(level) -> new_ary
4247  *
4248  *  Returns a new array that is a one-dimensional flattening of +self+
4249  *  (recursively).
4250  *
4251  *  That is, for every element that is an array, extract its elements into
4252  *  the new array.
4253  *
4254  *  The optional +level+ argument determines the level of recursion to
4255  *  flatten.
4256  *
4257  *     s = [ 1, 2, 3 ]           #=> [1, 2, 3]
4258  *     t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
4259  *     a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
4260  *     a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
4261  *     a = [ 1, 2, [3, [4, 5] ] ]
4262  *     a.flatten(1)              #=> [1, 2, 3, [4, 5]]
4263  */
4264 
4265 static VALUE
4266 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
4267 {
4268     int mod = 0, level = -1;
4269     VALUE result, lv;
4270 
4271     rb_scan_args(argc, argv, "01", &lv);
4272     if (!NIL_P(lv)) level = NUM2INT(lv);
4273     if (level == 0) return ary_make_shared_copy(ary);
4274 
4275     result = flatten(ary, level, &mod);
4276     OBJ_INFECT(result, ary);
4277 
4278     return result;
4279 }
4280 
4281 #define OPTHASH_GIVEN_P(opts) \
4282     (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
4283 static VALUE sym_random;
4284 
4285 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
4286 
4287 /*
4288  *  call-seq:
4289  *     ary.shuffle!              -> ary
4290  *     ary.shuffle!(random: rng) -> ary
4291  *
4292  *  Shuffles elements in +self+ in place.
4293  *
4294  *  The optional +rng+ argument will be used as the random number generator.
4295  */
4296 
4297 static VALUE
4298 rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
4299 {
4300     VALUE *ptr, opts, *snap_ptr, randgen = rb_cRandom;
4301     long i, snap_len;
4302 
4303     if (OPTHASH_GIVEN_P(opts)) {
4304         randgen = rb_hash_lookup2(opts, sym_random, randgen);
4305     }
4306     rb_check_arity(argc, 0, 0);
4307     rb_ary_modify(ary);
4308     i = RARRAY_LEN(ary);
4309     ptr = RARRAY_PTR(ary);
4310     snap_len = i;
4311     snap_ptr = ptr;
4312     while (i) {
4313         long j = RAND_UPTO(i);
4314         VALUE tmp;
4315         if (snap_len != RARRAY_LEN(ary) || snap_ptr != RARRAY_PTR(ary)) {
4316             rb_raise(rb_eRuntimeError, "modified during shuffle");
4317         }
4318         tmp = ptr[--i];
4319         ptr[i] = ptr[j];
4320         ptr[j] = tmp;
4321     }
4322     return ary;
4323 }
4324 
4325 
4326 /*
4327  *  call-seq:
4328  *     ary.shuffle              -> new_ary
4329  *     ary.shuffle(random: rng) -> new_ary
4330  *
4331  *  Returns a new array with elements of +self+ shuffled.
4332  *
4333  *     a = [ 1, 2, 3 ]           #=> [1, 2, 3]
4334  *     a.shuffle                 #=> [2, 3, 1]
4335  *
4336  *  The optional +rng+ argument will be used as the random number generator.
4337  *
4338  *     a.shuffle(random: Random.new(1))  #=> [1, 3, 2]
4339  */
4340 
4341 static VALUE
4342 rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
4343 {
4344     ary = rb_ary_dup(ary);
4345     rb_ary_shuffle_bang(argc, argv, ary);
4346     return ary;
4347 }
4348 
4349 
4350 /*
4351  *  call-seq:
4352  *     ary.sample                  -> obj
4353  *     ary.sample(random: rng)     -> obj
4354  *     ary.sample(n)               -> new_ary
4355  *     ary.sample(n, random: rng)  -> new_ary
4356  *
4357  *  Choose a random element or +n+ random elements from the array.
4358  *
4359  *  The elements are chosen by using random and unique indices into the array
4360  *  in order to ensure that an element doesn't repeat itself unless the array
4361  *  already contained duplicate elements.
4362  *
4363  *  If the array is empty the first form returns +nil+ and the second form
4364  *  returns an empty array.
4365  *
4366  *  The optional +rng+ argument will be used as the random number generator.
4367  *
4368  *     a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
4369  *     a.sample         #=> 7
4370  *     a.sample(4)      #=> [6, 4, 2, 5]
4371  */
4372 
4373 
4374 static VALUE
4375 rb_ary_sample(int argc, VALUE *argv, VALUE ary)
4376 {
4377     VALUE nv, result, *ptr;
4378     VALUE opts, randgen = rb_cRandom;
4379     long n, len, i, j, k, idx[10];
4380     long rnds[numberof(idx)];
4381 
4382     if (OPTHASH_GIVEN_P(opts)) {
4383         randgen = rb_hash_lookup2(opts, sym_random, randgen);
4384     }
4385     ptr = RARRAY_PTR(ary);
4386     len = RARRAY_LEN(ary);
4387     if (argc == 0) {
4388         if (len == 0) return Qnil;
4389         if (len == 1) {
4390             i = 0;
4391         }
4392         else {
4393             i = RAND_UPTO(len);
4394             if ((len = RARRAY_LEN(ary)) <= i) return Qnil;
4395             ptr = RARRAY_PTR(ary);
4396         }
4397         return ptr[i];
4398     }
4399     rb_scan_args(argc, argv, "1", &nv);
4400     n = NUM2LONG(nv);
4401     if (n < 0) rb_raise(rb_eArgError, "negative sample number");
4402     if (n > len) n = len;
4403     if (n <= numberof(idx)) {
4404         for (i = 0; i < n; ++i) {
4405             rnds[i] = RAND_UPTO(len - i);
4406         }
4407     }
4408     k = len;
4409     len = RARRAY_LEN(ary);
4410     ptr = RARRAY_PTR(ary);
4411     if (len < k) {
4412         if (n <= numberof(idx)) {
4413             for (i = 0; i < n; ++i) {
4414                 if (rnds[i] >= len) {
4415                     return rb_ary_new2(0);
4416                 }
4417             }
4418         }
4419     }
4420     if (n > len) n = len;
4421     switch (n) {
4422       case 0:
4423         return rb_ary_new2(0);
4424       case 1:
4425         i = rnds[0];
4426         return rb_ary_new4(1, &ptr[i]);
4427       case 2:
4428         i = rnds[0];
4429         j = rnds[1];
4430         if (j >= i) j++;
4431         return rb_ary_new3(2, ptr[i], ptr[j]);
4432       case 3:
4433         i = rnds[0];
4434         j = rnds[1];
4435         k = rnds[2];
4436         {
4437             long l = j, g = i;
4438             if (j >= i) l = i, g = ++j;
4439             if (k >= l && (++k >= g)) ++k;
4440         }
4441         return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
4442     }
4443     if (n <= numberof(idx)) {
4444         VALUE *ptr_result;
4445         long sorted[numberof(idx)];
4446         sorted[0] = idx[0] = rnds[0];
4447         for (i=1; i<n; i++) {
4448             k = rnds[i];
4449             for (j = 0; j < i; ++j) {
4450                 if (k < sorted[j]) break;
4451                 ++k;
4452             }
4453             memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
4454             sorted[j] = idx[i] = k;
4455         }
4456         result = rb_ary_new2(n);
4457         ptr_result = RARRAY_PTR(result);
4458         for (i=0; i<n; i++) {
4459             ptr_result[i] = ptr[idx[i]];
4460         }
4461     }
4462     else {
4463         VALUE *ptr_result;
4464         result = rb_ary_new4(len, ptr);
4465         RBASIC(result)->klass = 0;
4466         ptr_result = RARRAY_PTR(result);
4467         RB_GC_GUARD(ary);
4468         for (i=0; i<n; i++) {
4469             j = RAND_UPTO(len-i) + i;
4470             nv = ptr_result[j];
4471             ptr_result[j] = ptr_result[i];
4472             ptr_result[i] = nv;
4473         }
4474         RBASIC(result)->klass = rb_cArray;
4475     }
4476     ARY_SET_LEN(result, n);
4477 
4478     return result;
4479 }
4480 
4481 static VALUE
4482 rb_ary_cycle_size(VALUE self, VALUE args)
4483 {
4484     long mul;
4485     VALUE n = Qnil;
4486     if (args && (RARRAY_LEN(args) > 0)) {
4487         n = RARRAY_PTR(args)[0];
4488     }
4489     if (RARRAY_LEN(self) == 0) return INT2FIX(0);
4490     if (n == Qnil) return DBL2NUM(INFINITY);
4491     mul = NUM2LONG(n);
4492     if (mul <= 0) return INT2FIX(0);
4493     return rb_funcall(rb_ary_length(self), '*', 1, LONG2FIX(mul));
4494 }
4495 
4496 /*
4497  *  call-seq:
4498  *     ary.cycle(n=nil) { |obj| block }  -> nil
4499  *     ary.cycle(n=nil)                  -> Enumerator
4500  *
4501  *  Calls the given block for each element +n+ times or forever if +nil+ is
4502  *  given.
4503  *
4504  *  Does nothing if a non-positive number is given or the array is empty.
4505  *
4506  *  Returns +nil+ if the loop has finished without getting interrupted.
4507  *
4508  *  If no block is given, an Enumerator is returned instead.
4509  *
4510  *     a = ["a", "b", "c"]
4511  *     a.cycle { |x| puts x }     # print, a, b, c, a, b, c,.. forever.
4512  *     a.cycle(2) { |x| puts x }  # print, a, b, c, a, b, c.
4513  *
4514  */
4515 
4516 static VALUE
4517 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
4518 {
4519     long n, i;
4520     VALUE nv = Qnil;
4521 
4522     rb_scan_args(argc, argv, "01", &nv);
4523 
4524     RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
4525     if (NIL_P(nv)) {
4526         n = -1;
4527     }
4528     else {
4529         n = NUM2LONG(nv);
4530         if (n <= 0) return Qnil;
4531     }
4532 
4533     while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
4534         for (i=0; i<RARRAY_LEN(ary); i++) {
4535             rb_yield(RARRAY_PTR(ary)[i]);
4536         }
4537     }
4538     return Qnil;
4539 }
4540 
4541 #define tmpbuf(n, size) rb_str_tmp_new((n)*(size))
4542 #define tmpbuf_discard(s) (rb_str_resize((s), 0L), RBASIC(s)->klass = rb_cString)
4543 #define tmpary(n) rb_ary_tmp_new(n)
4544 #define tmpary_discard(a) (ary_discard(a), RBASIC(a)->klass = rb_cArray)
4545 
4546 /*
4547  * Recursively compute permutations of +r+ elements of the set
4548  * <code>[0..n-1]</code>.
4549  *
4550  * When we have a complete permutation of array indexes, copy the values
4551  * at those indexes into a new array and yield that array.
4552  *
4553  * n: the size of the set
4554  * r: the number of elements in each permutation
4555  * p: the array (of size r) that we're filling in
4556  * index: what index we're filling in now
4557  * used: an array of booleans: whether a given index is already used
4558  * values: the Ruby array that holds the actual values to permute
4559  */
4560 static void
4561 permute0(long n, long r, long *p, long index, char *used, VALUE values)
4562 {
4563     long i,j;
4564     for (i = 0; i < n; i++) {
4565         if (used[i] == 0) {
4566             p[index] = i;
4567             if (index < r-1) {             /* if not done yet */
4568                 used[i] = 1;               /* mark index used */
4569                 permute0(n, r, p, index+1, /* recurse */
4570                          used, values);
4571                 used[i] = 0;               /* index unused */
4572             }
4573             else {
4574                 /* We have a complete permutation of array indexes */
4575                 /* Build a ruby array of the corresponding values */
4576                 /* And yield it to the associated block */
4577                 VALUE result = rb_ary_new2(r);
4578                 VALUE *result_array = RARRAY_PTR(result);
4579                 const VALUE *values_array = RARRAY_PTR(values);
4580 
4581                 for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
4582                 ARY_SET_LEN(result, r);
4583                 rb_yield(result);
4584                 if (RBASIC(values)->klass) {
4585                     rb_raise(rb_eRuntimeError, "permute reentered");
4586                 }
4587             }
4588         }
4589     }
4590 }
4591 
4592 /*
4593  * Returns the product of from, from-1, ..., from - how_many + 1.
4594  * http://en.wikipedia.org/wiki/Pochhammer_symbol
4595  */
4596 static VALUE
4597 descending_factorial(long from, long how_many)
4598 {
4599     VALUE cnt = LONG2FIX(how_many >= 0);
4600     while (how_many-- > 0) {
4601         cnt = rb_funcall(cnt, '*', 1, LONG2FIX(from--));
4602     }
4603     return cnt;
4604 }
4605 
4606 static VALUE
4607 binomial_coefficient(long comb, long size)
4608 {
4609     if (comb > size-comb) {
4610         comb = size-comb;
4611     }
4612     if (comb < 0) {
4613         return LONG2FIX(0);
4614     }
4615     return rb_funcall(descending_factorial(size, comb), id_div, 1, descending_factorial(comb, comb));
4616 }
4617 
4618 static VALUE
4619 rb_ary_permutation_size(VALUE ary, VALUE args)
4620 {
4621     long n = RARRAY_LEN(ary);
4622     long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_PTR(args)[0]) : n;
4623 
4624     return descending_factorial(n, k);
4625 }
4626 
4627 /*
4628  *  call-seq:
4629  *     ary.permutation { |p| block }          -> ary
4630  *     ary.permutation                        -> Enumerator
4631  *     ary.permutation(n) { |p| block }       -> ary
4632  *     ary.permutation(n)                     -> Enumerator
4633  *
4634  * When invoked with a block, yield all permutations of length +n+ of the
4635  * elements of the array, then return the array itself.
4636  *
4637  * If +n+ is not specified, yield all permutations of all elements.
4638  *
4639  * The implementation makes no guarantees about the order in which the
4640  * permutations are yielded.
4641  *
4642  * If no block is given, an Enumerator is returned instead.
4643  *
4644  * Examples:
4645  *
4646  *   a = [1, 2, 3]
4647  *   a.permutation.to_a    #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
4648  *   a.permutation(1).to_a #=> [[1],[2],[3]]
4649  *   a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
4650  *   a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
4651  *   a.permutation(0).to_a #=> [[]] # one permutation of length 0
4652  *   a.permutation(4).to_a #=> []   # no permutations of length 4
4653  */
4654 
4655 static VALUE
4656 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
4657 {
4658     VALUE num;
4659     long r, n, i;
4660 
4661     n = RARRAY_LEN(ary);                  /* Array length */
4662     RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size);   /* Return enumerator if no block */
4663     rb_scan_args(argc, argv, "01", &num);
4664     r = NIL_P(num) ? n : NUM2LONG(num);   /* Permutation size from argument */
4665 
4666     if (r < 0 || n < r) {
4667         /* no permutations: yield nothing */
4668     }
4669     else if (r == 0) { /* exactly one permutation: the zero-length array */
4670         rb_yield(rb_ary_new2(0));
4671     }
4672     else if (r == 1) { /* this is a special, easy case */
4673         for (i = 0; i < RARRAY_LEN(ary); i++) {
4674             rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
4675         }
4676     }
4677     else {             /* this is the general case */
4678         volatile VALUE t0 = tmpbuf(n,sizeof(long));
4679         long *p = (long*)RSTRING_PTR(t0);
4680         volatile VALUE t1 = tmpbuf(n,sizeof(char));
4681         char *used = (char*)RSTRING_PTR(t1);
4682         VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
4683         RBASIC(ary0)->klass = 0;
4684 
4685         MEMZERO(used, char, n); /* initialize array */
4686 
4687         permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
4688         tmpbuf_discard(t0);
4689         tmpbuf_discard(t1);
4690         RBASIC(ary0)->klass = rb_cArray;
4691     }
4692     return ary;
4693 }
4694 
4695 static VALUE
4696 rb_ary_combination_size(VALUE ary, VALUE args)
4697 {
4698     long n = RARRAY_LEN(ary);
4699     long k = NUM2LONG(RARRAY_PTR(args)[0]);
4700 
4701     return binomial_coefficient(k, n);
4702 }
4703 
4704 /*
4705  *  call-seq:
4706  *     ary.combination(n) { |c| block }    -> ary
4707  *     ary.combination(n)                  -> Enumerator
4708  *
4709  * When invoked with a block, yields all combinations of length +n+ of elements
4710  * from the array and then returns the array itself.
4711  *
4712  * The implementation makes no guarantees about the order in which the
4713  * combinations are yielded.
4714  *
4715  * If no block is given, an Enumerator is returned instead.
4716  *
4717  * Examples:
4718  *
4719  *     a = [1, 2, 3, 4]
4720  *     a.combination(1).to_a  #=> [[1],[2],[3],[4]]
4721  *     a.combination(2).to_a  #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
4722  *     a.combination(3).to_a  #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
4723  *     a.combination(4).to_a  #=> [[1,2,3,4]]
4724  *     a.combination(0).to_a  #=> [[]] # one combination of length 0
4725  *     a.combination(5).to_a  #=> []   # no combinations of length 5
4726  *
4727  */
4728 
4729 static VALUE
4730 rb_ary_combination(VALUE ary, VALUE num)
4731 {
4732     long n, i, len;
4733 
4734     n = NUM2LONG(num);
4735     RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
4736     len = RARRAY_LEN(ary);
4737     if (n < 0 || len < n) {
4738         /* yield nothing */
4739     }
4740     else if (n == 0) {
4741         rb_yield(rb_ary_new2(0));
4742     }
4743     else if (n == 1) {
4744         for (i = 0; i < len; i++) {
4745             rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
4746         }
4747     }
4748     else {
4749         volatile VALUE t0 = tmpbuf(n+1, sizeof(long));
4750         long *stack = (long*)RSTRING_PTR(t0);
4751         volatile VALUE cc = tmpary(n);
4752         VALUE *chosen = RARRAY_PTR(cc);
4753         long lev = 0;
4754 
4755         MEMZERO(stack, long, n);
4756         stack[0] = -1;
4757         for (;;) {
4758             chosen[lev] = RARRAY_PTR(ary)[stack[lev+1]];
4759             for (lev++; lev < n; lev++) {
4760                 chosen[lev] = RARRAY_PTR(ary)[stack[lev+1] = stack[lev]+1];
4761             }
4762             rb_yield(rb_ary_new4(n, chosen));
4763             if (RBASIC(t0)->klass) {
4764                 rb_raise(rb_eRuntimeError, "combination reentered");
4765             }
4766             do {
4767                 if (lev == 0) goto done;
4768                 stack[lev--]++;
4769             } while (stack[lev+1]+n == len+lev+1);
4770         }
4771     done:
4772         tmpbuf_discard(t0);
4773         tmpary_discard(cc);
4774     }
4775     return ary;
4776 }
4777 
4778 /*
4779  * Recursively compute repeated permutations of +r+ elements of the set
4780  * <code>[0..n-1]</code>.
4781  *
4782  * When we have a complete repeated permutation of array indexes, copy the
4783  * values at those indexes into a new array and yield that array.
4784  *
4785  * n: the size of the set
4786  * r: the number of elements in each permutation
4787  * p: the array (of size r) that we're filling in
4788  * index: what index we're filling in now
4789  * values: the Ruby array that holds the actual values to permute
4790  */
4791 static void
4792 rpermute0(long n, long r, long *p, long index, VALUE values)
4793 {
4794     long i, j;
4795     for (i = 0; i < n; i++) {
4796         p[index] = i;
4797         if (index < r-1) {              /* if not done yet */
4798             rpermute0(n, r, p, index+1, values); /* recurse */
4799         }
4800         else {
4801             /* We have a complete permutation of array indexes */
4802             /* Build a ruby array of the corresponding values */
4803             /* And yield it to the associated block */
4804             VALUE result = rb_ary_new2(r);
4805             VALUE *result_array = RARRAY_PTR(result);
4806             const VALUE *values_array = RARRAY_PTR(values);
4807 
4808             for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
4809             ARY_SET_LEN(result, r);
4810             rb_yield(result);
4811             if (RBASIC(values)->klass) {
4812                 rb_raise(rb_eRuntimeError, "repeated permute reentered");
4813             }
4814         }
4815     }
4816 }
4817 
4818 static VALUE
4819 rb_ary_repeated_permutation_size(VALUE ary, VALUE args)
4820 {
4821     long n = RARRAY_LEN(ary);
4822     long k = NUM2LONG(RARRAY_PTR(args)[0]);
4823 
4824     if (k < 0) {
4825         return LONG2FIX(0);
4826     }
4827 
4828     return rb_funcall(LONG2NUM(n), id_power, 1, LONG2NUM(k));
4829 }
4830 
4831 /*
4832  *  call-seq:
4833  *     ary.repeated_permutation(n) { |p| block } -> ary
4834  *     ary.repeated_permutation(n)               -> Enumerator
4835  *
4836  * When invoked with a block, yield all repeated permutations of length +n+ of
4837  * the elements of the array, then return the array itself.
4838  *
4839  * The implementation makes no guarantees about the order in which the repeated
4840  * permutations are yielded.
4841  *
4842  * If no block is given, an Enumerator is returned instead.
4843  *
4844  * Examples:
4845  *
4846  *     a = [1, 2]
4847  *     a.repeated_permutation(1).to_a  #=> [[1], [2]]
4848  *     a.repeated_permutation(2).to_a  #=> [[1,1],[1,2],[2,1],[2,2]]
4849  *     a.repeated_permutation(3).to_a  #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2],
4850  *                                     #    [2,1,1],[2,1,2],[2,2,1],[2,2,2]]
4851  *     a.repeated_permutation(0).to_a  #=> [[]] # one permutation of length 0
4852  */
4853 
4854 static VALUE
4855 rb_ary_repeated_permutation(VALUE ary, VALUE num)
4856 {
4857     long r, n, i;
4858 
4859     n = RARRAY_LEN(ary);                  /* Array length */
4860     RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size);      /* Return Enumerator if no block */
4861     r = NUM2LONG(num);                    /* Permutation size from argument */
4862 
4863     if (r < 0) {
4864         /* no permutations: yield nothing */
4865     }
4866     else if (r == 0) { /* exactly one permutation: the zero-length array */
4867         rb_yield(rb_ary_new2(0));
4868     }
4869     else if (r == 1) { /* this is a special, easy case */
4870         for (i = 0; i < RARRAY_LEN(ary); i++) {
4871             rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
4872         }
4873     }
4874     else {             /* this is the general case */
4875         volatile VALUE t0 = tmpbuf(r, sizeof(long));
4876         long *p = (long*)RSTRING_PTR(t0);
4877         VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
4878         RBASIC(ary0)->klass = 0;
4879 
4880         rpermute0(n, r, p, 0, ary0); /* compute and yield repeated permutations */
4881         tmpbuf_discard(t0);
4882         RBASIC(ary0)->klass = rb_cArray;
4883     }
4884     return ary;
4885 }
4886 
4887 static void
4888 rcombinate0(long n, long r, long *p, long index, long rest, VALUE values)
4889 {
4890     long j;
4891     if (rest > 0) {
4892         for (; index < n; ++index) {
4893             p[r-rest] = index;
4894             rcombinate0(n, r, p, index, rest-1, values);
4895         }
4896     }
4897     else {
4898         VALUE result = rb_ary_new2(r);
4899         VALUE *result_array = RARRAY_PTR(result);
4900         const VALUE *values_array = RARRAY_PTR(values);
4901 
4902         for (j = 0; j < r; ++j) result_array[j] = values_array[p[j]];
4903         ARY_SET_LEN(result, r);
4904         rb_yield(result);
4905         if (RBASIC(values)->klass) {
4906             rb_raise(rb_eRuntimeError, "repeated combination reentered");
4907         }
4908     }
4909 }
4910 
4911 static VALUE
4912 rb_ary_repeated_combination_size(VALUE ary, VALUE args)
4913 {
4914     long n = RARRAY_LEN(ary);
4915     long k = NUM2LONG(RARRAY_PTR(args)[0]);
4916     if (k == 0) {
4917         return LONG2FIX(1);
4918     }
4919     return binomial_coefficient(k, n + k - 1);
4920 }
4921 
4922 /*
4923  *  call-seq:
4924  *     ary.repeated_combination(n) { |c| block } -> ary
4925  *     ary.repeated_combination(n)               -> Enumerator
4926  *
4927  * When invoked with a block, yields all repeated combinations of length +n+ of
4928  * elements from the array and then returns the array itself.
4929  *
4930  * The implementation makes no guarantees about the order in which the repeated
4931  * combinations are yielded.
4932  *
4933  * If no block is given, an Enumerator is returned instead.
4934  *
4935  * Examples:
4936  *
4937  *   a = [1, 2, 3]
4938  *   a.repeated_combination(1).to_a  #=> [[1], [2], [3]]
4939  *   a.repeated_combination(2).to_a  #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
4940  *   a.repeated_combination(3).to_a  #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],
4941  *                                   #    [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]
4942  *   a.repeated_combination(4).to_a  #=> [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3],
4943  *                                   #    [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3],
4944  *                                   #    [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]]
4945  *   a.repeated_combination(0).to_a  #=> [[]] # one combination of length 0
4946  *
4947  */
4948 
4949 static VALUE
4950 rb_ary_repeated_combination(VALUE ary, VALUE num)
4951 {
4952     long n, i, len;
4953 
4954     n = NUM2LONG(num);                 /* Combination size from argument */
4955     RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size);   /* Return enumerator if no block */
4956     len = RARRAY_LEN(ary);
4957     if (n < 0) {
4958         /* yield nothing */
4959     }
4960     else if (n == 0) {
4961         rb_yield(rb_ary_new2(0));
4962     }
4963     else if (n == 1) {
4964         for (i = 0; i < len; i++) {
4965             rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
4966         }
4967     }
4968     else if (len == 0) {
4969         /* yield nothing */
4970     }
4971     else {
4972         volatile VALUE t0 = tmpbuf(n, sizeof(long));
4973         long *p = (long*)RSTRING_PTR(t0);
4974         VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
4975         RBASIC(ary0)->klass = 0;
4976 
4977         rcombinate0(len, n, p, 0, n, ary0); /* compute and yield repeated combinations */
4978         tmpbuf_discard(t0);
4979         RBASIC(ary0)->klass = rb_cArray;
4980     }
4981     return ary;
4982 }
4983 
4984 /*
4985  *  call-seq:
4986  *     ary.product(other_ary, ...)                -> new_ary
4987  *     ary.product(other_ary, ...) { |p| block }  -> ary
4988  *
4989  *  Returns an array of all combinations of elements from all arrays.
4990  *
4991  *  The length of the returned array is the product of the length of +self+ and
4992  *  the argument arrays.
4993  *
4994  *  If given a block, #product will yield all combinations and return +self+
4995  *  instead.
4996  *
4997  *     [1,2,3].product([4,5])     #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
4998  *     [1,2].product([1,2])       #=> [[1,1],[1,2],[2,1],[2,2]]
4999  *     [1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
5000  *                                #     [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
5001  *     [1,2].product()            #=> [[1],[2]]
5002  *     [1,2].product([])          #=> []
5003  */
5004 
5005 static VALUE
5006 rb_ary_product(int argc, VALUE *argv, VALUE ary)
5007 {
5008     int n = argc+1;    /* How many arrays we're operating on */
5009     volatile VALUE t0 = tmpary(n);
5010     volatile VALUE t1 = tmpbuf(n, sizeof(int));
5011     VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
5012     int *counters = (int*)RSTRING_PTR(t1); /* The current position in each one */
5013     VALUE result = Qnil;      /* The array we'll be returning, when no block given */
5014     long i,j;
5015     long resultlen = 1;
5016 
5017     RBASIC(t0)->klass = 0;
5018     RBASIC(t1)->klass = 0;
5019 
5020     /* initialize the arrays of arrays */
5021     ARY_SET_LEN(t0, n);
5022     arrays[0] = ary;
5023     for (i = 1; i < n; i++) arrays[i] = Qnil;
5024     for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
5025 
5026     /* initialize the counters for the arrays */
5027     for (i = 0; i < n; i++) counters[i] = 0;
5028 
5029     /* Otherwise, allocate and fill in an array of results */
5030     if (rb_block_given_p()) {
5031         /* Make defensive copies of arrays; exit if any is empty */
5032         for (i = 0; i < n; i++) {
5033             if (RARRAY_LEN(arrays[i]) == 0) goto done;
5034             arrays[i] = ary_make_shared_copy(arrays[i]);
5035         }
5036     }
5037     else {
5038         /* Compute the length of the result array; return [] if any is empty */
5039         for (i = 0; i < n; i++) {
5040             long k = RARRAY_LEN(arrays[i]);
5041             if (k == 0) {
5042                 result = rb_ary_new2(0);
5043                 goto done;
5044             }
5045             if (MUL_OVERFLOW_LONG_P(resultlen, k))
5046                 rb_raise(rb_eRangeError, "too big to product");
5047             resultlen *= k;
5048         }
5049         result = rb_ary_new2(resultlen);
5050     }
5051     for (;;) {
5052         int m;
5053         /* fill in one subarray */
5054         VALUE subarray = rb_ary_new2(n);
5055         for (j = 0; j < n; j++) {
5056             rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
5057         }
5058 
5059         /* put it on the result array */
5060         if (NIL_P(result)) {
5061             FL_SET(t0, FL_USER5);
5062             rb_yield(subarray);
5063             if (! FL_TEST(t0, FL_USER5)) {
5064                 rb_raise(rb_eRuntimeError, "product reentered");
5065             }
5066             else {
5067                 FL_UNSET(t0, FL_USER5);
5068             }
5069         }
5070         else {
5071             rb_ary_push(result, subarray);
5072         }
5073 
5074         /*
5075          * Increment the last counter.  If it overflows, reset to 0
5076          * and increment the one before it.
5077          */
5078         m = n-1;
5079         counters[m]++;
5080         while (counters[m] == RARRAY_LEN(arrays[m])) {
5081             counters[m] = 0;
5082             /* If the first counter overflows, we are done */
5083             if (--m < 0) goto done;
5084             counters[m]++;
5085         }
5086     }
5087 done:
5088     tmpary_discard(t0);
5089     tmpbuf_discard(t1);
5090 
5091     return NIL_P(result) ? ary : result;
5092 }
5093 
5094 /*
5095  *  call-seq:
5096  *     ary.take(n)               -> new_ary
5097  *
5098  *  Returns first +n+ elements from the array.
5099  *
5100  *  If a negative number is given, raises an ArgumentError.
5101  *
5102  *  See also Array#drop
5103  *
5104  *     a = [1, 2, 3, 4, 5, 0]
5105  *     a.take(3)             #=> [1, 2, 3]
5106  *
5107  */
5108 
5109 static VALUE
5110 rb_ary_take(VALUE obj, VALUE n)
5111 {
5112     long len = NUM2LONG(n);
5113     if (len < 0) {
5114         rb_raise(rb_eArgError, "attempt to take negative size");
5115     }
5116     return rb_ary_subseq(obj, 0, len);
5117 }
5118 
5119 /*
5120  *  call-seq:
5121  *     ary.take_while { |arr| block }  -> new_ary
5122  *     ary.take_while                  -> Enumerator
5123  *
5124  *  Passes elements to the block until the block returns +nil+ or +false+, then
5125  *  stops iterating and returns an array of all prior elements.
5126  *
5127  *  If no block is given, an Enumerator is returned instead.
5128  *
5129  *  See also Array#drop_while
5130  *
5131  *     a = [1, 2, 3, 4, 5, 0]
5132  *     a.take_while { |i| i < 3 }  #=> [1, 2]
5133  *
5134  */
5135 
5136 static VALUE
5137 rb_ary_take_while(VALUE ary)
5138 {
5139     long i;
5140 
5141     RETURN_ENUMERATOR(ary, 0, 0);
5142     for (i = 0; i < RARRAY_LEN(ary); i++) {
5143         if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
5144     }
5145     return rb_ary_take(ary, LONG2FIX(i));
5146 }
5147 
5148 /*
5149  *  call-seq:
5150  *     ary.drop(n)               -> new_ary
5151  *
5152  *  Drops first +n+ elements from +ary+ and returns the rest of the elements in
5153  *  an array.
5154  *
5155  *  If a negative number is given, raises an ArgumentError.
5156  *
5157  *  See also Array#take
5158  *
5159  *     a = [1, 2, 3, 4, 5, 0]
5160  *     a.drop(3)             #=> [4, 5, 0]
5161  *
5162  */
5163 
5164 static VALUE
5165 rb_ary_drop(VALUE ary, VALUE n)
5166 {
5167     VALUE result;
5168     long pos = NUM2LONG(n);
5169     if (pos < 0) {
5170         rb_raise(rb_eArgError, "attempt to drop negative size");
5171     }
5172 
5173     result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
5174     if (result == Qnil) result = rb_ary_new();
5175     return result;
5176 }
5177 
5178 /*
5179  *  call-seq:
5180  *     ary.drop_while { |arr| block }   -> new_ary
5181  *     ary.drop_while                  -> Enumerator
5182  *
5183  *  Drops elements up to, but not including, the first element for which the
5184  *  block returns +nil+ or +false+ and returns an array containing the
5185  *  remaining elements.
5186  *
5187  *  If no block is given, an Enumerator is returned instead.
5188  *
5189  *  See also Array#take_while
5190  *
5191  *     a = [1, 2, 3, 4, 5, 0]
5192  *     a.drop_while {|i| i < 3 }   #=> [3, 4, 5, 0]
5193  *
5194  */
5195 
5196 static VALUE
5197 rb_ary_drop_while(VALUE ary)
5198 {
5199     long i;
5200 
5201     RETURN_ENUMERATOR(ary, 0, 0);
5202     for (i = 0; i < RARRAY_LEN(ary); i++) {
5203         if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
5204     }
5205     return rb_ary_drop(ary, LONG2FIX(i));
5206 }
5207 
5208 /*
5209  *  Arrays are ordered, integer-indexed collections of any object.
5210  *
5211  *  Array indexing starts at 0, as in C or Java.  A negative index is assumed
5212  *  to be relative to the end of the array---that is, an index of -1 indicates
5213  *  the last element of the array, -2 is the next to last element in the
5214  *  array, and so on.
5215  *
5216  *  == Creating Arrays
5217  *
5218  *  A new array can be created by using the literal constructor
5219  *  <code>[]</code>.  Arrays can contain different types of objects.  For
5220  *  example, the array below contains an Integer, a String and a Float:
5221  *
5222  *     ary = [1, "two", 3.0] #=> [1, "two", 3.0]
5223  *
5224  *  An array can also be created by explicitly calling Array.new with zero, one
5225  *  (the initial size of the Array) or two arguments (the initial size and a
5226  *  default object).
5227  *
5228  *     ary = Array.new    #=> []
5229  *     Array.new(3)       #=> [nil, nil, nil]
5230  *     Array.new(3, true) #=> [true, true, true]
5231  *
5232  *  Note that the second argument populates the array with references to the
5233  *  same object.  Therefore, it is only recommended in cases when you need to
5234  *  instantiate arrays with natively immutable objects such as Symbols,
5235  *  numbers, true or false.
5236  *
5237  *  To create an array with separate objects a block can be passed instead.
5238  *  This method is safe to use with mutable objects such as hashes, strings or
5239  *  other arrays:
5240  *
5241  *     Array.new(4) { Hash.new } #=> [{}, {}, {}, {}]
5242  *
5243  *  This is also a quick way to build up multi-dimensional arrays:
5244  *
5245  *     empty_table = Array.new(3) { Array.new(3) }
5246  *     #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
5247  *
5248  *  An array can also be created by using the Array() method, provided by
5249  *  Kernel, which tries to call #to_ary, then #to_a on its argument.
5250  *
5251  *      Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
5252  *
5253  *  == Example Usage
5254  *
5255  *  In addition to the methods it mixes in through the Enumerable module, the
5256  *  Array class has proprietary methods for accessing, searching and otherwise
5257  *  manipulating arrays.
5258  *
5259  *  Some of the more common ones are illustrated below.
5260  *
5261  *  == Accessing Elements
5262  *
5263  *  Elements in an array can be retrieved using the Array#[] method.  It can
5264  *  take a single integer argument (a numeric index), a pair of arguments
5265  *  (start and length) or a range.
5266  *
5267  *     arr = [1, 2, 3, 4, 5, 6]
5268  *     arr[2]    #=> 3
5269  *     arr[100]  #=> nil
5270  *     arr[-3]   #=> 4
5271  *     arr[2, 3] #=> [3, 4, 5]
5272  *     arr[1..4] #=> [2, 3, 4, 5]
5273  *
5274  *  Another way to access a particular array element is by using the #at method
5275  *
5276  *     arr.at(0) #=> 1
5277  *
5278  *  The #slice method works in an identical manner to Array#[].
5279  *
5280  *  To raise an error for indices outside of the array bounds or else to
5281  *  provide a default value when that happens, you can use #fetch.
5282  *
5283  *     arr = ['a', 'b', 'c', 'd', 'e', 'f']
5284  *     arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
5285  *     arr.fetch(100, "oops") #=> "oops"
5286  *
5287  *  The special methods #first and #last will return the first and last
5288  *  elements of an array, respectively.
5289  *
5290  *     arr.first #=> 1
5291  *     arr.last  #=> 6
5292  *
5293  *  To return the first +n+ elements of an array, use #take
5294  *
5295  *     arr.take(3) #=> [1, 2, 3]
5296  *
5297  *  #drop does the opposite of #take, by returning the elements after +n+
5298  *  elements have been dropped:
5299  *
5300  *     arr.drop(3) #=> [4, 5, 6]
5301  *
5302  *  == Obtaining Information about an Array
5303  *
5304  *  Arrays keep track of their own length at all times.  To query an array
5305  *  about the number of elements it contains, use #length, #count or #size.
5306  *
5307  *    browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
5308  *    browsers.length #=> 5
5309  *    browsers.count #=> 5
5310  *
5311  *  To check whether an array contains any elements at all
5312  *
5313  *    browsers.empty? #=> false
5314  *
5315  *  To check whether a particular item is included in the array
5316  *
5317  *    browsers.include?('Konqueror') #=> false
5318  *
5319  *  == Adding Items to Arrays
5320  *
5321  *  Items can be added to the end of an array by using either #push or #<<
5322  *
5323  *    arr = [1, 2, 3, 4]
5324  *    arr.push(5) #=> [1, 2, 3, 4, 5]
5325  *    arr << 6    #=> [1, 2, 3, 4, 5, 6]
5326  *
5327  *  #unshift will add a new item to the beginning of an array.
5328  *
5329  *     arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
5330  *
5331  *  With #insert you can add a new element to an array at any position.
5332  *
5333  *     arr.insert(3, 'apple')  #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
5334  *
5335  *  Using the #insert method, you can also insert multiple values at once:
5336  *
5337  *     arr.insert(3, 'orange', 'pear', 'grapefruit')
5338  *     #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
5339  *
5340  *  == Removing Items from an Array
5341  *
5342  *  The method #pop removes the last element in an array and returns it:
5343  *
5344  *     arr =  [1, 2, 3, 4, 5, 6]
5345  *     arr.pop #=> 6
5346  *     arr #=> [1, 2, 3, 4, 5]
5347  *
5348  *  To retrieve and at the same time remove the first item, use #shift:
5349  *
5350  *     arr.shift #=> 1
5351  *     arr #=> [2, 3, 4, 5]
5352  *
5353  *  To delete an element at a particular index:
5354  *
5355  *     arr.delete_at(2) #=> 4
5356  *     arr #=> [2, 3, 5]
5357  *
5358  *  To delete a particular element anywhere in an array, use #delete:
5359  *
5360  *     arr = [1, 2, 2, 3]
5361  *     arr.delete(2) #=> 2
5362  *     arr #=> [1,3]
5363  *
5364  *  A useful method if you need to remove +nil+ values from an array is
5365  *  #compact:
5366  *
5367  *     arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
5368  *     arr.compact  #=> ['foo', 0, 'bar', 7, 'baz']
5369  *     arr          #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
5370  *     arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
5371  *     arr          #=> ['foo', 0, 'bar', 7, 'baz']
5372  *
5373  *  Another common need is to remove duplicate elements from an array.
5374  *
5375  *  It has the non-destructive #uniq, and destructive method #uniq!
5376  *
5377  *     arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
5378  *     arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
5379  *
5380  *  == Iterating over Arrays
5381  *
5382  *  Like all classes that include the Enumerable module, Array has an each
5383  *  method, which defines what elements should be iterated over and how.  In
5384  *  case of Array's #each, all elements in the Array instance are yielded to
5385  *  the supplied block in sequence.
5386  *
5387  *  Note that this operation leaves the array unchanged.
5388  *
5389  *     arr = [1, 2, 3, 4, 5]
5390  *     arr.each { |a| print a -= 10, " " }
5391  *     # prints: -9 -8 -7 -6 -5
5392  *     #=> [1, 2, 3, 4, 5]
5393  *
5394  *  Another sometimes useful iterator is #reverse_each which will iterate over
5395  *  the elements in the array in reverse order.
5396  *
5397  *     words = %w[rats live on no evil star]
5398  *     str = ""
5399  *     words.reverse_each { |word| str += "#{word.reverse} " }
5400  *     str #=> "rats live on no evil star "
5401  *
5402  *  The #map method can be used to create a new array based on the original
5403  *  array, but with the values modified by the supplied block:
5404  *
5405  *     arr.map { |a| 2*a }   #=> [2, 4, 6, 8, 10]
5406  *     arr                   #=> [1, 2, 3, 4, 5]
5407  *     arr.map! { |a| a**2 } #=> [1, 4, 9, 16, 25]
5408  *     arr                   #=> [1, 4, 9, 16, 25]
5409  *
5410  *  == Selecting Items from an Array
5411  *
5412  *  Elements can be selected from an array according to criteria defined in a
5413  *  block.  The selection can happen in a destructive or a non-destructive
5414  *  manner.  While the destructive operations will modify the array they were
5415  *  called on, the non-destructive methods usually return a new array with the
5416  *  selected elements, but leave the original array unchanged.
5417  *
5418  *  === Non-destructive Selection
5419  *
5420  *     arr = [1, 2, 3, 4, 5, 6]
5421  *     arr.select { |a| a > 3 }     #=> [4, 5, 6]
5422  *     arr.reject { |a| a < 3 }     #=> [4, 5, 6]
5423  *     arr.drop_while { |a| a < 4 } #=> [4, 5, 6]
5424  *     arr                          #=> [1, 2, 3, 4, 5, 6]
5425  *
5426  *  === Destructive Selection
5427  *
5428  *  #select! and #reject! are the corresponding destructive methods to #select
5429  *  and #reject
5430  *
5431  *  Similar to #select vs. #reject, #delete_if and #keep_if have the exact
5432  *  opposite result when supplied with the same block:
5433  *
5434  *     arr.delete_if { |a| a < 4 } #=> [4, 5, 6]
5435  *     arr                         #=> [4, 5, 6]
5436  *
5437  *     arr = [1, 2, 3, 4, 5, 6]
5438  *     arr.keep_if { |a| a < 4 } #=> [1, 2, 3]
5439  *     arr                       #=> [1, 2, 3]
5440  *
5441  */
5442 
5443 void
5444 Init_Array(void)
5445 {
5446 #undef rb_intern
5447 #define rb_intern(str) rb_intern_const(str)
5448 
5449     rb_cArray  = rb_define_class("Array", rb_cObject);
5450     rb_include_module(rb_cArray, rb_mEnumerable);
5451 
5452     rb_define_alloc_func(rb_cArray, empty_ary_alloc);
5453     rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
5454     rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
5455     rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
5456     rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
5457 
5458     rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
5459     rb_define_alias(rb_cArray,  "to_s", "inspect");
5460     rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
5461     rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
5462     rb_define_method(rb_cArray, "frozen?",  rb_ary_frozen_p, 0);
5463 
5464     rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
5465     rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
5466     rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
5467 
5468     rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
5469     rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
5470     rb_define_method(rb_cArray, "at", rb_ary_at, 1);
5471     rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
5472     rb_define_method(rb_cArray, "first", rb_ary_first, -1);
5473     rb_define_method(rb_cArray, "last", rb_ary_last, -1);
5474     rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
5475     rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
5476     rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
5477     rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
5478     rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
5479     rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
5480     rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
5481     rb_define_method(rb_cArray, "each", rb_ary_each, 0);
5482     rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
5483     rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
5484     rb_define_method(rb_cArray, "length", rb_ary_length, 0);
5485     rb_define_alias(rb_cArray,  "size", "length");
5486     rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
5487     rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
5488     rb_define_method(rb_cArray, "index", rb_ary_index, -1);
5489     rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
5490     rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
5491     rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
5492     rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
5493     rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
5494     rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
5495     rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
5496     rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
5497     rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
5498     rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
5499     rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
5500     rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
5501     rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
5502     rb_define_method(rb_cArray, "select", rb_ary_select, 0);
5503     rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
5504     rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
5505     rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
5506     rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
5507     rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
5508     rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
5509     rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
5510     rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
5511     rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
5512     rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
5513     rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
5514     rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
5515     rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
5516     rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
5517     rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
5518 
5519     rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
5520     rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
5521 
5522     rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
5523     rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
5524 
5525     rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
5526     rb_define_method(rb_cArray, "*", rb_ary_times, 1);
5527 
5528     rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
5529     rb_define_method(rb_cArray, "&", rb_ary_and, 1);
5530     rb_define_method(rb_cArray, "|", rb_ary_or, 1);
5531 
5532     rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
5533     rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
5534     rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
5535     rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
5536     rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
5537     rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
5538     rb_define_method(rb_cArray, "count", rb_ary_count, -1);
5539     rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1);
5540     rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1);
5541     rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
5542     rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
5543     rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
5544     rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
5545     rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
5546     rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
5547     rb_define_method(rb_cArray, "product", rb_ary_product, -1);
5548 
5549     rb_define_method(rb_cArray, "take", rb_ary_take, 1);
5550     rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
5551     rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
5552     rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
5553     rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
5554 
5555     id_cmp = rb_intern("<=>");
5556     sym_random = ID2SYM(rb_intern("random"));
5557     id_div = rb_intern("div");
5558     id_power = rb_intern("**");
5559 }