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