00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "ruby/ruby.h"
00015 #include "ruby/util.h"
00016 #include "ruby/st.h"
00017 #include "ruby/encoding.h"
00018 #include "internal.h"
00019 #include "probes.h"
00020 #include "id.h"
00021
00022 #ifndef ARRAY_DEBUG
00023 # define NDEBUG
00024 #endif
00025 #include <assert.h>
00026
00027 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00028
00029 VALUE rb_cArray;
00030
00031 static ID id_cmp, id_div, id_power;
00032
00033 #define ARY_DEFAULT_SIZE 16
00034 #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
00035
00036 void
00037 rb_mem_clear(register VALUE *mem, register long size)
00038 {
00039 while (size--) {
00040 *mem++ = Qnil;
00041 }
00042 }
00043
00044 static inline void
00045 memfill(register VALUE *mem, register long size, register VALUE val)
00046 {
00047 while (size--) {
00048 *mem++ = val;
00049 }
00050 }
00051
00052 # define ARY_SHARED_P(ary) \
00053 (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
00054 FL_TEST((ary),ELTS_SHARED)!=0)
00055 # define ARY_EMBED_P(ary) \
00056 (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
00057 FL_TEST((ary), RARRAY_EMBED_FLAG)!=0)
00058
00059 #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
00060 #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
00061 #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
00062 #define ARY_EMBED_LEN(a) \
00063 (assert(ARY_EMBED_P(a)), \
00064 (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
00065 (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
00066
00067 #define ARY_OWNS_HEAP_P(a) (!FL_TEST((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
00068 #define FL_SET_EMBED(a) do { \
00069 assert(!ARY_SHARED_P(a)); \
00070 FL_SET((a), RARRAY_EMBED_FLAG); \
00071 } while (0)
00072 #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
00073 #define FL_SET_SHARED(ary) do { \
00074 assert(!ARY_EMBED_P(ary)); \
00075 FL_SET((ary), ELTS_SHARED); \
00076 } while (0)
00077 #define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
00078
00079 #define ARY_SET_PTR(ary, p) do { \
00080 assert(!ARY_EMBED_P(ary)); \
00081 assert(!OBJ_FROZEN(ary)); \
00082 RARRAY(ary)->as.heap.ptr = (p); \
00083 } while (0)
00084 #define ARY_SET_EMBED_LEN(ary, n) do { \
00085 long tmp_n = (n); \
00086 assert(ARY_EMBED_P(ary)); \
00087 assert(!OBJ_FROZEN(ary)); \
00088 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
00089 RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
00090 } while (0)
00091 #define ARY_SET_HEAP_LEN(ary, n) do { \
00092 assert(!ARY_EMBED_P(ary)); \
00093 RARRAY(ary)->as.heap.len = (n); \
00094 } while (0)
00095 #define ARY_SET_LEN(ary, n) do { \
00096 if (ARY_EMBED_P(ary)) { \
00097 ARY_SET_EMBED_LEN((ary), (n)); \
00098 } \
00099 else { \
00100 ARY_SET_HEAP_LEN((ary), (n)); \
00101 } \
00102 assert(RARRAY_LEN(ary) == (n)); \
00103 } while (0)
00104 #define ARY_INCREASE_PTR(ary, n) do { \
00105 assert(!ARY_EMBED_P(ary)); \
00106 assert(!OBJ_FROZEN(ary)); \
00107 RARRAY(ary)->as.heap.ptr += (n); \
00108 } while (0)
00109 #define ARY_INCREASE_LEN(ary, n) do { \
00110 assert(!OBJ_FROZEN(ary)); \
00111 if (ARY_EMBED_P(ary)) { \
00112 ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
00113 } \
00114 else { \
00115 RARRAY(ary)->as.heap.len += (n); \
00116 } \
00117 } while (0)
00118
00119 #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
00120 ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : RARRAY(ary)->as.heap.aux.capa)
00121 #define ARY_SET_CAPA(ary, n) do { \
00122 assert(!ARY_EMBED_P(ary)); \
00123 assert(!ARY_SHARED_P(ary)); \
00124 assert(!OBJ_FROZEN(ary)); \
00125 RARRAY(ary)->as.heap.aux.capa = (n); \
00126 } while (0)
00127
00128 #define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
00129 #define ARY_SET_SHARED(ary, value) do { \
00130 assert(!ARY_EMBED_P(ary)); \
00131 assert(ARY_SHARED_P(ary)); \
00132 assert(ARY_SHARED_ROOT_P(value)); \
00133 RARRAY(ary)->as.heap.aux.shared = (value); \
00134 } while (0)
00135 #define RARRAY_SHARED_ROOT_FLAG FL_USER5
00136 #define ARY_SHARED_ROOT_P(ary) (FL_TEST((ary), RARRAY_SHARED_ROOT_FLAG))
00137 #define ARY_SHARED_NUM(ary) \
00138 (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
00139 #define ARY_SET_SHARED_NUM(ary, value) do { \
00140 assert(ARY_SHARED_ROOT_P(ary)); \
00141 RARRAY(ary)->as.heap.aux.capa = (value); \
00142 } while (0)
00143 #define FL_SET_SHARED_ROOT(ary) do { \
00144 assert(!ARY_EMBED_P(ary)); \
00145 FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
00146 } while (0)
00147
00148 static void
00149 ary_resize_capa(VALUE ary, long capacity)
00150 {
00151 assert(RARRAY_LEN(ary) <= capacity);
00152 assert(!OBJ_FROZEN(ary));
00153 assert(!ARY_SHARED_P(ary));
00154 if (capacity > RARRAY_EMBED_LEN_MAX) {
00155 if (ARY_EMBED_P(ary)) {
00156 long len = ARY_EMBED_LEN(ary);
00157 VALUE *ptr = ALLOC_N(VALUE, (capacity));
00158 MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
00159 FL_UNSET_EMBED(ary);
00160 ARY_SET_PTR(ary, ptr);
00161 ARY_SET_HEAP_LEN(ary, len);
00162 }
00163 else {
00164 REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, (capacity));
00165 }
00166 ARY_SET_CAPA(ary, (capacity));
00167 }
00168 else {
00169 if (!ARY_EMBED_P(ary)) {
00170 long len = RARRAY_LEN(ary);
00171 VALUE *ptr = RARRAY_PTR(ary);
00172 if (len > capacity) len = capacity;
00173 MEMCPY(RARRAY(ary)->as.ary, ptr, VALUE, len);
00174 FL_SET_EMBED(ary);
00175 ARY_SET_LEN(ary, len);
00176 xfree(ptr);
00177 }
00178 }
00179 }
00180
00181 static void
00182 ary_double_capa(VALUE ary, long min)
00183 {
00184 long new_capa = ARY_CAPA(ary) / 2;
00185
00186 if (new_capa < ARY_DEFAULT_SIZE) {
00187 new_capa = ARY_DEFAULT_SIZE;
00188 }
00189 if (new_capa >= ARY_MAX_SIZE - min) {
00190 new_capa = (ARY_MAX_SIZE - min) / 2;
00191 }
00192 new_capa += min;
00193 ary_resize_capa(ary, new_capa);
00194 }
00195
00196 static void
00197 rb_ary_decrement_share(VALUE shared)
00198 {
00199 if (shared) {
00200 long num = ARY_SHARED_NUM(shared) - 1;
00201 if (num == 0) {
00202 rb_ary_free(shared);
00203 rb_gc_force_recycle(shared);
00204 }
00205 else if (num > 0) {
00206 ARY_SET_SHARED_NUM(shared, num);
00207 }
00208 }
00209 }
00210
00211 static void
00212 rb_ary_unshare(VALUE ary)
00213 {
00214 VALUE shared = RARRAY(ary)->as.heap.aux.shared;
00215 rb_ary_decrement_share(shared);
00216 FL_UNSET_SHARED(ary);
00217 }
00218
00219 static inline void
00220 rb_ary_unshare_safe(VALUE ary)
00221 {
00222 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
00223 rb_ary_unshare(ary);
00224 }
00225 }
00226
00227 static VALUE
00228 rb_ary_increment_share(VALUE shared)
00229 {
00230 long num = ARY_SHARED_NUM(shared);
00231 if (num >= 0) {
00232 ARY_SET_SHARED_NUM(shared, num + 1);
00233 }
00234 return shared;
00235 }
00236
00237 static void
00238 rb_ary_set_shared(VALUE ary, VALUE shared)
00239 {
00240 rb_ary_increment_share(shared);
00241 FL_SET_SHARED(ary);
00242 ARY_SET_SHARED(ary, shared);
00243 }
00244
00245 static inline void
00246 rb_ary_modify_check(VALUE ary)
00247 {
00248 rb_check_frozen(ary);
00249 if (!OBJ_UNTRUSTED(ary) && rb_safe_level() >= 4)
00250 rb_raise(rb_eSecurityError, "Insecure: can't modify array");
00251 }
00252
00253 void
00254 rb_ary_modify(VALUE ary)
00255 {
00256 rb_ary_modify_check(ary);
00257 if (ARY_SHARED_P(ary)) {
00258 long len = RARRAY_LEN(ary);
00259 VALUE shared = ARY_SHARED(ary);
00260 if (len <= RARRAY_EMBED_LEN_MAX) {
00261 VALUE *ptr = ARY_HEAP_PTR(ary);
00262 FL_UNSET_SHARED(ary);
00263 FL_SET_EMBED(ary);
00264 MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len);
00265 rb_ary_decrement_share(shared);
00266 ARY_SET_EMBED_LEN(ary, len);
00267 }
00268 else if (ARY_SHARED_NUM(shared) == 1 && len > (RARRAY_LEN(shared)>>1)) {
00269 long shift = RARRAY_PTR(ary) - RARRAY_PTR(shared);
00270 FL_UNSET_SHARED(ary);
00271 ARY_SET_PTR(ary, RARRAY_PTR(shared));
00272 ARY_SET_CAPA(ary, RARRAY_LEN(shared));
00273 MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+shift, VALUE, len);
00274 FL_SET_EMBED(shared);
00275 rb_ary_decrement_share(shared);
00276 }
00277 else {
00278 VALUE *ptr = ALLOC_N(VALUE, len);
00279 MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len);
00280 rb_ary_unshare(ary);
00281 ARY_SET_CAPA(ary, len);
00282 ARY_SET_PTR(ary, ptr);
00283 }
00284 }
00285 }
00286
00287 static void
00288 ary_ensure_room_for_push(VALUE ary, long add_len)
00289 {
00290 long new_len = RARRAY_LEN(ary) + add_len;
00291 long capa;
00292
00293 if (ARY_SHARED_P(ary)) {
00294 if (new_len > RARRAY_EMBED_LEN_MAX) {
00295 VALUE shared = ARY_SHARED(ary);
00296 if (ARY_SHARED_NUM(shared) == 1) {
00297 if (RARRAY_PTR(ary) - RARRAY_PTR(shared) + new_len <= RARRAY_LEN(shared)) {
00298 rb_ary_modify_check(ary);
00299 }
00300 else {
00301
00302 rb_ary_modify(ary);
00303 capa = ARY_CAPA(ary);
00304 if (new_len > capa - (capa >> 6)) {
00305 ary_double_capa(ary, new_len);
00306 }
00307 }
00308 return;
00309 }
00310 }
00311 }
00312 rb_ary_modify(ary);
00313 capa = ARY_CAPA(ary);
00314 if (new_len > capa) {
00315 ary_double_capa(ary, new_len);
00316 }
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 VALUE
00330 rb_ary_freeze(VALUE ary)
00331 {
00332 return rb_obj_freeze(ary);
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 static VALUE
00344 rb_ary_frozen_p(VALUE ary)
00345 {
00346 if (OBJ_FROZEN(ary)) return Qtrue;
00347 return Qfalse;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357 VALUE
00358 rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
00359 {
00360 if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
00361 !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
00362 RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared &&
00363 RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
00364 return Qtrue;
00365 }
00366 return Qfalse;
00367 }
00368
00369 static VALUE
00370 ary_alloc(VALUE klass)
00371 {
00372 NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY);
00373 FL_SET_EMBED((VALUE)ary);
00374 ARY_SET_EMBED_LEN((VALUE)ary, 0);
00375
00376 return (VALUE)ary;
00377 }
00378
00379 static VALUE
00380 empty_ary_alloc(VALUE klass)
00381 {
00382 if (RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
00383 RUBY_DTRACE_ARRAY_CREATE(0, rb_sourcefile(), rb_sourceline());
00384 }
00385
00386 return ary_alloc(klass);
00387 }
00388
00389 static VALUE
00390 ary_new(VALUE klass, long capa)
00391 {
00392 VALUE ary;
00393
00394 if (capa < 0) {
00395 rb_raise(rb_eArgError, "negative array size (or size too big)");
00396 }
00397 if (capa > ARY_MAX_SIZE) {
00398 rb_raise(rb_eArgError, "array size too big");
00399 }
00400
00401 if (RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
00402 RUBY_DTRACE_ARRAY_CREATE(capa, rb_sourcefile(), rb_sourceline());
00403 }
00404
00405 ary = ary_alloc(klass);
00406 if (capa > RARRAY_EMBED_LEN_MAX) {
00407 FL_UNSET_EMBED(ary);
00408 ARY_SET_PTR(ary, ALLOC_N(VALUE, capa));
00409 ARY_SET_CAPA(ary, capa);
00410 ARY_SET_HEAP_LEN(ary, 0);
00411 }
00412
00413 return ary;
00414 }
00415
00416 VALUE
00417 rb_ary_new2(long capa)
00418 {
00419 return ary_new(rb_cArray, capa);
00420 }
00421
00422
00423 VALUE
00424 rb_ary_new(void)
00425 {
00426 return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
00427 }
00428
00429 #include <stdarg.h>
00430
00431 VALUE
00432 rb_ary_new3(long n, ...)
00433 {
00434 va_list ar;
00435 VALUE ary;
00436 long i;
00437
00438 ary = rb_ary_new2(n);
00439
00440 va_start(ar, n);
00441 for (i=0; i<n; i++) {
00442 RARRAY_PTR(ary)[i] = va_arg(ar, VALUE);
00443 }
00444 va_end(ar);
00445
00446 ARY_SET_LEN(ary, n);
00447 return ary;
00448 }
00449
00450 VALUE
00451 rb_ary_new4(long n, const VALUE *elts)
00452 {
00453 VALUE ary;
00454
00455 ary = rb_ary_new2(n);
00456 if (n > 0 && elts) {
00457 MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
00458 ARY_SET_LEN(ary, n);
00459 }
00460
00461 return ary;
00462 }
00463
00464 VALUE
00465 rb_ary_tmp_new(long capa)
00466 {
00467 return ary_new(0, capa);
00468 }
00469
00470 void
00471 rb_ary_free(VALUE ary)
00472 {
00473 if (ARY_OWNS_HEAP_P(ary)) {
00474 xfree(ARY_HEAP_PTR(ary));
00475 }
00476 }
00477
00478 RUBY_FUNC_EXPORTED size_t
00479 rb_ary_memsize(VALUE ary)
00480 {
00481 if (ARY_OWNS_HEAP_P(ary)) {
00482 return RARRAY(ary)->as.heap.aux.capa * sizeof(VALUE);
00483 }
00484 else {
00485 return 0;
00486 }
00487 }
00488
00489 static inline void
00490 ary_discard(VALUE ary)
00491 {
00492 rb_ary_free(ary);
00493 RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
00494 RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK;
00495 }
00496
00497 static VALUE
00498 ary_make_shared(VALUE ary)
00499 {
00500 assert(!ARY_EMBED_P(ary));
00501 if (ARY_SHARED_P(ary)) {
00502 return ARY_SHARED(ary);
00503 }
00504 else if (ARY_SHARED_ROOT_P(ary)) {
00505 return ary;
00506 }
00507 else if (OBJ_FROZEN(ary)) {
00508 ary_resize_capa(ary, ARY_HEAP_LEN(ary));
00509 FL_SET_SHARED_ROOT(ary);
00510 ARY_SET_SHARED_NUM(ary, 1);
00511 return ary;
00512 }
00513 else {
00514 NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY);
00515 FL_UNSET_EMBED(shared);
00516
00517 ARY_SET_LEN((VALUE)shared, ARY_CAPA(ary));
00518 ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary));
00519 rb_mem_clear(RARRAY_PTR(shared) + RARRAY_LEN(ary), ARY_CAPA(ary) - RARRAY_LEN(ary));
00520 FL_SET_SHARED_ROOT(shared);
00521 ARY_SET_SHARED_NUM((VALUE)shared, 1);
00522 FL_SET_SHARED(ary);
00523 ARY_SET_SHARED(ary, (VALUE)shared);
00524 OBJ_FREEZE(shared);
00525 return (VALUE)shared;
00526 }
00527 }
00528
00529
00530 static VALUE
00531 ary_make_substitution(VALUE ary)
00532 {
00533 if (RARRAY_LEN(ary) <= RARRAY_EMBED_LEN_MAX) {
00534 VALUE subst = rb_ary_new2(RARRAY_LEN(ary));
00535 MEMCPY(ARY_EMBED_PTR(subst), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
00536 ARY_SET_EMBED_LEN(subst, RARRAY_LEN(ary));
00537 return subst;
00538 }
00539 else {
00540 return rb_ary_increment_share(ary_make_shared(ary));
00541 }
00542 }
00543
00544 VALUE
00545 rb_assoc_new(VALUE car, VALUE cdr)
00546 {
00547 return rb_ary_new3(2, car, cdr);
00548 }
00549
00550 static VALUE
00551 to_ary(VALUE ary)
00552 {
00553 return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
00554 }
00555
00556 VALUE
00557 rb_check_array_type(VALUE ary)
00558 {
00559 return rb_check_convert_type(ary, T_ARRAY, "Array", "to_ary");
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581 static VALUE
00582 rb_ary_s_try_convert(VALUE dummy, VALUE ary)
00583 {
00584 return rb_check_array_type(ary);
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 static VALUE
00644 rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
00645 {
00646 long len;
00647 VALUE size, val;
00648
00649 rb_ary_modify(ary);
00650 if (argc == 0) {
00651 if (ARY_OWNS_HEAP_P(ary) && RARRAY_PTR(ary)) {
00652 xfree(RARRAY_PTR(ary));
00653 }
00654 rb_ary_unshare_safe(ary);
00655 FL_SET_EMBED(ary);
00656 ARY_SET_EMBED_LEN(ary, 0);
00657 if (rb_block_given_p()) {
00658 rb_warning("given block not used");
00659 }
00660 return ary;
00661 }
00662 rb_scan_args(argc, argv, "02", &size, &val);
00663 if (argc == 1 && !FIXNUM_P(size)) {
00664 val = rb_check_array_type(size);
00665 if (!NIL_P(val)) {
00666 rb_ary_replace(ary, val);
00667 return ary;
00668 }
00669 }
00670
00671 len = NUM2LONG(size);
00672 if (len < 0) {
00673 rb_raise(rb_eArgError, "negative array size");
00674 }
00675 if (len > ARY_MAX_SIZE) {
00676 rb_raise(rb_eArgError, "array size too big");
00677 }
00678 rb_ary_modify(ary);
00679 ary_resize_capa(ary, len);
00680 if (rb_block_given_p()) {
00681 long i;
00682
00683 if (argc == 2) {
00684 rb_warn("block supersedes default value argument");
00685 }
00686 for (i=0; i<len; i++) {
00687 rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
00688 ARY_SET_LEN(ary, i + 1);
00689 }
00690 }
00691 else {
00692 memfill(RARRAY_PTR(ary), len, val);
00693 ARY_SET_LEN(ary, len);
00694 }
00695 return ary;
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 static VALUE
00707 rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
00708 {
00709 VALUE ary = ary_new(klass, argc);
00710 if (argc > 0 && argv) {
00711 MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
00712 ARY_SET_LEN(ary, argc);
00713 }
00714
00715 return ary;
00716 }
00717
00718 void
00719 rb_ary_store(VALUE ary, long idx, VALUE val)
00720 {
00721 if (idx < 0) {
00722 idx += RARRAY_LEN(ary);
00723 if (idx < 0) {
00724 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
00725 idx - RARRAY_LEN(ary), -RARRAY_LEN(ary));
00726 }
00727 }
00728 else if (idx >= ARY_MAX_SIZE) {
00729 rb_raise(rb_eIndexError, "index %ld too big", idx);
00730 }
00731
00732 rb_ary_modify(ary);
00733 if (idx >= ARY_CAPA(ary)) {
00734 ary_double_capa(ary, idx);
00735 }
00736 if (idx > RARRAY_LEN(ary)) {
00737 rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary),
00738 idx-RARRAY_LEN(ary) + 1);
00739 }
00740
00741 if (idx >= RARRAY_LEN(ary)) {
00742 ARY_SET_LEN(ary, idx + 1);
00743 }
00744 RARRAY_PTR(ary)[idx] = val;
00745 }
00746
00747 static VALUE
00748 ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
00749 {
00750 assert(offset >= 0);
00751 assert(len >= 0);
00752 assert(offset+len <= RARRAY_LEN(ary));
00753
00754 if (len <= RARRAY_EMBED_LEN_MAX) {
00755 VALUE result = ary_alloc(klass);
00756 MEMCPY(ARY_EMBED_PTR(result), RARRAY_PTR(ary) + offset, VALUE, len);
00757 ARY_SET_EMBED_LEN(result, len);
00758 return result;
00759 }
00760 else {
00761 VALUE shared, result = ary_alloc(klass);
00762 FL_UNSET_EMBED(result);
00763
00764 shared = ary_make_shared(ary);
00765 ARY_SET_PTR(result, RARRAY_PTR(ary));
00766 ARY_SET_LEN(result, RARRAY_LEN(ary));
00767 rb_ary_set_shared(result, shared);
00768
00769 ARY_INCREASE_PTR(result, offset);
00770 ARY_SET_LEN(result, len);
00771 return result;
00772 }
00773 }
00774
00775 static VALUE
00776 ary_make_shared_copy(VALUE ary)
00777 {
00778 return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary));
00779 }
00780
00781 enum ary_take_pos_flags
00782 {
00783 ARY_TAKE_FIRST = 0,
00784 ARY_TAKE_LAST = 1
00785 };
00786
00787 static VALUE
00788 ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
00789 {
00790 VALUE nv;
00791 long n;
00792 long offset = 0;
00793
00794 rb_scan_args(argc, argv, "1", &nv);
00795 n = NUM2LONG(nv);
00796 if (n > RARRAY_LEN(ary)) {
00797 n = RARRAY_LEN(ary);
00798 }
00799 else if (n < 0) {
00800 rb_raise(rb_eArgError, "negative array size");
00801 }
00802 if (last) {
00803 offset = RARRAY_LEN(ary) - n;
00804 }
00805 return ary_make_partial(ary, rb_cArray, offset, n);
00806 }
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 VALUE
00822 rb_ary_push(VALUE ary, VALUE item)
00823 {
00824 long idx = RARRAY_LEN(ary);
00825
00826 ary_ensure_room_for_push(ary, 1);
00827 RARRAY_PTR(ary)[idx] = item;
00828 ARY_SET_LEN(ary, idx + 1);
00829 return ary;
00830 }
00831
00832 VALUE
00833 rb_ary_cat(VALUE ary, const VALUE *ptr, long len)
00834 {
00835 long oldlen = RARRAY_LEN(ary);
00836
00837 ary_ensure_room_for_push(ary, len);
00838 MEMCPY(RARRAY_PTR(ary) + oldlen, ptr, VALUE, len);
00839 ARY_SET_LEN(ary, oldlen + len);
00840 return ary;
00841 }
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 static VALUE
00860 rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
00861 {
00862 return rb_ary_cat(ary, argv, argc);
00863 }
00864
00865 VALUE
00866 rb_ary_pop(VALUE ary)
00867 {
00868 long n;
00869 rb_ary_modify_check(ary);
00870 if (RARRAY_LEN(ary) == 0) return Qnil;
00871 if (ARY_OWNS_HEAP_P(ary) &&
00872 RARRAY_LEN(ary) * 3 < ARY_CAPA(ary) &&
00873 ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
00874 {
00875 ary_resize_capa(ary, RARRAY_LEN(ary) * 2);
00876 }
00877 n = RARRAY_LEN(ary)-1;
00878 ARY_SET_LEN(ary, n);
00879 return RARRAY_PTR(ary)[n];
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900 static VALUE
00901 rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
00902 {
00903 VALUE result;
00904
00905 if (argc == 0) {
00906 return rb_ary_pop(ary);
00907 }
00908
00909 rb_ary_modify_check(ary);
00910 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
00911 ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
00912 return result;
00913 }
00914
00915 VALUE
00916 rb_ary_shift(VALUE ary)
00917 {
00918 VALUE top;
00919
00920 rb_ary_modify_check(ary);
00921 if (RARRAY_LEN(ary) == 0) return Qnil;
00922 top = RARRAY_PTR(ary)[0];
00923 if (!ARY_SHARED_P(ary)) {
00924 if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
00925 MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1);
00926 ARY_INCREASE_LEN(ary, -1);
00927 return top;
00928 }
00929 assert(!ARY_EMBED_P(ary));
00930
00931 RARRAY_PTR(ary)[0] = Qnil;
00932 ary_make_shared(ary);
00933 }
00934 else if (ARY_SHARED_NUM(ARY_SHARED(ary)) == 1) {
00935 RARRAY_PTR(ary)[0] = Qnil;
00936 }
00937 ARY_INCREASE_PTR(ary, 1);
00938 ARY_INCREASE_LEN(ary, -1);
00939
00940 return top;
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 static VALUE
00967 rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
00968 {
00969 VALUE result;
00970 long n;
00971
00972 if (argc == 0) {
00973 return rb_ary_shift(ary);
00974 }
00975
00976 rb_ary_modify_check(ary);
00977 result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
00978 n = RARRAY_LEN(result);
00979 if (ARY_SHARED_P(ary)) {
00980 if (ARY_SHARED_NUM(ARY_SHARED(ary)) == 1) {
00981 rb_mem_clear(RARRAY_PTR(ary), n);
00982 }
00983 ARY_INCREASE_PTR(ary, n);
00984 }
00985 else {
00986 MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
00987 }
00988 ARY_INCREASE_LEN(ary, -n);
00989
00990 return result;
00991 }
00992
00993 static void
00994 ary_ensure_room_for_unshift(VALUE ary, int argc)
00995 {
00996 long len = RARRAY_LEN(ary);
00997 long new_len = len + argc;
00998 long capa;
00999 VALUE *head, *sharedp;
01000
01001 if (ARY_SHARED_P(ary)) {
01002 VALUE shared = ARY_SHARED(ary);
01003 capa = RARRAY_LEN(shared);
01004 if (ARY_SHARED_NUM(shared) == 1 && capa > new_len) {
01005 head = RARRAY_PTR(ary);
01006 sharedp = RARRAY_PTR(shared);
01007 goto makeroom_if_need;
01008 }
01009 }
01010
01011 rb_ary_modify(ary);
01012 capa = ARY_CAPA(ary);
01013 if (capa - (capa >> 6) <= new_len) {
01014 ary_double_capa(ary, new_len);
01015 }
01016
01017
01018 if (new_len > ARY_DEFAULT_SIZE * 4) {
01019
01020 capa = ARY_CAPA(ary);
01021 ary_make_shared(ary);
01022
01023 head = sharedp = RARRAY_PTR(ary);
01024 goto makeroom;
01025 makeroom_if_need:
01026 if (head - sharedp < argc) {
01027 long room;
01028 makeroom:
01029 room = capa - new_len;
01030 room -= room >> 4;
01031 MEMMOVE(sharedp + argc + room, head, VALUE, len);
01032 head = sharedp + argc + room;
01033 }
01034 ARY_SET_PTR(ary, head - argc);
01035 }
01036 else {
01037
01038 MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len);
01039 }
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054 static VALUE
01055 rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
01056 {
01057 long len = RARRAY_LEN(ary);
01058
01059 if (argc == 0) {
01060 rb_ary_modify_check(ary);
01061 return ary;
01062 }
01063
01064 ary_ensure_room_for_unshift(ary, argc);
01065 MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
01066 ARY_SET_LEN(ary, len + argc);
01067 return ary;
01068 }
01069
01070 VALUE
01071 rb_ary_unshift(VALUE ary, VALUE item)
01072 {
01073 return rb_ary_unshift_m(1,&item,ary);
01074 }
01075
01076
01077 static inline VALUE
01078 rb_ary_elt(VALUE ary, long offset)
01079 {
01080 if (RARRAY_LEN(ary) == 0) return Qnil;
01081 if (offset < 0 || RARRAY_LEN(ary) <= offset) {
01082 return Qnil;
01083 }
01084 return RARRAY_PTR(ary)[offset];
01085 }
01086
01087 VALUE
01088 rb_ary_entry(VALUE ary, long offset)
01089 {
01090 if (offset < 0) {
01091 offset += RARRAY_LEN(ary);
01092 }
01093 return rb_ary_elt(ary, offset);
01094 }
01095
01096 VALUE
01097 rb_ary_subseq(VALUE ary, long beg, long len)
01098 {
01099 VALUE klass;
01100
01101 if (beg > RARRAY_LEN(ary)) return Qnil;
01102 if (beg < 0 || len < 0) return Qnil;
01103
01104 if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
01105 len = RARRAY_LEN(ary) - beg;
01106 }
01107 klass = rb_obj_class(ary);
01108 if (len == 0) return ary_new(klass, 0);
01109
01110 return ary_make_partial(ary, klass, beg, len);
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 VALUE
01150 rb_ary_aref(int argc, VALUE *argv, VALUE ary)
01151 {
01152 VALUE arg;
01153 long beg, len;
01154
01155 if (argc == 2) {
01156 beg = NUM2LONG(argv[0]);
01157 len = NUM2LONG(argv[1]);
01158 if (beg < 0) {
01159 beg += RARRAY_LEN(ary);
01160 }
01161 return rb_ary_subseq(ary, beg, len);
01162 }
01163 if (argc != 1) {
01164 rb_scan_args(argc, argv, "11", NULL, NULL);
01165 }
01166 arg = argv[0];
01167
01168 if (FIXNUM_P(arg)) {
01169 return rb_ary_entry(ary, FIX2LONG(arg));
01170 }
01171
01172 switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
01173 case Qfalse:
01174 break;
01175 case Qnil:
01176 return Qnil;
01177 default:
01178 return rb_ary_subseq(ary, beg, len);
01179 }
01180 return rb_ary_entry(ary, NUM2LONG(arg));
01181 }
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 static VALUE
01197 rb_ary_at(VALUE ary, VALUE pos)
01198 {
01199 return rb_ary_entry(ary, NUM2LONG(pos));
01200 }
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217 static VALUE
01218 rb_ary_first(int argc, VALUE *argv, VALUE ary)
01219 {
01220 if (argc == 0) {
01221 if (RARRAY_LEN(ary) == 0) return Qnil;
01222 return RARRAY_PTR(ary)[0];
01223 }
01224 else {
01225 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
01226 }
01227 }
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 VALUE
01245 rb_ary_last(int argc, VALUE *argv, VALUE ary)
01246 {
01247 if (argc == 0) {
01248 if (RARRAY_LEN(ary) == 0) return Qnil;
01249 return RARRAY_PTR(ary)[RARRAY_LEN(ary)-1];
01250 }
01251 else {
01252 return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
01253 }
01254 }
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 static VALUE
01280 rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
01281 {
01282 VALUE pos, ifnone;
01283 long block_given;
01284 long idx;
01285
01286 rb_scan_args(argc, argv, "11", &pos, &ifnone);
01287 block_given = rb_block_given_p();
01288 if (block_given && argc == 2) {
01289 rb_warn("block supersedes default value argument");
01290 }
01291 idx = NUM2LONG(pos);
01292
01293 if (idx < 0) {
01294 idx += RARRAY_LEN(ary);
01295 }
01296 if (idx < 0 || RARRAY_LEN(ary) <= idx) {
01297 if (block_given) return rb_yield(pos);
01298 if (argc == 1) {
01299 rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
01300 idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
01301 }
01302 return ifnone;
01303 }
01304 return RARRAY_PTR(ary)[idx];
01305 }
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 static VALUE
01333 rb_ary_index(int argc, VALUE *argv, VALUE ary)
01334 {
01335 VALUE val;
01336 long i;
01337
01338 if (argc == 0) {
01339 RETURN_ENUMERATOR(ary, 0, 0);
01340 for (i=0; i<RARRAY_LEN(ary); i++) {
01341 if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
01342 return LONG2NUM(i);
01343 }
01344 }
01345 return Qnil;
01346 }
01347 rb_scan_args(argc, argv, "1", &val);
01348 if (rb_block_given_p())
01349 rb_warn("given block not used");
01350 for (i=0; i<RARRAY_LEN(ary); i++) {
01351 if (rb_equal(RARRAY_PTR(ary)[i], val))
01352 return LONG2NUM(i);
01353 }
01354 return Qnil;
01355 }
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381 static VALUE
01382 rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
01383 {
01384 VALUE val;
01385 long i = RARRAY_LEN(ary);
01386
01387 if (argc == 0) {
01388 RETURN_ENUMERATOR(ary, 0, 0);
01389 while (i--) {
01390 if (RTEST(rb_yield(RARRAY_PTR(ary)[i])))
01391 return LONG2NUM(i);
01392 if (i > RARRAY_LEN(ary)) {
01393 i = RARRAY_LEN(ary);
01394 }
01395 }
01396 return Qnil;
01397 }
01398 rb_scan_args(argc, argv, "1", &val);
01399 if (rb_block_given_p())
01400 rb_warn("given block not used");
01401 while (i--) {
01402 if (rb_equal(RARRAY_PTR(ary)[i], val))
01403 return LONG2NUM(i);
01404 if (i > RARRAY_LEN(ary)) {
01405 i = RARRAY_LEN(ary);
01406 }
01407 }
01408 return Qnil;
01409 }
01410
01411 VALUE
01412 rb_ary_to_ary(VALUE obj)
01413 {
01414 VALUE tmp = rb_check_array_type(obj);
01415
01416 if (!NIL_P(tmp)) return tmp;
01417 return rb_ary_new3(1, obj);
01418 }
01419
01420 static void
01421 rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
01422 {
01423 long rlen;
01424
01425 if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
01426 if (beg < 0) {
01427 beg += RARRAY_LEN(ary);
01428 if (beg < 0) {
01429 rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
01430 beg - RARRAY_LEN(ary), -RARRAY_LEN(ary));
01431 }
01432 }
01433 if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
01434 len = RARRAY_LEN(ary) - beg;
01435 }
01436
01437 if (rpl == Qundef) {
01438 rlen = 0;
01439 }
01440 else {
01441 rpl = rb_ary_to_ary(rpl);
01442 rlen = RARRAY_LEN(rpl);
01443 }
01444 if (beg >= RARRAY_LEN(ary)) {
01445 if (beg > ARY_MAX_SIZE - rlen) {
01446 rb_raise(rb_eIndexError, "index %ld too big", beg);
01447 }
01448 ary_ensure_room_for_push(ary, rlen-len);
01449 len = beg + rlen;
01450 rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary));
01451 if (rlen > 0) {
01452 MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
01453 }
01454 ARY_SET_LEN(ary, len);
01455 }
01456 else {
01457 long alen;
01458
01459 rb_ary_modify(ary);
01460 alen = RARRAY_LEN(ary) + rlen - len;
01461 if (alen >= ARY_CAPA(ary)) {
01462 ary_double_capa(ary, alen);
01463 }
01464
01465 if (len != rlen) {
01466 MEMMOVE(RARRAY_PTR(ary) + beg + rlen, RARRAY_PTR(ary) + beg + len,
01467 VALUE, RARRAY_LEN(ary) - (beg + len));
01468 ARY_SET_LEN(ary, alen);
01469 }
01470 if (rlen > 0) {
01471 MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
01472 }
01473 }
01474 RB_GC_GUARD(rpl);
01475 }
01476
01477 void
01478 rb_ary_set_len(VALUE ary, long len)
01479 {
01480 long capa;
01481
01482 rb_ary_modify_check(ary);
01483 if (ARY_SHARED_P(ary)) {
01484 rb_raise(rb_eRuntimeError, "can't set length of shared ");
01485 }
01486 if (len > (capa = (long)ARY_CAPA(ary))) {
01487 rb_bug("probable buffer overflow: %ld for %ld", len, capa);
01488 }
01489 ARY_SET_LEN(ary, len);
01490 }
01491
01500 VALUE
01501 rb_ary_resize(VALUE ary, long len)
01502 {
01503 long olen;
01504
01505 rb_ary_modify(ary);
01506 olen = RARRAY_LEN(ary);
01507 if (len == olen) return ary;
01508 if (len > ARY_MAX_SIZE) {
01509 rb_raise(rb_eIndexError, "index %ld too big", len);
01510 }
01511 if (len > olen) {
01512 if (len >= ARY_CAPA(ary)) {
01513 ary_double_capa(ary, len);
01514 }
01515 rb_mem_clear(RARRAY_PTR(ary) + olen, len - olen);
01516 ARY_SET_LEN(ary, len);
01517 }
01518 else if (ARY_EMBED_P(ary)) {
01519 ARY_SET_EMBED_LEN(ary, len);
01520 }
01521 else if (len <= RARRAY_EMBED_LEN_MAX) {
01522 VALUE tmp[RARRAY_EMBED_LEN_MAX];
01523 MEMCPY(tmp, ARY_HEAP_PTR(ary), VALUE, len);
01524 ary_discard(ary);
01525 MEMCPY(ARY_EMBED_PTR(ary), tmp, VALUE, len);
01526 ARY_SET_EMBED_LEN(ary, len);
01527 }
01528 else {
01529 if (olen > len + ARY_DEFAULT_SIZE) {
01530 REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, len);
01531 ARY_SET_CAPA(ary, len);
01532 }
01533 ARY_SET_HEAP_LEN(ary, len);
01534 }
01535 return ary;
01536 }
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573 static VALUE
01574 rb_ary_aset(int argc, VALUE *argv, VALUE ary)
01575 {
01576 long offset, beg, len;
01577
01578 if (argc == 3) {
01579 rb_ary_modify_check(ary);
01580 beg = NUM2LONG(argv[0]);
01581 len = NUM2LONG(argv[1]);
01582 rb_ary_splice(ary, beg, len, argv[2]);
01583 return argv[2];
01584 }
01585 rb_check_arity(argc, 2, 2);
01586 rb_ary_modify_check(ary);
01587 if (FIXNUM_P(argv[0])) {
01588 offset = FIX2LONG(argv[0]);
01589 goto fixnum;
01590 }
01591 if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
01592
01593 rb_ary_splice(ary, beg, len, argv[1]);
01594 return argv[1];
01595 }
01596
01597 offset = NUM2LONG(argv[0]);
01598 fixnum:
01599 rb_ary_store(ary, offset, argv[1]);
01600 return argv[1];
01601 }
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617 static VALUE
01618 rb_ary_insert(int argc, VALUE *argv, VALUE ary)
01619 {
01620 long pos;
01621
01622 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
01623 rb_ary_modify_check(ary);
01624 if (argc == 1) return ary;
01625 pos = NUM2LONG(argv[0]);
01626 if (pos == -1) {
01627 pos = RARRAY_LEN(ary);
01628 }
01629 if (pos < 0) {
01630 pos++;
01631 }
01632 rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
01633 return ary;
01634 }
01635
01636 static VALUE
01637 rb_ary_length(VALUE ary);
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657 VALUE
01658 rb_ary_each(VALUE array)
01659 {
01660 long i;
01661 volatile VALUE ary = array;
01662
01663 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
01664 for (i=0; i<RARRAY_LEN(ary); i++) {
01665 rb_yield(RARRAY_PTR(ary)[i]);
01666 }
01667 return ary;
01668 }
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688 static VALUE
01689 rb_ary_each_index(VALUE ary)
01690 {
01691 long i;
01692 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
01693
01694 for (i=0; i<RARRAY_LEN(ary); i++) {
01695 rb_yield(LONG2NUM(i));
01696 }
01697 return ary;
01698 }
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 static VALUE
01716 rb_ary_reverse_each(VALUE ary)
01717 {
01718 long len;
01719
01720 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
01721 len = RARRAY_LEN(ary);
01722 while (len--) {
01723 rb_yield(RARRAY_PTR(ary)[len]);
01724 if (RARRAY_LEN(ary) < len) {
01725 len = RARRAY_LEN(ary);
01726 }
01727 }
01728 return ary;
01729 }
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741 static VALUE
01742 rb_ary_length(VALUE ary)
01743 {
01744 long len = RARRAY_LEN(ary);
01745 return LONG2NUM(len);
01746 }
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757 static VALUE
01758 rb_ary_empty_p(VALUE ary)
01759 {
01760 if (RARRAY_LEN(ary) == 0)
01761 return Qtrue;
01762 return Qfalse;
01763 }
01764
01765 VALUE
01766 rb_ary_dup(VALUE ary)
01767 {
01768 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
01769 MEMCPY(RARRAY_PTR(dup), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
01770 ARY_SET_LEN(dup, RARRAY_LEN(ary));
01771 return dup;
01772 }
01773
01774 VALUE
01775 rb_ary_resurrect(VALUE ary)
01776 {
01777 return rb_ary_new4(RARRAY_LEN(ary), RARRAY_PTR(ary));
01778 }
01779
01780 extern VALUE rb_output_fs;
01781
01782 static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
01783
01784 static VALUE
01785 recursive_join(VALUE obj, VALUE argp, int recur)
01786 {
01787 VALUE *arg = (VALUE *)argp;
01788 VALUE ary = arg[0];
01789 VALUE sep = arg[1];
01790 VALUE result = arg[2];
01791 int *first = (int *)arg[3];
01792
01793 if (recur) {
01794 rb_raise(rb_eArgError, "recursive array join");
01795 }
01796 else {
01797 ary_join_1(obj, ary, sep, 0, result, first);
01798 }
01799 return Qnil;
01800 }
01801
01802 static void
01803 ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
01804 {
01805 long i;
01806 VALUE val;
01807
01808 if (max > 0) rb_enc_copy(result, RARRAY_PTR(ary)[0]);
01809 for (i=0; i<max; i++) {
01810 val = RARRAY_PTR(ary)[i];
01811 if (i > 0 && !NIL_P(sep))
01812 rb_str_buf_append(result, sep);
01813 rb_str_buf_append(result, val);
01814 if (OBJ_TAINTED(val)) OBJ_TAINT(result);
01815 if (OBJ_UNTRUSTED(val)) OBJ_TAINT(result);
01816 }
01817 }
01818
01819 static void
01820 ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
01821 {
01822 VALUE val, tmp;
01823
01824 for (; i<RARRAY_LEN(ary); i++) {
01825 if (i > 0 && !NIL_P(sep))
01826 rb_str_buf_append(result, sep);
01827
01828 val = RARRAY_PTR(ary)[i];
01829 switch (TYPE(val)) {
01830 case T_STRING:
01831 str_join:
01832 rb_str_buf_append(result, val);
01833 *first = FALSE;
01834 break;
01835 case T_ARRAY:
01836 obj = val;
01837 ary_join:
01838 if (val == ary) {
01839 rb_raise(rb_eArgError, "recursive array join");
01840 }
01841 else {
01842 VALUE args[4];
01843
01844 args[0] = val;
01845 args[1] = sep;
01846 args[2] = result;
01847 args[3] = (VALUE)first;
01848 rb_exec_recursive(recursive_join, obj, (VALUE)args);
01849 }
01850 break;
01851 default:
01852 tmp = rb_check_string_type(val);
01853 if (!NIL_P(tmp)) {
01854 val = tmp;
01855 goto str_join;
01856 }
01857 tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_ary");
01858 if (!NIL_P(tmp)) {
01859 obj = val;
01860 val = tmp;
01861 goto ary_join;
01862 }
01863 val = rb_obj_as_string(val);
01864 if (*first) {
01865 rb_enc_copy(result, val);
01866 *first = FALSE;
01867 }
01868 goto str_join;
01869 }
01870 }
01871 }
01872
01873 VALUE
01874 rb_ary_join(VALUE ary, VALUE sep)
01875 {
01876 long len = 1, i;
01877 int taint = FALSE;
01878 int untrust = FALSE;
01879 VALUE val, tmp, result;
01880
01881 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
01882 if (OBJ_TAINTED(ary)) taint = TRUE;
01883 if (OBJ_UNTRUSTED(ary)) untrust = TRUE;
01884
01885 if (!NIL_P(sep)) {
01886 StringValue(sep);
01887 len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
01888 }
01889 for (i=0; i<RARRAY_LEN(ary); i++) {
01890 val = RARRAY_PTR(ary)[i];
01891 tmp = rb_check_string_type(val);
01892
01893 if (NIL_P(tmp) || tmp != val) {
01894 int first;
01895 result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10);
01896 rb_enc_associate(result, rb_usascii_encoding());
01897 if (taint) OBJ_TAINT(result);
01898 if (untrust) OBJ_UNTRUST(result);
01899 ary_join_0(ary, sep, i, result);
01900 first = i == 0;
01901 ary_join_1(ary, ary, sep, i, result, &first);
01902 return result;
01903 }
01904
01905 len += RSTRING_LEN(tmp);
01906 }
01907
01908 result = rb_str_buf_new(len);
01909 if (taint) OBJ_TAINT(result);
01910 if (untrust) OBJ_UNTRUST(result);
01911 ary_join_0(ary, sep, RARRAY_LEN(ary), result);
01912
01913 return result;
01914 }
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929 static VALUE
01930 rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
01931 {
01932 VALUE sep;
01933
01934 rb_scan_args(argc, argv, "01", &sep);
01935 if (NIL_P(sep)) sep = rb_output_fs;
01936
01937 return rb_ary_join(ary, sep);
01938 }
01939
01940 static VALUE
01941 inspect_ary(VALUE ary, VALUE dummy, int recur)
01942 {
01943 int tainted = OBJ_TAINTED(ary);
01944 int untrust = OBJ_UNTRUSTED(ary);
01945 long i;
01946 VALUE s, str;
01947
01948 if (recur) return rb_usascii_str_new_cstr("[...]");
01949 str = rb_str_buf_new2("[");
01950 for (i=0; i<RARRAY_LEN(ary); i++) {
01951 s = rb_inspect(RARRAY_PTR(ary)[i]);
01952 if (OBJ_TAINTED(s)) tainted = TRUE;
01953 if (OBJ_UNTRUSTED(s)) untrust = TRUE;
01954 if (i > 0) rb_str_buf_cat2(str, ", ");
01955 else rb_enc_copy(str, s);
01956 rb_str_buf_append(str, s);
01957 }
01958 rb_str_buf_cat2(str, "]");
01959 if (tainted) OBJ_TAINT(str);
01960 if (untrust) OBJ_UNTRUST(str);
01961 return str;
01962 }
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974 static VALUE
01975 rb_ary_inspect(VALUE ary)
01976 {
01977 if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
01978 return rb_exec_recursive(inspect_ary, ary, 0);
01979 }
01980
01981 VALUE
01982 rb_ary_to_s(VALUE ary)
01983 {
01984 return rb_ary_inspect(ary);
01985 }
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996 static VALUE
01997 rb_ary_to_a(VALUE ary)
01998 {
01999 if (rb_obj_class(ary) != rb_cArray) {
02000 VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
02001 rb_ary_replace(dup, ary);
02002 return dup;
02003 }
02004 return ary;
02005 }
02006
02007
02008
02009
02010
02011
02012
02013
02014 static VALUE
02015 rb_ary_to_ary_m(VALUE ary)
02016 {
02017 return ary;
02018 }
02019
02020 static void
02021 ary_reverse(VALUE *p1, VALUE *p2)
02022 {
02023 while (p1 < p2) {
02024 VALUE tmp = *p1;
02025 *p1++ = *p2;
02026 *p2-- = tmp;
02027 }
02028 }
02029
02030 VALUE
02031 rb_ary_reverse(VALUE ary)
02032 {
02033 VALUE *p1, *p2;
02034
02035 rb_ary_modify(ary);
02036 if (RARRAY_LEN(ary) > 1) {
02037 p1 = RARRAY_PTR(ary);
02038 p2 = p1 + RARRAY_LEN(ary) - 1;
02039 ary_reverse(p1, p2);
02040 }
02041 return ary;
02042 }
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055 static VALUE
02056 rb_ary_reverse_bang(VALUE ary)
02057 {
02058 return rb_ary_reverse(ary);
02059 }
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071 static VALUE
02072 rb_ary_reverse_m(VALUE ary)
02073 {
02074 long len = RARRAY_LEN(ary);
02075 VALUE dup = rb_ary_new2(len);
02076
02077 if (len > 0) {
02078 VALUE *p1 = RARRAY_PTR(ary);
02079 VALUE *p2 = RARRAY_PTR(dup) + len - 1;
02080 do *p2-- = *p1++; while (--len > 0);
02081 }
02082 ARY_SET_LEN(dup, RARRAY_LEN(ary));
02083 return dup;
02084 }
02085
02086 static inline long
02087 rotate_count(long cnt, long len)
02088 {
02089 return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
02090 }
02091
02092 VALUE
02093 rb_ary_rotate(VALUE ary, long cnt)
02094 {
02095 rb_ary_modify(ary);
02096
02097 if (cnt != 0) {
02098 VALUE *ptr = RARRAY_PTR(ary);
02099 long len = RARRAY_LEN(ary);
02100
02101 if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
02102 --len;
02103 if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
02104 if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
02105 if (len > 0) ary_reverse(ptr, ptr + len);
02106 return ary;
02107 }
02108 }
02109
02110 return Qnil;
02111 }
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130 static VALUE
02131 rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
02132 {
02133 long n = 1;
02134
02135 switch (argc) {
02136 case 1: n = NUM2LONG(argv[0]);
02137 case 0: break;
02138 default: rb_scan_args(argc, argv, "01", NULL);
02139 }
02140 rb_ary_rotate(ary, n);
02141 return ary;
02142 }
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161 static VALUE
02162 rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
02163 {
02164 VALUE rotated, *ptr, *ptr2;
02165 long len, cnt = 1;
02166
02167 switch (argc) {
02168 case 1: cnt = NUM2LONG(argv[0]);
02169 case 0: break;
02170 default: rb_scan_args(argc, argv, "01", NULL);
02171 }
02172
02173 len = RARRAY_LEN(ary);
02174 rotated = rb_ary_new2(len);
02175 if (len > 0) {
02176 cnt = rotate_count(cnt, len);
02177 ptr = RARRAY_PTR(ary);
02178 ptr2 = RARRAY_PTR(rotated);
02179 len -= cnt;
02180 MEMCPY(ptr2, ptr + cnt, VALUE, len);
02181 MEMCPY(ptr2 + len, ptr, VALUE, cnt);
02182 }
02183 ARY_SET_LEN(rotated, RARRAY_LEN(ary));
02184 return rotated;
02185 }
02186
02187 struct ary_sort_data {
02188 VALUE ary;
02189 int opt_methods;
02190 int opt_inited;
02191 };
02192
02193 enum {
02194 sort_opt_Fixnum,
02195 sort_opt_String,
02196 sort_optimizable_count
02197 };
02198
02199 #define STRING_P(s) (RB_TYPE_P((s), T_STRING) && CLASS_OF(s) == rb_cString)
02200
02201 #define SORT_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(sort_opt_,type))
02202 #define SORT_OPTIMIZABLE(data, type) \
02203 (((data)->opt_inited & SORT_OPTIMIZABLE_BIT(type)) ? \
02204 ((data)->opt_methods & SORT_OPTIMIZABLE_BIT(type)) : \
02205 (((data)->opt_inited |= SORT_OPTIMIZABLE_BIT(type)), \
02206 rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \
02207 ((data)->opt_methods |= SORT_OPTIMIZABLE_BIT(type))))
02208
02209 static VALUE
02210 sort_reentered(VALUE ary)
02211 {
02212 if (RBASIC(ary)->klass) {
02213 rb_raise(rb_eRuntimeError, "sort reentered");
02214 }
02215 return Qnil;
02216 }
02217
02218 static int
02219 sort_1(const void *ap, const void *bp, void *dummy)
02220 {
02221 struct ary_sort_data *data = dummy;
02222 VALUE retval = sort_reentered(data->ary);
02223 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
02224 int n;
02225
02226 retval = rb_yield_values(2, a, b);
02227 n = rb_cmpint(retval, a, b);
02228 sort_reentered(data->ary);
02229 return n;
02230 }
02231
02232 static int
02233 sort_2(const void *ap, const void *bp, void *dummy)
02234 {
02235 struct ary_sort_data *data = dummy;
02236 VALUE retval = sort_reentered(data->ary);
02237 VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
02238 int n;
02239
02240 if (FIXNUM_P(a) && FIXNUM_P(b) && SORT_OPTIMIZABLE(data, Fixnum)) {
02241 if ((long)a > (long)b) return 1;
02242 if ((long)a < (long)b) return -1;
02243 return 0;
02244 }
02245 if (STRING_P(a) && STRING_P(b) && SORT_OPTIMIZABLE(data, String)) {
02246 return rb_str_cmp(a, b);
02247 }
02248
02249 retval = rb_funcall(a, id_cmp, 1, b);
02250 n = rb_cmpint(retval, a, b);
02251 sort_reentered(data->ary);
02252
02253 return n;
02254 }
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277 VALUE
02278 rb_ary_sort_bang(VALUE ary)
02279 {
02280 rb_ary_modify(ary);
02281 assert(!ARY_SHARED_P(ary));
02282 if (RARRAY_LEN(ary) > 1) {
02283 VALUE tmp = ary_make_substitution(ary);
02284 struct ary_sort_data data;
02285 long len = RARRAY_LEN(ary);
02286
02287 RBASIC(tmp)->klass = 0;
02288 data.ary = tmp;
02289 data.opt_methods = 0;
02290 data.opt_inited = 0;
02291 ruby_qsort(RARRAY_PTR(tmp), len, sizeof(VALUE),
02292 rb_block_given_p()?sort_1:sort_2, &data);
02293
02294 if (ARY_EMBED_P(tmp)) {
02295 assert(ARY_EMBED_P(tmp));
02296 if (ARY_SHARED_P(ary)) {
02297 rb_ary_unshare(ary);
02298 }
02299 FL_SET_EMBED(ary);
02300 MEMCPY(RARRAY_PTR(ary), ARY_EMBED_PTR(tmp), VALUE, ARY_EMBED_LEN(tmp));
02301 ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
02302 }
02303 else {
02304 assert(!ARY_EMBED_P(tmp));
02305 if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
02306 assert(!ARY_EMBED_P(ary));
02307 FL_UNSET_SHARED(ary);
02308 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
02309 }
02310 else {
02311 assert(!ARY_SHARED_P(tmp));
02312 if (ARY_EMBED_P(ary)) {
02313 FL_UNSET_EMBED(ary);
02314 }
02315 else if (ARY_SHARED_P(ary)) {
02316
02317 rb_ary_unshare(ary);
02318 }
02319 else {
02320 xfree(ARY_HEAP_PTR(ary));
02321 }
02322 ARY_SET_PTR(ary, RARRAY_PTR(tmp));
02323 ARY_SET_HEAP_LEN(ary, len);
02324 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
02325 }
02326
02327 FL_UNSET(tmp, FL_FREEZE);
02328 FL_SET_EMBED(tmp);
02329 ARY_SET_EMBED_LEN(tmp, 0);
02330 FL_SET(tmp, FL_FREEZE);
02331 }
02332
02333 RBASIC(tmp)->klass = rb_cArray;
02334 }
02335 return ary;
02336 }
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360 VALUE
02361 rb_ary_sort(VALUE ary)
02362 {
02363 ary = rb_ary_dup(ary);
02364 rb_ary_sort_bang(ary);
02365 return ary;
02366 }
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421 static VALUE
02422 rb_ary_bsearch(VALUE ary)
02423 {
02424 long low = 0, high = RARRAY_LEN(ary), mid;
02425 int smaller = 0, satisfied = 0;
02426 VALUE v, val;
02427
02428 RETURN_ENUMERATOR(ary, 0, 0);
02429 while (low < high) {
02430 mid = low + ((high - low) / 2);
02431 val = rb_ary_entry(ary, mid);
02432 v = rb_yield(val);
02433 if (FIXNUM_P(v)) {
02434 if (FIX2INT(v) == 0) return val;
02435 smaller = FIX2INT(v) < 0;
02436 }
02437 else if (v == Qtrue) {
02438 satisfied = 1;
02439 smaller = 1;
02440 }
02441 else if (v == Qfalse || v == Qnil) {
02442 smaller = 0;
02443 }
02444 else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
02445 switch (rb_cmpint(rb_funcall(v, id_cmp, 1, INT2FIX(0)), v, INT2FIX(0))) {
02446 case 0: return val;
02447 case 1: smaller = 1; break;
02448 case -1: smaller = 0;
02449 }
02450 }
02451 else {
02452 rb_raise(rb_eTypeError, "wrong argument type %s"
02453 " (must be numeric, true, false or nil)",
02454 rb_obj_classname(v));
02455 }
02456 if (smaller) {
02457 high = mid;
02458 }
02459 else {
02460 low = mid + 1;
02461 }
02462 }
02463 if (low == RARRAY_LEN(ary)) return Qnil;
02464 if (!satisfied) return Qnil;
02465 return rb_ary_entry(ary, low);
02466 }
02467
02468
02469 static VALUE
02470 sort_by_i(VALUE i)
02471 {
02472 return rb_yield(i);
02473 }
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487 static VALUE
02488 rb_ary_sort_by_bang(VALUE ary)
02489 {
02490 VALUE sorted;
02491
02492 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
02493 rb_ary_modify(ary);
02494 sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
02495 rb_ary_replace(ary, sorted);
02496 return ary;
02497 }
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520 static VALUE
02521 rb_ary_collect(VALUE ary)
02522 {
02523 long i;
02524 VALUE collect;
02525
02526 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
02527 collect = rb_ary_new2(RARRAY_LEN(ary));
02528 for (i = 0; i < RARRAY_LEN(ary); i++) {
02529 rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
02530 }
02531 return collect;
02532 }
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554 static VALUE
02555 rb_ary_collect_bang(VALUE ary)
02556 {
02557 long i;
02558
02559 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
02560 rb_ary_modify(ary);
02561 for (i = 0; i < RARRAY_LEN(ary); i++) {
02562 rb_ary_store(ary, i, rb_yield(RARRAY_PTR(ary)[i]));
02563 }
02564 return ary;
02565 }
02566
02567 VALUE
02568 rb_get_values_at(VALUE obj, long olen, int argc, VALUE *argv, VALUE (*func) (VALUE, long))
02569 {
02570 VALUE result = rb_ary_new2(argc);
02571 long beg, len, i, j;
02572
02573 for (i=0; i<argc; i++) {
02574 if (FIXNUM_P(argv[i])) {
02575 rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
02576 continue;
02577 }
02578
02579 if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
02580 long end = olen < beg+len ? olen : beg+len;
02581 for (j = beg; j < end; j++) {
02582 rb_ary_push(result, (*func)(obj, j));
02583 }
02584 if (beg + len > j)
02585 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
02586 continue;
02587 }
02588 rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
02589 }
02590 return result;
02591 }
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611 static VALUE
02612 rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
02613 {
02614 return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
02615 }
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636 static VALUE
02637 rb_ary_select(VALUE ary)
02638 {
02639 VALUE result;
02640 long i;
02641
02642 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
02643 result = rb_ary_new2(RARRAY_LEN(ary));
02644 for (i = 0; i < RARRAY_LEN(ary); i++) {
02645 if (RTEST(rb_yield(RARRAY_PTR(ary)[i]))) {
02646 rb_ary_push(result, rb_ary_elt(ary, i));
02647 }
02648 }
02649 return result;
02650 }
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668 static VALUE
02669 rb_ary_select_bang(VALUE ary)
02670 {
02671 long i1, i2;
02672
02673 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
02674 rb_ary_modify(ary);
02675 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
02676 VALUE v = RARRAY_PTR(ary)[i1];
02677 if (!RTEST(rb_yield(v))) continue;
02678 if (i1 != i2) {
02679 rb_ary_store(ary, i2, v);
02680 }
02681 i2++;
02682 }
02683
02684 if (RARRAY_LEN(ary) == i2) return Qnil;
02685 if (i2 < RARRAY_LEN(ary))
02686 ARY_SET_LEN(ary, i2);
02687 return ary;
02688 }
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706 static VALUE
02707 rb_ary_keep_if(VALUE ary)
02708 {
02709 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
02710 rb_ary_select_bang(ary);
02711 return ary;
02712 }
02713
02714 static void
02715 ary_resize_smaller(VALUE ary, long len)
02716 {
02717 rb_ary_modify(ary);
02718 if (RARRAY_LEN(ary) > len) {
02719 ARY_SET_LEN(ary, len);
02720 if (len * 2 < ARY_CAPA(ary) &&
02721 ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
02722 ary_resize_capa(ary, len * 2);
02723 }
02724 }
02725 }
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747 VALUE
02748 rb_ary_delete(VALUE ary, VALUE item)
02749 {
02750 VALUE v = item;
02751 long i1, i2;
02752
02753 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
02754 VALUE e = RARRAY_PTR(ary)[i1];
02755
02756 if (rb_equal(e, item)) {
02757 v = e;
02758 continue;
02759 }
02760 if (i1 != i2) {
02761 rb_ary_store(ary, i2, e);
02762 }
02763 i2++;
02764 }
02765 if (RARRAY_LEN(ary) == i2) {
02766 if (rb_block_given_p()) {
02767 return rb_yield(item);
02768 }
02769 return Qnil;
02770 }
02771
02772 ary_resize_smaller(ary, i2);
02773
02774 return v;
02775 }
02776
02777 void
02778 rb_ary_delete_same(VALUE ary, VALUE item)
02779 {
02780 long i1, i2;
02781
02782 for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
02783 VALUE e = RARRAY_PTR(ary)[i1];
02784
02785 if (e == item) {
02786 continue;
02787 }
02788 if (i1 != i2) {
02789 rb_ary_store(ary, i2, e);
02790 }
02791 i2++;
02792 }
02793 if (RARRAY_LEN(ary) == i2) {
02794 return;
02795 }
02796
02797 ary_resize_smaller(ary, i2);
02798 }
02799
02800 VALUE
02801 rb_ary_delete_at(VALUE ary, long pos)
02802 {
02803 long len = RARRAY_LEN(ary);
02804 VALUE del;
02805
02806 if (pos >= len) return Qnil;
02807 if (pos < 0) {
02808 pos += len;
02809 if (pos < 0) return Qnil;
02810 }
02811
02812 rb_ary_modify(ary);
02813 del = RARRAY_PTR(ary)[pos];
02814 MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
02815 RARRAY_LEN(ary)-pos-1);
02816 ARY_INCREASE_LEN(ary, -1);
02817
02818 return del;
02819 }
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835
02836 static VALUE
02837 rb_ary_delete_at_m(VALUE ary, VALUE pos)
02838 {
02839 return rb_ary_delete_at(ary, NUM2LONG(pos));
02840 }
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863 static VALUE
02864 rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
02865 {
02866 VALUE arg1, arg2;
02867 long pos, len, orig_len;
02868
02869 rb_ary_modify_check(ary);
02870 if (argc == 2) {
02871 pos = NUM2LONG(argv[0]);
02872 len = NUM2LONG(argv[1]);
02873 delete_pos_len:
02874 if (len < 0) return Qnil;
02875 orig_len = RARRAY_LEN(ary);
02876 if (pos < 0) {
02877 pos += orig_len;
02878 if (pos < 0) return Qnil;
02879 }
02880 else if (orig_len < pos) return Qnil;
02881 if (orig_len < pos + len) {
02882 len = orig_len - pos;
02883 }
02884 if (len == 0) return rb_ary_new2(0);
02885 arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
02886 RBASIC(arg2)->klass = rb_obj_class(ary);
02887 rb_ary_splice(ary, pos, len, Qundef);
02888 return arg2;
02889 }
02890
02891 if (argc != 1) {
02892
02893 rb_scan_args(argc, argv, "11", NULL, NULL);
02894 }
02895 arg1 = argv[0];
02896
02897 if (!FIXNUM_P(arg1)) {
02898 switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
02899 case Qtrue:
02900
02901 goto delete_pos_len;
02902 case Qnil:
02903
02904 return Qnil;
02905 default:
02906
02907 break;
02908 }
02909 }
02910
02911 return rb_ary_delete_at(ary, NUM2LONG(arg1));
02912 }
02913
02914 static VALUE
02915 ary_reject(VALUE orig, VALUE result)
02916 {
02917 long i;
02918
02919 for (i = 0; i < RARRAY_LEN(orig); i++) {
02920 VALUE v = RARRAY_PTR(orig)[i];
02921 if (!RTEST(rb_yield(v))) {
02922 rb_ary_push(result, v);
02923 }
02924 }
02925 return result;
02926 }
02927
02928 static VALUE
02929 ary_reject_bang(VALUE ary)
02930 {
02931 long i;
02932 VALUE result = Qnil;
02933
02934 rb_ary_modify_check(ary);
02935 for (i = 0; i < RARRAY_LEN(ary); ) {
02936 VALUE v = RARRAY_PTR(ary)[i];
02937 if (RTEST(rb_yield(v))) {
02938 rb_ary_delete_at(ary, i);
02939 result = ary;
02940 }
02941 else {
02942 i++;
02943 }
02944 }
02945 return result;
02946 }
02947
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964 static VALUE
02965 rb_ary_reject_bang(VALUE ary)
02966 {
02967 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
02968 return ary_reject_bang(ary);
02969 }
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984 static VALUE
02985 rb_ary_reject(VALUE ary)
02986 {
02987 VALUE rejected_ary;
02988
02989 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
02990 rejected_ary = rb_ary_new();
02991 ary_reject(ary, rejected_ary);
02992 return rejected_ary;
02993 }
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013 static VALUE
03014 rb_ary_delete_if(VALUE ary)
03015 {
03016 RETURN_SIZED_ENUMERATOR(ary, 0, 0, rb_ary_length);
03017 ary_reject_bang(ary);
03018 return ary;
03019 }
03020
03021 static VALUE
03022 take_i(VALUE val, VALUE *args, int argc, VALUE *argv)
03023 {
03024 if (args[1]-- == 0) rb_iter_break();
03025 if (argc > 1) val = rb_ary_new4(argc, argv);
03026 rb_ary_push(args[0], val);
03027 return Qnil;
03028 }
03029
03030 static VALUE
03031 take_items(VALUE obj, long n)
03032 {
03033 VALUE result = rb_check_array_type(obj);
03034 VALUE args[2];
03035
03036 if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
03037 result = rb_ary_new2(n);
03038 args[0] = result; args[1] = (VALUE)n;
03039 if (rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args) == Qundef)
03040 rb_raise(rb_eTypeError, "wrong argument type %s (must respond to :each)",
03041 rb_obj_classname(obj));
03042 return result;
03043 }
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070 static VALUE
03071 rb_ary_zip(int argc, VALUE *argv, VALUE ary)
03072 {
03073 int i, j;
03074 long len;
03075 VALUE result = Qnil;
03076
03077 len = RARRAY_LEN(ary);
03078 for (i=0; i<argc; i++) {
03079 argv[i] = take_items(argv[i], len);
03080 }
03081 if (!rb_block_given_p()) {
03082 result = rb_ary_new2(len);
03083 }
03084
03085 for (i=0; i<RARRAY_LEN(ary); i++) {
03086 VALUE tmp = rb_ary_new2(argc+1);
03087
03088 rb_ary_push(tmp, rb_ary_elt(ary, i));
03089 for (j=0; j<argc; j++) {
03090 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
03091 }
03092 if (NIL_P(result)) {
03093 rb_yield(tmp);
03094 }
03095 else {
03096 rb_ary_push(result, tmp);
03097 }
03098 }
03099 return result;
03100 }
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115 static VALUE
03116 rb_ary_transpose(VALUE ary)
03117 {
03118 long elen = -1, alen, i, j;
03119 VALUE tmp, result = 0;
03120
03121 alen = RARRAY_LEN(ary);
03122 if (alen == 0) return rb_ary_dup(ary);
03123 for (i=0; i<alen; i++) {
03124 tmp = to_ary(rb_ary_elt(ary, i));
03125 if (elen < 0) {
03126 elen = RARRAY_LEN(tmp);
03127 result = rb_ary_new2(elen);
03128 for (j=0; j<elen; j++) {
03129 rb_ary_store(result, j, rb_ary_new2(alen));
03130 }
03131 }
03132 else if (elen != RARRAY_LEN(tmp)) {
03133 rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
03134 RARRAY_LEN(tmp), elen);
03135 }
03136 for (j=0; j<elen; j++) {
03137 rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
03138 }
03139 }
03140 return result;
03141 }
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155 VALUE
03156 rb_ary_replace(VALUE copy, VALUE orig)
03157 {
03158 rb_ary_modify_check(copy);
03159 orig = to_ary(orig);
03160 if (copy == orig) return copy;
03161
03162 if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
03163 VALUE *ptr;
03164 VALUE shared = 0;
03165
03166 if (ARY_OWNS_HEAP_P(copy)) {
03167 xfree(RARRAY_PTR(copy));
03168 }
03169 else if (ARY_SHARED_P(copy)) {
03170 shared = ARY_SHARED(copy);
03171 FL_UNSET_SHARED(copy);
03172 }
03173 FL_SET_EMBED(copy);
03174 ptr = RARRAY_PTR(orig);
03175 MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
03176 if (shared) {
03177 rb_ary_decrement_share(shared);
03178 }
03179 ARY_SET_LEN(copy, RARRAY_LEN(orig));
03180 }
03181 else {
03182 VALUE shared = ary_make_shared(orig);
03183 if (ARY_OWNS_HEAP_P(copy)) {
03184 xfree(RARRAY_PTR(copy));
03185 }
03186 else {
03187 rb_ary_unshare_safe(copy);
03188 }
03189 FL_UNSET_EMBED(copy);
03190 ARY_SET_PTR(copy, RARRAY_PTR(orig));
03191 ARY_SET_LEN(copy, RARRAY_LEN(orig));
03192 rb_ary_set_shared(copy, shared);
03193 }
03194 return copy;
03195 }
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207 VALUE
03208 rb_ary_clear(VALUE ary)
03209 {
03210 rb_ary_modify_check(ary);
03211 ARY_SET_LEN(ary, 0);
03212 if (ARY_SHARED_P(ary)) {
03213 if (!ARY_EMBED_P(ary)) {
03214 rb_ary_unshare(ary);
03215 FL_SET_EMBED(ary);
03216 }
03217 }
03218 else if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
03219 ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
03220 }
03221 return ary;
03222 }
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254 static VALUE
03255 rb_ary_fill(int argc, VALUE *argv, VALUE ary)
03256 {
03257 VALUE item, arg1, arg2;
03258 long beg = 0, end = 0, len = 0;
03259 VALUE *p, *pend;
03260 int block_p = FALSE;
03261
03262 if (rb_block_given_p()) {
03263 block_p = TRUE;
03264 rb_scan_args(argc, argv, "02", &arg1, &arg2);
03265 argc += 1;
03266 }
03267 else {
03268 rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
03269 }
03270 switch (argc) {
03271 case 1:
03272 beg = 0;
03273 len = RARRAY_LEN(ary);
03274 break;
03275 case 2:
03276 if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
03277 break;
03278 }
03279
03280 case 3:
03281 beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
03282 if (beg < 0) {
03283 beg = RARRAY_LEN(ary) + beg;
03284 if (beg < 0) beg = 0;
03285 }
03286 len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
03287 break;
03288 }
03289 rb_ary_modify(ary);
03290 if (len < 0) {
03291 return ary;
03292 }
03293 if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
03294 rb_raise(rb_eArgError, "argument too big");
03295 }
03296 end = beg + len;
03297 if (RARRAY_LEN(ary) < end) {
03298 if (end >= ARY_CAPA(ary)) {
03299 ary_resize_capa(ary, end);
03300 }
03301 rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
03302 ARY_SET_LEN(ary, end);
03303 }
03304
03305 if (block_p) {
03306 VALUE v;
03307 long i;
03308
03309 for (i=beg; i<end; i++) {
03310 v = rb_yield(LONG2NUM(i));
03311 if (i>=RARRAY_LEN(ary)) break;
03312 RARRAY_PTR(ary)[i] = v;
03313 }
03314 }
03315 else {
03316 p = RARRAY_PTR(ary) + beg;
03317 pend = p + len;
03318 while (p < pend) {
03319 *p++ = item;
03320 }
03321 }
03322 return ary;
03323 }
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340 VALUE
03341 rb_ary_plus(VALUE x, VALUE y)
03342 {
03343 VALUE z;
03344 long len;
03345
03346 y = to_ary(y);
03347 len = RARRAY_LEN(x) + RARRAY_LEN(y);
03348 z = rb_ary_new2(len);
03349 MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
03350 MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
03351 ARY_SET_LEN(z, len);
03352 return z;
03353 }
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369 VALUE
03370 rb_ary_concat(VALUE x, VALUE y)
03371 {
03372 rb_ary_modify_check(x);
03373 y = to_ary(y);
03374 if (RARRAY_LEN(y) > 0) {
03375 rb_ary_splice(x, RARRAY_LEN(x), 0, y);
03376 }
03377 return x;
03378 }
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398 static VALUE
03399 rb_ary_times(VALUE ary, VALUE times)
03400 {
03401 VALUE ary2, tmp, *ptr, *ptr2;
03402 long t, len;
03403
03404 tmp = rb_check_string_type(times);
03405 if (!NIL_P(tmp)) {
03406 return rb_ary_join(ary, tmp);
03407 }
03408
03409 len = NUM2LONG(times);
03410 if (len == 0) {
03411 ary2 = ary_new(rb_obj_class(ary), 0);
03412 goto out;
03413 }
03414 if (len < 0) {
03415 rb_raise(rb_eArgError, "negative argument");
03416 }
03417 if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
03418 rb_raise(rb_eArgError, "argument too big");
03419 }
03420 len *= RARRAY_LEN(ary);
03421
03422 ary2 = ary_new(rb_obj_class(ary), len);
03423 ARY_SET_LEN(ary2, len);
03424
03425 ptr = RARRAY_PTR(ary);
03426 ptr2 = RARRAY_PTR(ary2);
03427 t = RARRAY_LEN(ary);
03428 if (0 < t) {
03429 MEMCPY(ptr2, ptr, VALUE, t);
03430 while (t <= len/2) {
03431 MEMCPY(ptr2+t, ptr2, VALUE, t);
03432 t *= 2;
03433 }
03434 if (t < len) {
03435 MEMCPY(ptr2+t, ptr2, VALUE, len-t);
03436 }
03437 }
03438 out:
03439 OBJ_INFECT(ary2, ary);
03440
03441 return ary2;
03442 }
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464 VALUE
03465 rb_ary_assoc(VALUE ary, VALUE key)
03466 {
03467 long i;
03468 VALUE v;
03469
03470 for (i = 0; i < RARRAY_LEN(ary); ++i) {
03471 v = rb_check_array_type(RARRAY_PTR(ary)[i]);
03472 if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
03473 rb_equal(RARRAY_PTR(v)[0], key))
03474 return v;
03475 }
03476 return Qnil;
03477 }
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497 VALUE
03498 rb_ary_rassoc(VALUE ary, VALUE value)
03499 {
03500 long i;
03501 VALUE v;
03502
03503 for (i = 0; i < RARRAY_LEN(ary); ++i) {
03504 v = RARRAY_PTR(ary)[i];
03505 if (RB_TYPE_P(v, T_ARRAY) &&
03506 RARRAY_LEN(v) > 1 &&
03507 rb_equal(RARRAY_PTR(v)[1], value))
03508 return v;
03509 }
03510 return Qnil;
03511 }
03512
03513 static VALUE
03514 recursive_equal(VALUE ary1, VALUE ary2, int recur)
03515 {
03516 long i, len1;
03517 VALUE *p1, *p2;
03518
03519 if (recur) return Qtrue;
03520
03521 p1 = RARRAY_PTR(ary1);
03522 p2 = RARRAY_PTR(ary2);
03523 len1 = RARRAY_LEN(ary1);
03524
03525 for (i = 0; i < len1; i++) {
03526 if (*p1 != *p2) {
03527 if (rb_equal(*p1, *p2)) {
03528 len1 = RARRAY_LEN(ary1);
03529 if (len1 != RARRAY_LEN(ary2))
03530 return Qfalse;
03531 if (len1 < i)
03532 return Qtrue;
03533 p1 = RARRAY_PTR(ary1) + i;
03534 p2 = RARRAY_PTR(ary2) + i;
03535 }
03536 else {
03537 return Qfalse;
03538 }
03539 }
03540 p1++;
03541 p2++;
03542 }
03543 return Qtrue;
03544 }
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560 static VALUE
03561 rb_ary_equal(VALUE ary1, VALUE ary2)
03562 {
03563 if (ary1 == ary2) return Qtrue;
03564 if (!RB_TYPE_P(ary2, T_ARRAY)) {
03565 if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
03566 return Qfalse;
03567 }
03568 return rb_equal(ary2, ary1);
03569 }
03570 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
03571 return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
03572 }
03573
03574 static VALUE
03575 recursive_eql(VALUE ary1, VALUE ary2, int recur)
03576 {
03577 long i;
03578
03579 if (recur) return Qtrue;
03580 for (i=0; i<RARRAY_LEN(ary1); i++) {
03581 if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
03582 return Qfalse;
03583 }
03584 return Qtrue;
03585 }
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595 static VALUE
03596 rb_ary_eql(VALUE ary1, VALUE ary2)
03597 {
03598 if (ary1 == ary2) return Qtrue;
03599 if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
03600 if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
03601 return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
03602 }
03603
03604 static VALUE
03605 recursive_hash(VALUE ary, VALUE dummy, int recur)
03606 {
03607 long i;
03608 st_index_t h;
03609 VALUE n;
03610
03611 h = rb_hash_start(RARRAY_LEN(ary));
03612 if (recur) {
03613 h = rb_hash_uint(h, NUM2LONG(rb_hash(rb_cArray)));
03614 }
03615 else {
03616 for (i=0; i<RARRAY_LEN(ary); i++) {
03617 n = rb_hash(RARRAY_PTR(ary)[i]);
03618 h = rb_hash_uint(h, NUM2LONG(n));
03619 }
03620 }
03621 h = rb_hash_end(h);
03622 return LONG2FIX(h);
03623 }
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635 static VALUE
03636 rb_ary_hash(VALUE ary)
03637 {
03638 return rb_exec_recursive_outer(recursive_hash, ary, 0);
03639 }
03640
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653 VALUE
03654 rb_ary_includes(VALUE ary, VALUE item)
03655 {
03656 long i;
03657
03658 for (i=0; i<RARRAY_LEN(ary); i++) {
03659 if (rb_equal(RARRAY_PTR(ary)[i], item)) {
03660 return Qtrue;
03661 }
03662 }
03663 return Qfalse;
03664 }
03665
03666
03667 static VALUE
03668 recursive_cmp(VALUE ary1, VALUE ary2, int recur)
03669 {
03670 long i, len;
03671
03672 if (recur) return Qundef;
03673 len = RARRAY_LEN(ary1);
03674 if (len > RARRAY_LEN(ary2)) {
03675 len = RARRAY_LEN(ary2);
03676 }
03677 for (i=0; i<len; i++) {
03678 VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
03679 if (v != INT2FIX(0)) {
03680 return v;
03681 }
03682 }
03683 return Qundef;
03684 }
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711 VALUE
03712 rb_ary_cmp(VALUE ary1, VALUE ary2)
03713 {
03714 long len;
03715 VALUE v;
03716
03717 ary2 = rb_check_array_type(ary2);
03718 if (NIL_P(ary2)) return Qnil;
03719 if (ary1 == ary2) return INT2FIX(0);
03720 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
03721 if (v != Qundef) return v;
03722 len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
03723 if (len == 0) return INT2FIX(0);
03724 if (len > 0) return INT2FIX(1);
03725 return INT2FIX(-1);
03726 }
03727
03728 static VALUE
03729 ary_add_hash(VALUE hash, VALUE ary)
03730 {
03731 long i;
03732
03733 for (i=0; i<RARRAY_LEN(ary); i++) {
03734 rb_hash_aset(hash, RARRAY_PTR(ary)[i], Qtrue);
03735 }
03736 return hash;
03737 }
03738
03739 static inline VALUE
03740 ary_tmp_hash_new(void)
03741 {
03742 VALUE hash = rb_hash_new();
03743
03744 RBASIC(hash)->klass = 0;
03745 return hash;
03746 }
03747
03748 static VALUE
03749 ary_make_hash(VALUE ary)
03750 {
03751 VALUE hash = ary_tmp_hash_new();
03752 return ary_add_hash(hash, ary);
03753 }
03754
03755 static VALUE
03756 ary_add_hash_by(VALUE hash, VALUE ary)
03757 {
03758 long i;
03759
03760 for (i = 0; i < RARRAY_LEN(ary); ++i) {
03761 VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
03762 if (rb_hash_lookup2(hash, k, Qundef) == Qundef) {
03763 rb_hash_aset(hash, k, v);
03764 }
03765 }
03766 return hash;
03767 }
03768
03769 static VALUE
03770 ary_make_hash_by(VALUE ary)
03771 {
03772 VALUE hash = ary_tmp_hash_new();
03773 return ary_add_hash_by(hash, ary);
03774 }
03775
03776 static inline void
03777 ary_recycle_hash(VALUE hash)
03778 {
03779 if (RHASH(hash)->ntbl) {
03780 st_table *tbl = RHASH(hash)->ntbl;
03781 RHASH(hash)->ntbl = 0;
03782 st_free_table(tbl);
03783 }
03784 RB_GC_GUARD(hash);
03785 }
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804 static VALUE
03805 rb_ary_diff(VALUE ary1, VALUE ary2)
03806 {
03807 VALUE ary3;
03808 VALUE hash;
03809 long i;
03810
03811 hash = ary_make_hash(to_ary(ary2));
03812 ary3 = rb_ary_new();
03813
03814 for (i=0; i<RARRAY_LEN(ary1); i++) {
03815 if (st_lookup(RHASH_TBL(hash), RARRAY_PTR(ary1)[i], 0)) continue;
03816 rb_ary_push(ary3, rb_ary_elt(ary1, i));
03817 }
03818 ary_recycle_hash(hash);
03819 return ary3;
03820 }
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839 static VALUE
03840 rb_ary_and(VALUE ary1, VALUE ary2)
03841 {
03842 VALUE hash, ary3, v;
03843 st_data_t vv;
03844 long i;
03845
03846 ary2 = to_ary(ary2);
03847 ary3 = rb_ary_new2(RARRAY_LEN(ary1) < RARRAY_LEN(ary2) ?
03848 RARRAY_LEN(ary1) : RARRAY_LEN(ary2));
03849 hash = ary_make_hash(ary2);
03850
03851 if (RHASH_EMPTY_P(hash))
03852 return ary3;
03853
03854 for (i=0; i<RARRAY_LEN(ary1); i++) {
03855 vv = (st_data_t)(v = rb_ary_elt(ary1, i));
03856 if (st_delete(RHASH_TBL(hash), &vv, 0)) {
03857 rb_ary_push(ary3, v);
03858 }
03859 }
03860 ary_recycle_hash(hash);
03861
03862 return ary3;
03863 }
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879 static VALUE
03880 rb_ary_or(VALUE ary1, VALUE ary2)
03881 {
03882 VALUE hash, ary3, v;
03883 st_data_t vv;
03884 long i;
03885
03886 ary2 = to_ary(ary2);
03887 ary3 = rb_ary_new2(RARRAY_LEN(ary1)+RARRAY_LEN(ary2));
03888 hash = ary_add_hash(ary_make_hash(ary1), ary2);
03889
03890 for (i=0; i<RARRAY_LEN(ary1); i++) {
03891 vv = (st_data_t)(v = rb_ary_elt(ary1, i));
03892 if (st_delete(RHASH_TBL(hash), &vv, 0)) {
03893 rb_ary_push(ary3, v);
03894 }
03895 }
03896 for (i=0; i<RARRAY_LEN(ary2); i++) {
03897 vv = (st_data_t)(v = rb_ary_elt(ary2, i));
03898 if (st_delete(RHASH_TBL(hash), &vv, 0)) {
03899 rb_ary_push(ary3, v);
03900 }
03901 }
03902 ary_recycle_hash(hash);
03903 return ary3;
03904 }
03905
03906 static int
03907 push_value(st_data_t key, st_data_t val, st_data_t ary)
03908 {
03909 rb_ary_push((VALUE)ary, (VALUE)val);
03910 return ST_CONTINUE;
03911 }
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935
03936
03937
03938 static VALUE
03939 rb_ary_uniq_bang(VALUE ary)
03940 {
03941 VALUE hash, v;
03942 long i, j;
03943
03944 rb_ary_modify_check(ary);
03945 if (RARRAY_LEN(ary) <= 1)
03946 return Qnil;
03947 if (rb_block_given_p()) {
03948 hash = ary_make_hash_by(ary);
03949 if (RARRAY_LEN(ary) == (i = RHASH_SIZE(hash))) {
03950 return Qnil;
03951 }
03952 ARY_SET_LEN(ary, 0);
03953 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
03954 rb_ary_unshare(ary);
03955 FL_SET_EMBED(ary);
03956 }
03957 ary_resize_capa(ary, i);
03958 st_foreach(RHASH_TBL(hash), push_value, ary);
03959 }
03960 else {
03961 hash = ary_make_hash(ary);
03962 if (RARRAY_LEN(ary) == (long)RHASH_SIZE(hash)) {
03963 return Qnil;
03964 }
03965 for (i=j=0; i<RARRAY_LEN(ary); i++) {
03966 st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
03967 if (st_delete(RHASH_TBL(hash), &vv, 0)) {
03968 rb_ary_store(ary, j++, v);
03969 }
03970 }
03971 ARY_SET_LEN(ary, j);
03972 }
03973 ary_recycle_hash(hash);
03974
03975 return ary;
03976 }
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997 static VALUE
03998 rb_ary_uniq(VALUE ary)
03999 {
04000 VALUE hash, uniq, v;
04001 long i;
04002
04003 if (RARRAY_LEN(ary) <= 1)
04004 return rb_ary_dup(ary);
04005 if (rb_block_given_p()) {
04006 hash = ary_make_hash_by(ary);
04007 uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
04008 st_foreach(RHASH_TBL(hash), push_value, uniq);
04009 }
04010 else {
04011 hash = ary_make_hash(ary);
04012 uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash));
04013 for (i=0; i<RARRAY_LEN(ary); i++) {
04014 st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i));
04015 if (st_delete(RHASH_TBL(hash), &vv, 0)) {
04016 rb_ary_push(uniq, v);
04017 }
04018 }
04019 }
04020 ary_recycle_hash(hash);
04021
04022 return uniq;
04023 }
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037 static VALUE
04038 rb_ary_compact_bang(VALUE ary)
04039 {
04040 VALUE *p, *t, *end;
04041 long n;
04042
04043 rb_ary_modify(ary);
04044 p = t = RARRAY_PTR(ary);
04045 end = p + RARRAY_LEN(ary);
04046
04047 while (t < end) {
04048 if (NIL_P(*t)) t++;
04049 else *p++ = *t++;
04050 }
04051 n = p - RARRAY_PTR(ary);
04052 if (RARRAY_LEN(ary) == n) {
04053 return Qnil;
04054 }
04055 ARY_SET_LEN(ary, n);
04056 if (n * 2 < ARY_CAPA(ary) && ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
04057 ary_resize_capa(ary, n * 2);
04058 }
04059
04060 return ary;
04061 }
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073 static VALUE
04074 rb_ary_compact(VALUE ary)
04075 {
04076 ary = rb_ary_dup(ary);
04077 rb_ary_compact_bang(ary);
04078 return ary;
04079 }
04080
04081
04082
04083
04084
04085
04086
04087
04088
04089
04090
04091
04092
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102 static VALUE
04103 rb_ary_count(int argc, VALUE *argv, VALUE ary)
04104 {
04105 long i, n = 0;
04106
04107 if (argc == 0) {
04108 VALUE v;
04109
04110 if (!rb_block_given_p())
04111 return LONG2NUM(RARRAY_LEN(ary));
04112
04113 for (i = 0; i < RARRAY_LEN(ary); i++) {
04114 v = RARRAY_PTR(ary)[i];
04115 if (RTEST(rb_yield(v))) n++;
04116 }
04117 }
04118 else {
04119 VALUE obj;
04120
04121 rb_scan_args(argc, argv, "1", &obj);
04122 if (rb_block_given_p()) {
04123 rb_warn("given block not used");
04124 }
04125 for (i = 0; i < RARRAY_LEN(ary); i++) {
04126 if (rb_equal(RARRAY_PTR(ary)[i], obj)) n++;
04127 }
04128 }
04129
04130 return LONG2NUM(n);
04131 }
04132
04133 static VALUE
04134 flatten(VALUE ary, int level, int *modified)
04135 {
04136 long i = 0;
04137 VALUE stack, result, tmp, elt;
04138 st_table *memo;
04139 st_data_t id;
04140
04141 stack = ary_new(0, ARY_DEFAULT_SIZE);
04142 result = ary_new(0, RARRAY_LEN(ary));
04143 memo = st_init_numtable();
04144 st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
04145 *modified = 0;
04146
04147 while (1) {
04148 while (i < RARRAY_LEN(ary)) {
04149 elt = RARRAY_PTR(ary)[i++];
04150 tmp = rb_check_array_type(elt);
04151 if (RBASIC(result)->klass) {
04152 rb_raise(rb_eRuntimeError, "flatten reentered");
04153 }
04154 if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
04155 rb_ary_push(result, elt);
04156 }
04157 else {
04158 *modified = 1;
04159 id = (st_data_t)tmp;
04160 if (st_lookup(memo, id, 0)) {
04161 st_free_table(memo);
04162 rb_raise(rb_eArgError, "tried to flatten recursive array");
04163 }
04164 st_insert(memo, id, (st_data_t)Qtrue);
04165 rb_ary_push(stack, ary);
04166 rb_ary_push(stack, LONG2NUM(i));
04167 ary = tmp;
04168 i = 0;
04169 }
04170 }
04171 if (RARRAY_LEN(stack) == 0) {
04172 break;
04173 }
04174 id = (st_data_t)ary;
04175 st_delete(memo, &id, 0);
04176 tmp = rb_ary_pop(stack);
04177 i = NUM2LONG(tmp);
04178 ary = rb_ary_pop(stack);
04179 }
04180
04181 st_free_table(memo);
04182
04183 RBASIC(result)->klass = rb_class_of(ary);
04184 return result;
04185 }
04186
04187
04188
04189
04190
04191
04192
04193
04194
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204
04205
04206
04207 static VALUE
04208 rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
04209 {
04210 int mod = 0, level = -1;
04211 VALUE result, lv;
04212
04213 rb_scan_args(argc, argv, "01", &lv);
04214 rb_ary_modify_check(ary);
04215 if (!NIL_P(lv)) level = NUM2INT(lv);
04216 if (level == 0) return Qnil;
04217
04218 result = flatten(ary, level, &mod);
04219 if (mod == 0) {
04220 ary_discard(result);
04221 return Qnil;
04222 }
04223 if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
04224 rb_ary_replace(ary, result);
04225 if (mod) ARY_SET_EMBED_LEN(result, 0);
04226
04227 return ary;
04228 }
04229
04230
04231
04232
04233
04234
04235
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252 static VALUE
04253 rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
04254 {
04255 int mod = 0, level = -1;
04256 VALUE result, lv;
04257
04258 rb_scan_args(argc, argv, "01", &lv);
04259 if (!NIL_P(lv)) level = NUM2INT(lv);
04260 if (level == 0) return ary_make_shared_copy(ary);
04261
04262 result = flatten(ary, level, &mod);
04263 OBJ_INFECT(result, ary);
04264
04265 return result;
04266 }
04267
04268 #define OPTHASH_GIVEN_P(opts) \
04269 (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
04270 static VALUE sym_random;
04271
04272 #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284 static VALUE
04285 rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
04286 {
04287 VALUE *ptr, opts, *snap_ptr, randgen = rb_cRandom;
04288 long i, snap_len;
04289
04290 if (OPTHASH_GIVEN_P(opts)) {
04291 randgen = rb_hash_lookup2(opts, sym_random, randgen);
04292 }
04293 rb_check_arity(argc, 0, 0);
04294 rb_ary_modify(ary);
04295 i = RARRAY_LEN(ary);
04296 ptr = RARRAY_PTR(ary);
04297 snap_len = i;
04298 snap_ptr = ptr;
04299 while (i) {
04300 long j = RAND_UPTO(i);
04301 VALUE tmp;
04302 if (snap_len != RARRAY_LEN(ary) || snap_ptr != RARRAY_PTR(ary)) {
04303 rb_raise(rb_eRuntimeError, "modified during shuffle");
04304 }
04305 tmp = ptr[--i];
04306 ptr[i] = ptr[j];
04307 ptr[j] = tmp;
04308 }
04309 return ary;
04310 }
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328 static VALUE
04329 rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
04330 {
04331 ary = rb_ary_dup(ary);
04332 rb_ary_shuffle_bang(argc, argv, ary);
04333 return ary;
04334 }
04335
04336
04337
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356
04357
04358
04359
04360
04361 static VALUE
04362 rb_ary_sample(int argc, VALUE *argv, VALUE ary)
04363 {
04364 VALUE nv, result, *ptr;
04365 VALUE opts, randgen = rb_cRandom;
04366 long n, len, i, j, k, idx[10];
04367 long rnds[numberof(idx)];
04368
04369 if (OPTHASH_GIVEN_P(opts)) {
04370 randgen = rb_hash_lookup2(opts, sym_random, randgen);
04371 }
04372 ptr = RARRAY_PTR(ary);
04373 len = RARRAY_LEN(ary);
04374 if (argc == 0) {
04375 if (len == 0) return Qnil;
04376 if (len == 1) {
04377 i = 0;
04378 }
04379 else {
04380 i = RAND_UPTO(len);
04381 if ((len = RARRAY_LEN(ary)) <= i) return Qnil;
04382 ptr = RARRAY_PTR(ary);
04383 }
04384 return ptr[i];
04385 }
04386 rb_scan_args(argc, argv, "1", &nv);
04387 n = NUM2LONG(nv);
04388 if (n < 0) rb_raise(rb_eArgError, "negative sample number");
04389 if (n > len) n = len;
04390 if (n <= numberof(idx)) {
04391 for (i = 0; i < n; ++i) {
04392 rnds[i] = RAND_UPTO(len - i);
04393 }
04394 }
04395 k = len;
04396 len = RARRAY_LEN(ary);
04397 ptr = RARRAY_PTR(ary);
04398 if (len < k) {
04399 if (n <= numberof(idx)) {
04400 for (i = 0; i < n; ++i) {
04401 if (rnds[i] >= len) {
04402 return rb_ary_new2(0);
04403 }
04404 }
04405 }
04406 }
04407 if (n > len) n = len;
04408 switch (n) {
04409 case 0:
04410 return rb_ary_new2(0);
04411 case 1:
04412 i = rnds[0];
04413 return rb_ary_new4(1, &ptr[i]);
04414 case 2:
04415 i = rnds[0];
04416 j = rnds[1];
04417 if (j >= i) j++;
04418 return rb_ary_new3(2, ptr[i], ptr[j]);
04419 case 3:
04420 i = rnds[0];
04421 j = rnds[1];
04422 k = rnds[2];
04423 {
04424 long l = j, g = i;
04425 if (j >= i) l = i, g = ++j;
04426 if (k >= l && (++k >= g)) ++k;
04427 }
04428 return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
04429 }
04430 if (n <= numberof(idx)) {
04431 VALUE *ptr_result;
04432 long sorted[numberof(idx)];
04433 sorted[0] = idx[0] = rnds[0];
04434 for (i=1; i<n; i++) {
04435 k = rnds[i];
04436 for (j = 0; j < i; ++j) {
04437 if (k < sorted[j]) break;
04438 ++k;
04439 }
04440 memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
04441 sorted[j] = idx[i] = k;
04442 }
04443 result = rb_ary_new2(n);
04444 ptr_result = RARRAY_PTR(result);
04445 for (i=0; i<n; i++) {
04446 ptr_result[i] = ptr[idx[i]];
04447 }
04448 }
04449 else {
04450 VALUE *ptr_result;
04451 result = rb_ary_new4(len, ptr);
04452 RBASIC(result)->klass = 0;
04453 ptr_result = RARRAY_PTR(result);
04454 RB_GC_GUARD(ary);
04455 for (i=0; i<n; i++) {
04456 j = RAND_UPTO(len-i) + i;
04457 nv = ptr_result[j];
04458 ptr_result[j] = ptr_result[i];
04459 ptr_result[i] = nv;
04460 }
04461 RBASIC(result)->klass = rb_cArray;
04462 }
04463 ARY_SET_LEN(result, n);
04464
04465 return result;
04466 }
04467
04468 static VALUE
04469 rb_ary_cycle_size(VALUE self, VALUE args)
04470 {
04471 long mul;
04472 VALUE n = Qnil;
04473 if (args && (RARRAY_LEN(args) > 0)) {
04474 n = RARRAY_PTR(args)[0];
04475 }
04476 if (RARRAY_LEN(self) == 0) return INT2FIX(0);
04477 if (n == Qnil) return DBL2NUM(INFINITY);
04478 mul = NUM2LONG(n);
04479 if (mul <= 0) return INT2FIX(0);
04480 return rb_funcall(rb_ary_length(self), '*', 1, LONG2FIX(mul));
04481 }
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495
04496
04497
04498
04499
04500
04501
04502
04503 static VALUE
04504 rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
04505 {
04506 long n, i;
04507 VALUE nv = Qnil;
04508
04509 rb_scan_args(argc, argv, "01", &nv);
04510
04511 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
04512 if (NIL_P(nv)) {
04513 n = -1;
04514 }
04515 else {
04516 n = NUM2LONG(nv);
04517 if (n <= 0) return Qnil;
04518 }
04519
04520 while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
04521 for (i=0; i<RARRAY_LEN(ary); i++) {
04522 rb_yield(RARRAY_PTR(ary)[i]);
04523 }
04524 }
04525 return Qnil;
04526 }
04527
04528 #define tmpbuf(n, size) rb_str_tmp_new((n)*(size))
04529 #define tmpbuf_discard(s) (rb_str_resize((s), 0L), RBASIC(s)->klass = rb_cString)
04530 #define tmpary(n) rb_ary_tmp_new(n)
04531 #define tmpary_discard(a) (ary_discard(a), RBASIC(a)->klass = rb_cArray)
04532
04533
04534
04535
04536
04537
04538 static int
04539 yield_indexed_values(const VALUE values, const long r, const long *const p)
04540 {
04541 const VALUE result = rb_ary_new2(r);
04542 VALUE *const result_array = RARRAY_PTR(result);
04543 const VALUE *const values_array = RARRAY_PTR(values);
04544 long i;
04545
04546 for (i = 0; i < r; i++) result_array[i] = values_array[p[i]];
04547 ARY_SET_LEN(result, r);
04548 rb_yield(result);
04549 return !RBASIC(values)->klass;
04550 }
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566 static void
04567 permute0(long n, long r, long *p, long index, char *used, VALUE values)
04568 {
04569 long i;
04570 for (i = 0; i < n; i++) {
04571 if (used[i] == 0) {
04572 p[index] = i;
04573 if (index < r-1) {
04574 used[i] = 1;
04575 permute0(n, r, p, index+1,
04576 used, values);
04577 used[i] = 0;
04578 }
04579 else {
04580 if (!yield_indexed_values(values, r, p)) {
04581 rb_raise(rb_eRuntimeError, "permute reentered");
04582 }
04583 }
04584 }
04585 }
04586 }
04587
04588
04589
04590
04591
04592 static VALUE
04593 descending_factorial(long from, long how_many)
04594 {
04595 VALUE cnt = LONG2FIX(how_many >= 0);
04596 while (how_many-- > 0) {
04597 cnt = rb_funcall(cnt, '*', 1, LONG2FIX(from--));
04598 }
04599 return cnt;
04600 }
04601
04602 static VALUE
04603 binomial_coefficient(long comb, long size)
04604 {
04605 if (comb > size-comb) {
04606 comb = size-comb;
04607 }
04608 if (comb < 0) {
04609 return LONG2FIX(0);
04610 }
04611 return rb_funcall(descending_factorial(size, comb), id_div, 1, descending_factorial(comb, comb));
04612 }
04613
04614 static VALUE
04615 rb_ary_permutation_size(VALUE ary, VALUE args)
04616 {
04617 long n = RARRAY_LEN(ary);
04618 long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_PTR(args)[0]) : n;
04619
04620 return descending_factorial(n, k);
04621 }
04622
04623
04624
04625
04626
04627
04628
04629
04630
04631
04632
04633
04634
04635
04636
04637
04638
04639
04640
04641
04642
04643
04644
04645
04646
04647
04648
04649
04650
04651 static VALUE
04652 rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
04653 {
04654 VALUE num;
04655 long r, n, i;
04656
04657 n = RARRAY_LEN(ary);
04658 RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size);
04659 rb_scan_args(argc, argv, "01", &num);
04660 r = NIL_P(num) ? n : NUM2LONG(num);
04661
04662 if (r < 0 || n < r) {
04663
04664 }
04665 else if (r == 0) {
04666 rb_yield(rb_ary_new2(0));
04667 }
04668 else if (r == 1) {
04669 for (i = 0; i < RARRAY_LEN(ary); i++) {
04670 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
04671 }
04672 }
04673 else {
04674 volatile VALUE t0 = tmpbuf(r,sizeof(long));
04675 long *p = (long*)RSTRING_PTR(t0);
04676 volatile VALUE t1 = tmpbuf(n,sizeof(char));
04677 char *used = (char*)RSTRING_PTR(t1);
04678 VALUE ary0 = ary_make_shared_copy(ary);
04679 RBASIC(ary0)->klass = 0;
04680
04681 MEMZERO(used, char, n);
04682
04683 permute0(n, r, p, 0, used, ary0);
04684 tmpbuf_discard(t0);
04685 tmpbuf_discard(t1);
04686 RBASIC(ary0)->klass = rb_cArray;
04687 }
04688 return ary;
04689 }
04690
04691 static VALUE
04692 rb_ary_combination_size(VALUE ary, VALUE args)
04693 {
04694 long n = RARRAY_LEN(ary);
04695 long k = NUM2LONG(RARRAY_PTR(args)[0]);
04696
04697 return binomial_coefficient(k, n);
04698 }
04699
04700
04701
04702
04703
04704
04705
04706
04707
04708
04709
04710
04711
04712
04713
04714
04715
04716
04717
04718
04719
04720
04721
04722
04723
04724
04725 static VALUE
04726 rb_ary_combination(VALUE ary, VALUE num)
04727 {
04728 long n, i, len;
04729
04730 n = NUM2LONG(num);
04731 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
04732 len = RARRAY_LEN(ary);
04733 if (n < 0 || len < n) {
04734
04735 }
04736 else if (n == 0) {
04737 rb_yield(rb_ary_new2(0));
04738 }
04739 else if (n == 1) {
04740 for (i = 0; i < len; i++) {
04741 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
04742 }
04743 }
04744 else {
04745 VALUE ary0 = ary_make_shared_copy(ary);
04746 volatile VALUE t0;
04747 long *stack = ALLOCV_N(long, t0, n+1);
04748 long lev = 0;
04749
04750 RBASIC(ary0)->klass = 0;
04751 MEMZERO(stack+1, long, n);
04752 stack[0] = -1;
04753 for (;;) {
04754 for (lev++; lev < n; lev++) {
04755 stack[lev+1] = stack[lev]+1;
04756 }
04757 if (!yield_indexed_values(ary0, n, stack+1)) {
04758 rb_raise(rb_eRuntimeError, "combination reentered");
04759 }
04760 do {
04761 if (lev == 0) goto done;
04762 stack[lev--]++;
04763 } while (stack[lev+1]+n == len+lev+1);
04764 }
04765 done:
04766 ALLOCV_END(t0);
04767 RBASIC(ary0)->klass = rb_cArray;
04768 }
04769 return ary;
04770 }
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782
04783
04784
04785 static void
04786 rpermute0(long n, long r, long *p, long index, VALUE values)
04787 {
04788 long i;
04789 for (i = 0; i < n; i++) {
04790 p[index] = i;
04791 if (index < r-1) {
04792 rpermute0(n, r, p, index+1, values);
04793 }
04794 else {
04795 if (!yield_indexed_values(values, r, p)) {
04796 rb_raise(rb_eRuntimeError, "repeated permute reentered");
04797 }
04798 }
04799 }
04800 }
04801
04802 static VALUE
04803 rb_ary_repeated_permutation_size(VALUE ary, VALUE args)
04804 {
04805 long n = RARRAY_LEN(ary);
04806 long k = NUM2LONG(RARRAY_PTR(args)[0]);
04807
04808 if (k < 0) {
04809 return LONG2FIX(0);
04810 }
04811
04812 return rb_funcall(LONG2NUM(n), id_power, 1, LONG2NUM(k));
04813 }
04814
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831
04832
04833
04834
04835
04836
04837
04838 static VALUE
04839 rb_ary_repeated_permutation(VALUE ary, VALUE num)
04840 {
04841 long r, n, i;
04842
04843 n = RARRAY_LEN(ary);
04844 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size);
04845 r = NUM2LONG(num);
04846
04847 if (r < 0) {
04848
04849 }
04850 else if (r == 0) {
04851 rb_yield(rb_ary_new2(0));
04852 }
04853 else if (r == 1) {
04854 for (i = 0; i < RARRAY_LEN(ary); i++) {
04855 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
04856 }
04857 }
04858 else {
04859 volatile VALUE t0 = tmpbuf(r, sizeof(long));
04860 long *p = (long*)RSTRING_PTR(t0);
04861 VALUE ary0 = ary_make_shared_copy(ary);
04862 RBASIC(ary0)->klass = 0;
04863
04864 rpermute0(n, r, p, 0, ary0);
04865 tmpbuf_discard(t0);
04866 RBASIC(ary0)->klass = rb_cArray;
04867 }
04868 return ary;
04869 }
04870
04871 static void
04872 rcombinate0(long n, long r, long *p, long index, long rest, VALUE values)
04873 {
04874 if (rest > 0) {
04875 for (; index < n; ++index) {
04876 p[r-rest] = index;
04877 rcombinate0(n, r, p, index, rest-1, values);
04878 }
04879 }
04880 else {
04881 if (!yield_indexed_values(values, r, p)) {
04882 rb_raise(rb_eRuntimeError, "repeated combination reentered");
04883 }
04884 }
04885 }
04886
04887 static VALUE
04888 rb_ary_repeated_combination_size(VALUE ary, VALUE args)
04889 {
04890 long n = RARRAY_LEN(ary);
04891 long k = NUM2LONG(RARRAY_PTR(args)[0]);
04892 if (k == 0) {
04893 return LONG2FIX(1);
04894 }
04895 return binomial_coefficient(k, n + k - 1);
04896 }
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919
04920
04921
04922
04923
04924
04925 static VALUE
04926 rb_ary_repeated_combination(VALUE ary, VALUE num)
04927 {
04928 long n, i, len;
04929
04930 n = NUM2LONG(num);
04931 RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size);
04932 len = RARRAY_LEN(ary);
04933 if (n < 0) {
04934
04935 }
04936 else if (n == 0) {
04937 rb_yield(rb_ary_new2(0));
04938 }
04939 else if (n == 1) {
04940 for (i = 0; i < len; i++) {
04941 rb_yield(rb_ary_new3(1, RARRAY_PTR(ary)[i]));
04942 }
04943 }
04944 else if (len == 0) {
04945
04946 }
04947 else {
04948 volatile VALUE t0 = tmpbuf(n, sizeof(long));
04949 long *p = (long*)RSTRING_PTR(t0);
04950 VALUE ary0 = ary_make_shared_copy(ary);
04951 RBASIC(ary0)->klass = 0;
04952
04953 rcombinate0(len, n, p, 0, n, ary0);
04954 tmpbuf_discard(t0);
04955 RBASIC(ary0)->klass = rb_cArray;
04956 }
04957 return ary;
04958 }
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981 static VALUE
04982 rb_ary_product(int argc, VALUE *argv, VALUE ary)
04983 {
04984 int n = argc+1;
04985 volatile VALUE t0 = tmpary(n);
04986 volatile VALUE t1 = tmpbuf(n, sizeof(int));
04987 VALUE *arrays = RARRAY_PTR(t0);
04988 int *counters = (int*)RSTRING_PTR(t1);
04989 VALUE result = Qnil;
04990 long i,j;
04991 long resultlen = 1;
04992
04993 RBASIC(t0)->klass = 0;
04994 RBASIC(t1)->klass = 0;
04995
04996
04997 ARY_SET_LEN(t0, n);
04998 arrays[0] = ary;
04999 for (i = 1; i < n; i++) arrays[i] = Qnil;
05000 for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
05001
05002
05003 for (i = 0; i < n; i++) counters[i] = 0;
05004
05005
05006 if (rb_block_given_p()) {
05007
05008 for (i = 0; i < n; i++) {
05009 if (RARRAY_LEN(arrays[i]) == 0) goto done;
05010 arrays[i] = ary_make_shared_copy(arrays[i]);
05011 }
05012 }
05013 else {
05014
05015 for (i = 0; i < n; i++) {
05016 long k = RARRAY_LEN(arrays[i]);
05017 if (k == 0) {
05018 result = rb_ary_new2(0);
05019 goto done;
05020 }
05021 if (MUL_OVERFLOW_LONG_P(resultlen, k))
05022 rb_raise(rb_eRangeError, "too big to product");
05023 resultlen *= k;
05024 }
05025 result = rb_ary_new2(resultlen);
05026 }
05027 for (;;) {
05028 int m;
05029
05030 VALUE subarray = rb_ary_new2(n);
05031 for (j = 0; j < n; j++) {
05032 rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
05033 }
05034
05035
05036 if (NIL_P(result)) {
05037 FL_SET(t0, FL_USER5);
05038 rb_yield(subarray);
05039 if (! FL_TEST(t0, FL_USER5)) {
05040 rb_raise(rb_eRuntimeError, "product reentered");
05041 }
05042 else {
05043 FL_UNSET(t0, FL_USER5);
05044 }
05045 }
05046 else {
05047 rb_ary_push(result, subarray);
05048 }
05049
05050
05051
05052
05053
05054 m = n-1;
05055 counters[m]++;
05056 while (counters[m] == RARRAY_LEN(arrays[m])) {
05057 counters[m] = 0;
05058
05059 if (--m < 0) goto done;
05060 counters[m]++;
05061 }
05062 }
05063 done:
05064 tmpary_discard(t0);
05065 tmpbuf_discard(t1);
05066
05067 return NIL_P(result) ? ary : result;
05068 }
05069
05070
05071
05072
05073
05074
05075
05076
05077
05078
05079
05080
05081
05082
05083
05084
05085 static VALUE
05086 rb_ary_take(VALUE obj, VALUE n)
05087 {
05088 long len = NUM2LONG(n);
05089 if (len < 0) {
05090 rb_raise(rb_eArgError, "attempt to take negative size");
05091 }
05092 return rb_ary_subseq(obj, 0, len);
05093 }
05094
05095
05096
05097
05098
05099
05100
05101
05102
05103
05104
05105
05106
05107
05108
05109
05110
05111
05112 static VALUE
05113 rb_ary_take_while(VALUE ary)
05114 {
05115 long i;
05116
05117 RETURN_ENUMERATOR(ary, 0, 0);
05118 for (i = 0; i < RARRAY_LEN(ary); i++) {
05119 if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
05120 }
05121 return rb_ary_take(ary, LONG2FIX(i));
05122 }
05123
05124
05125
05126
05127
05128
05129
05130
05131
05132
05133
05134
05135
05136
05137
05138
05139
05140 static VALUE
05141 rb_ary_drop(VALUE ary, VALUE n)
05142 {
05143 VALUE result;
05144 long pos = NUM2LONG(n);
05145 if (pos < 0) {
05146 rb_raise(rb_eArgError, "attempt to drop negative size");
05147 }
05148
05149 result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
05150 if (result == Qnil) result = rb_ary_new();
05151 return result;
05152 }
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169
05170
05171
05172 static VALUE
05173 rb_ary_drop_while(VALUE ary)
05174 {
05175 long i;
05176
05177 RETURN_ENUMERATOR(ary, 0, 0);
05178 for (i = 0; i < RARRAY_LEN(ary); i++) {
05179 if (!RTEST(rb_yield(RARRAY_PTR(ary)[i]))) break;
05180 }
05181 return rb_ary_drop(ary, LONG2FIX(i));
05182 }
05183
05184
05185
05186
05187
05188
05189
05190
05191
05192
05193
05194
05195
05196
05197
05198
05199
05200
05201
05202
05203
05204
05205
05206
05207
05208
05209
05210
05211
05212
05213
05214
05215
05216
05217
05218
05219
05220
05221
05222
05223
05224
05225
05226
05227
05228
05229
05230
05231
05232
05233
05234
05235
05236
05237
05238
05239
05240
05241
05242
05243
05244
05245
05246
05247
05248
05249
05250
05251
05252
05253
05254
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264
05265
05266
05267
05268
05269
05270
05271
05272
05273
05274
05275
05276
05277
05278
05279
05280
05281
05282
05283
05284
05285
05286
05287
05288
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306
05307
05308
05309
05310
05311
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336
05337
05338
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354
05355
05356
05357
05358
05359
05360
05361
05362
05363
05364
05365
05366
05367
05368
05369
05370
05371
05372
05373
05374
05375
05376
05377
05378
05379
05380
05381
05382
05383
05384
05385
05386
05387
05388
05389
05390
05391
05392
05393
05394
05395
05396
05397
05398
05399
05400
05401
05402
05403
05404
05405
05406
05407
05408
05409
05410
05411
05412
05413
05414
05415
05416
05417
05418 void
05419 Init_Array(void)
05420 {
05421 #undef rb_intern
05422 #define rb_intern(str) rb_intern_const(str)
05423
05424 rb_cArray = rb_define_class("Array", rb_cObject);
05425 rb_include_module(rb_cArray, rb_mEnumerable);
05426
05427 rb_define_alloc_func(rb_cArray, empty_ary_alloc);
05428 rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
05429 rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
05430 rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
05431 rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
05432
05433 rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
05434 rb_define_alias(rb_cArray, "to_s", "inspect");
05435 rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
05436 rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
05437 rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0);
05438
05439 rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
05440 rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
05441 rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
05442
05443 rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
05444 rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
05445 rb_define_method(rb_cArray, "at", rb_ary_at, 1);
05446 rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
05447 rb_define_method(rb_cArray, "first", rb_ary_first, -1);
05448 rb_define_method(rb_cArray, "last", rb_ary_last, -1);
05449 rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
05450 rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
05451 rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
05452 rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
05453 rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
05454 rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
05455 rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
05456 rb_define_method(rb_cArray, "each", rb_ary_each, 0);
05457 rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
05458 rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
05459 rb_define_method(rb_cArray, "length", rb_ary_length, 0);
05460 rb_define_alias(rb_cArray, "size", "length");
05461 rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
05462 rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
05463 rb_define_method(rb_cArray, "index", rb_ary_index, -1);
05464 rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
05465 rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
05466 rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
05467 rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
05468 rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
05469 rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
05470 rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
05471 rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
05472 rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
05473 rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
05474 rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
05475 rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
05476 rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
05477 rb_define_method(rb_cArray, "select", rb_ary_select, 0);
05478 rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
05479 rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
05480 rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
05481 rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
05482 rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
05483 rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
05484 rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
05485 rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
05486 rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
05487 rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
05488 rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
05489 rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
05490 rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
05491 rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
05492 rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
05493
05494 rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
05495 rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
05496
05497 rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
05498 rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
05499
05500 rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
05501 rb_define_method(rb_cArray, "*", rb_ary_times, 1);
05502
05503 rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
05504 rb_define_method(rb_cArray, "&", rb_ary_and, 1);
05505 rb_define_method(rb_cArray, "|", rb_ary_or, 1);
05506
05507 rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
05508 rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
05509 rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
05510 rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
05511 rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
05512 rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
05513 rb_define_method(rb_cArray, "count", rb_ary_count, -1);
05514 rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1);
05515 rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1);
05516 rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
05517 rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
05518 rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
05519 rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
05520 rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
05521 rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
05522 rb_define_method(rb_cArray, "product", rb_ary_product, -1);
05523
05524 rb_define_method(rb_cArray, "take", rb_ary_take, 1);
05525 rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
05526 rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
05527 rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
05528 rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
05529
05530 id_cmp = rb_intern("<=>");
05531 sym_random = ID2SYM(rb_intern("random"));
05532 id_div = rb_intern("div");
05533 id_power = rb_intern("**");
05534 }
05535