001
002
003
004
005
006
007
008
009
010
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
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
322
323
324
325
326
327
328
329
330 VALUE
331 rb_ary_freeze(VALUE ary)
332 {
333 return rb_obj_freeze(ary);
334 }
335
336
337
338
339
340
341
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
352
353
354
355
356
357
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
565
566
567
568
569
570
571
572
573
574
575
576
577
578
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
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
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
701
702
703
704
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
811
812
813
814
815
816
817
818
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
859
860
861
862
863
864
865
866
867
868
869
870
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
898
899
900
901
902
903
904
905
906
907
908
909
910
911
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));
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);
952 ARY_INCREASE_LEN(ary, -1);
953
954 return top;
955 }
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
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
1032 if (new_len > ARY_DEFAULT_SIZE * 4) {
1033
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
1052 MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len);
1053 }
1054 }
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
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
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
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
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
1182 if (FIXNUM_P(arg)) {
1183 return rb_ary_entry(ary, FIX2LONG(arg));
1184 }
1185
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
1199
1200
1201
1202
1203
1204
1205
1206
1207
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
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
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
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
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
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
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
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
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
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
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);
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
1510
1511
1512
1513
1514
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
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
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
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
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
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
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
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
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
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
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
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
1749
1750
1751
1752
1753
1754
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
1766
1767
1768
1769
1770
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
1933
1934
1935
1936
1937
1938
1939
1940
1941
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
1981
1982
1983
1984
1985
1986
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
2004
2005
2006
2007
2008
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
2024
2025
2026
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;
2054 ary_reverse(p1, p2);
2055 }
2056 return ary;
2057 }
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070 static VALUE
2071 rb_ary_reverse_bang(VALUE ary)
2072 {
2073 return rb_ary_reverse(ary);
2074 }
2075
2076
2077
2078
2079
2080
2081
2082
2083
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
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
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
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
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
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
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);
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)) {
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
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
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
2348 RBASIC(tmp)->klass = rb_cArray;
2349 }
2350 return ary;
2351 }
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
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
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
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
2492
2493
2494
2495
2496
2497
2498
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
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
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
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
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
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
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
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
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
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
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
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
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
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
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
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
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
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
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
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
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
2916 goto delete_pos_len;
2917 case Qnil:
2918
2919 return Qnil;
2920 default:
2921
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
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
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
2988
2989
2990
2991
2992
2993
2994
2995
2996
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
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
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
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
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
3119
3120
3121
3122
3123
3124
3125
3126
3127
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) {
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
3160
3161
3162
3163
3164
3165
3166
3167
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
3214
3215
3216
3217
3218
3219
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
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
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;
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
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
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
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
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
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
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
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
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
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
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
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;
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
3563
3564
3565
3566
3567
3568
3569
3570
3571
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;
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
3604
3605
3606
3607
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
3642
3643
3644
3645
3646
3647
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
3658
3659
3660
3661
3662
3663
3664
3665
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;
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
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
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
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
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
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
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
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
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
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
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
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
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
4041
4042
4043
4044
4045
4046
4047
4048
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
4079
4080
4081
4082
4083
4084
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
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
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
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
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
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
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
4289
4290
4291
4292
4293
4294
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
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
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
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
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
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
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
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
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) {
4568 used[i] = 1;
4569 permute0(n, r, p, index+1,
4570 used, values);
4571 used[i] = 0;
4572 }
4573 else {
4574
4575
4576
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
4594
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
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
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);
4662 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size);
4663 rb_scan_args(argc, argv, "01", &num);
4664 r = NIL_P(num) ? n : NUM2LONG(num);
4665
4666 if (r < 0 || n < r) {
4667
4668 }
4669 else if (r == 0) {
4670 rb_yield(rb_ary_new2(0));
4671 }
4672 else if (r == 1) {
4673 for (i = 0; i < RARRAY_LEN(ary); i++) {
4674 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
4675 }
4676 }
4677 else {
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);
4683 RBASIC(ary0)->klass = 0;
4684
4685 MEMZERO(used, char, n);
4686
4687 permute0(n, r, p, 0, used, ary0);
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
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
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
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
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
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) {
4798 rpermute0(n, r, p, index+1, values);
4799 }
4800 else {
4801
4802
4803
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
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
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);
4860 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size);
4861 r = NUM2LONG(num);
4862
4863 if (r < 0) {
4864
4865 }
4866 else if (r == 0) {
4867 rb_yield(rb_ary_new2(0));
4868 }
4869 else if (r == 1) {
4870 for (i = 0; i < RARRAY_LEN(ary); i++) {
4871 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
4872 }
4873 }
4874 else {
4875 volatile VALUE t0 = tmpbuf(r, sizeof(long));
4876 long *p = (long*)RSTRING_PTR(t0);
4877 VALUE ary0 = ary_make_shared_copy(ary);
4878 RBASIC(ary0)->klass = 0;
4879
4880 rpermute0(n, r, p, 0, ary0);
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
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
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);
4955 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size);
4956 len = RARRAY_LEN(ary);
4957 if (n < 0) {
4958
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
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);
4975 RBASIC(ary0)->klass = 0;
4976
4977 rcombinate0(len, n, p, 0, n, ary0);
4978 tmpbuf_discard(t0);
4979 RBASIC(ary0)->klass = rb_cArray;
4980 }
4981 return ary;
4982 }
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005 static VALUE
5006 rb_ary_product(int argc, VALUE *argv, VALUE ary)
5007 {
5008 int n = argc+1;
5009 volatile VALUE t0 = tmpary(n);
5010 volatile VALUE t1 = tmpbuf(n, sizeof(int));
5011 VALUE *arrays = RARRAY_PTR(t0);
5012 int *counters = (int*)RSTRING_PTR(t1);
5013 VALUE result = Qnil;
5014 long i,j;
5015 long resultlen = 1;
5016
5017 RBASIC(t0)->klass = 0;
5018 RBASIC(t1)->klass = 0;
5019
5020
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
5027 for (i = 0; i < n; i++) counters[i] = 0;
5028
5029
5030 if (rb_block_given_p()) {
5031
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
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
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
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
5076
5077
5078 m = n-1;
5079 counters[m]++;
5080 while (counters[m] == RARRAY_LEN(arrays[m])) {
5081 counters[m] = 0;
5082
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
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
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
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
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
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
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
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
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
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
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 }