LCOV - code coverage report
Current view: top level - ruby - array.c (source / functions) Hit Total Coverage
Test: lcov-all-filtered.info Lines: 2135 2164 98.7 %
Date: 2018-09-21 23:31:11 Functions: 199 200 99.5 %
Branches: 2172 2847 76.3 %

           Branch data     Line data    Source code
       1                 :            : /**********************************************************************
       2                 :            : 
       3                 :            :   array.c -
       4                 :            : 
       5                 :            :   $Author: kazu $
       6                 :            :   created at: Fri Aug  6 09:46:12 JST 1993
       7                 :            : 
       8                 :            :   Copyright (C) 1993-2007 Yukihiro Matsumoto
       9                 :            :   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
      10                 :            :   Copyright (C) 2000  Information-technology Promotion Agency, Japan
      11                 :            : 
      12                 :            : **********************************************************************/
      13                 :            : 
      14                 :            : #include "ruby/encoding.h"
      15                 :            : #include "ruby/util.h"
      16                 :            : #include "ruby/st.h"
      17                 :            : #include "internal.h"
      18                 :            : #include "probes.h"
      19                 :            : #include "id.h"
      20                 :            : #include "debug_counter.h"
      21                 :            : 
      22                 :            : #ifndef ARRAY_DEBUG
      23                 :            : # define NDEBUG
      24                 :            : #endif
      25                 :            : #include "ruby_assert.h"
      26                 :            : 
      27                 :            : VALUE rb_cArray;
      28                 :            : 
      29                 :            : /* for OPTIMIZED_CMP: */
      30                 :            : #define id_cmp idCmp
      31                 :            : 
      32                 :            : #define ARY_DEFAULT_SIZE 16
      33                 :            : #define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
      34                 :            : #define SMALL_ARRAY_LEN 16
      35                 :            : 
      36                 :            : # define ARY_SHARED_P(ary) \
      37                 :            :     (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
      38                 :            :      FL_TEST((ary),ELTS_SHARED)!=0)
      39                 :            : # define ARY_EMBED_P(ary) \
      40                 :            :     (assert(!FL_TEST((ary), ELTS_SHARED) || !FL_TEST((ary), RARRAY_EMBED_FLAG)), \
      41                 :            :      FL_TEST((ary), RARRAY_EMBED_FLAG)!=0)
      42                 :            : 
      43                 :            : #define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
      44                 :            : #define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
      45                 :            : #define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
      46                 :            : #define ARY_EMBED_LEN(a) \
      47                 :            :     (assert(ARY_EMBED_P(a)), \
      48                 :            :      (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
      49                 :            :          (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
      50                 :            : #define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), RARRAY(a)->as.heap.aux.capa * sizeof(VALUE))
      51                 :            : 
      52                 :            : #define ARY_OWNS_HEAP_P(a) (!FL_TEST((a), ELTS_SHARED|RARRAY_EMBED_FLAG))
      53                 :            : #define FL_SET_EMBED(a) do { \
      54                 :            :     assert(!ARY_SHARED_P(a)); \
      55                 :            :     FL_SET((a), RARRAY_EMBED_FLAG); \
      56                 :            : } while (0)
      57                 :            : #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
      58                 :            : #define FL_SET_SHARED(ary) do { \
      59                 :            :     assert(!ARY_EMBED_P(ary)); \
      60                 :            :     FL_SET((ary), ELTS_SHARED); \
      61                 :            : } while (0)
      62                 :            : #define FL_UNSET_SHARED(ary) FL_UNSET((ary), ELTS_SHARED)
      63                 :            : 
      64                 :            : #define ARY_SET_PTR(ary, p) do { \
      65                 :            :     assert(!ARY_EMBED_P(ary)); \
      66                 :            :     assert(!OBJ_FROZEN(ary)); \
      67                 :            :     RARRAY(ary)->as.heap.ptr = (p); \
      68                 :            : } while (0)
      69                 :            : #define ARY_SET_EMBED_LEN(ary, n) do { \
      70                 :            :     long tmp_n = (n); \
      71                 :            :     assert(ARY_EMBED_P(ary)); \
      72                 :            :     assert(!OBJ_FROZEN(ary)); \
      73                 :            :     RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
      74                 :            :     RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
      75                 :            : } while (0)
      76                 :            : #define ARY_SET_HEAP_LEN(ary, n) do { \
      77                 :            :     assert(!ARY_EMBED_P(ary)); \
      78                 :            :     RARRAY(ary)->as.heap.len = (n); \
      79                 :            : } while (0)
      80                 :            : #define ARY_SET_LEN(ary, n) do { \
      81                 :            :     if (ARY_EMBED_P(ary)) { \
      82                 :            :         ARY_SET_EMBED_LEN((ary), (n)); \
      83                 :            :     } \
      84                 :            :     else { \
      85                 :            :         ARY_SET_HEAP_LEN((ary), (n)); \
      86                 :            :     } \
      87                 :            :     assert(RARRAY_LEN(ary) == (n)); \
      88                 :            : } while (0)
      89                 :            : #define ARY_INCREASE_PTR(ary, n) do  { \
      90                 :            :     assert(!ARY_EMBED_P(ary)); \
      91                 :            :     assert(!OBJ_FROZEN(ary)); \
      92                 :            :     RARRAY(ary)->as.heap.ptr += (n); \
      93                 :            : } while (0)
      94                 :            : #define ARY_INCREASE_LEN(ary, n) do  { \
      95                 :            :     assert(!OBJ_FROZEN(ary)); \
      96                 :            :     if (ARY_EMBED_P(ary)) { \
      97                 :            :         ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \
      98                 :            :     } \
      99                 :            :     else { \
     100                 :            :         RARRAY(ary)->as.heap.len += (n); \
     101                 :            :     } \
     102                 :            : } while (0)
     103                 :            : 
     104                 :            : #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
     105                 :            :                        ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : RARRAY(ary)->as.heap.aux.capa)
     106                 :            : #define ARY_SET_CAPA(ary, n) do { \
     107                 :            :     assert(!ARY_EMBED_P(ary)); \
     108                 :            :     assert(!ARY_SHARED_P(ary)); \
     109                 :            :     assert(!OBJ_FROZEN(ary)); \
     110                 :            :     RARRAY(ary)->as.heap.aux.capa = (n); \
     111                 :            : } while (0)
     112                 :            : 
     113                 :            : #define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
     114                 :            : #define ARY_SET_SHARED(ary, value) do { \
     115                 :            :     const VALUE _ary_ = (ary); \
     116                 :            :     const VALUE _value_ = (value); \
     117                 :            :     assert(!ARY_EMBED_P(_ary_)); \
     118                 :            :     assert(ARY_SHARED_P(_ary_)); \
     119                 :            :     assert(ARY_SHARED_ROOT_P(_value_)); \
     120                 :            :     RB_OBJ_WRITE(_ary_, &RARRAY(_ary_)->as.heap.aux.shared, _value_); \
     121                 :            : } while (0)
     122                 :            : #define RARRAY_SHARED_ROOT_FLAG FL_USER5
     123                 :            : #define ARY_SHARED_ROOT_P(ary) (FL_TEST((ary), RARRAY_SHARED_ROOT_FLAG))
     124                 :            : #define ARY_SHARED_NUM(ary) \
     125                 :            :     (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
     126                 :            : #define ARY_SHARED_OCCUPIED(ary) (ARY_SHARED_NUM(ary) == 1)
     127                 :            : #define ARY_SET_SHARED_NUM(ary, value) do { \
     128                 :            :     assert(ARY_SHARED_ROOT_P(ary)); \
     129                 :            :     RARRAY(ary)->as.heap.aux.capa = (value); \
     130                 :            : } while (0)
     131                 :            : #define FL_SET_SHARED_ROOT(ary) do { \
     132                 :            :     assert(!ARY_EMBED_P(ary)); \
     133                 :            :     FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \
     134                 :            : } while (0)
     135                 :            : 
     136                 :            : #define ARY_SET(a, i, v) RARRAY_ASET((assert(!ARY_SHARED_P(a)), (a)), (i), (v))
     137                 :            : 
     138                 :            : void
     139                 :    5268434 : rb_mem_clear(register VALUE *mem, register long size)
     140                 :            : {
     141 [ +  + ][ +  + ]:   32345400 :     while (size--) {
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
     142                 :   23395894 :         *mem++ = Qnil;
     143                 :            :     }
     144                 :    5268434 : }
     145                 :            : 
     146                 :            : static void
     147                 :            : ary_mem_clear(VALUE ary, long beg, long size)
     148                 :            : {
     149                 :    3681072 :     RARRAY_PTR_USE(ary, ptr, {
     150                 :            :         rb_mem_clear(ptr + beg, size);
     151                 :            :     });
     152                 :            : }
     153                 :            : 
     154                 :            : static inline void
     155                 :            : memfill(register VALUE *mem, register long size, register VALUE val)
     156                 :            : {
     157         [ +  + ]:    5825362 :     while (size--) {
     158                 :    5213064 :         *mem++ = val;
     159                 :            :     }
     160                 :            : }
     161                 :            : 
     162                 :            : static void
     163                 :     612298 : ary_memfill(VALUE ary, long beg, long size, VALUE val)
     164                 :            : {
     165                 :    1224596 :     RARRAY_PTR_USE(ary, ptr, {
     166                 :            :         memfill(ptr + beg, size, val);
     167                 :            :         RB_OBJ_WRITTEN(ary, Qundef, val);
     168                 :            :     });
     169                 :     612298 : }
     170                 :            : 
     171                 :            : static void
     172                 :   58364347 : ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary)
     173                 :            : {
     174                 :            : #if 1
     175                 :            :     assert(!ARY_SHARED_P(buff_owner_ary));
     176                 :            : 
     177         [ +  + ]:   58364347 :     if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) {
     178                 :     402701 :         rb_gc_writebarrier_remember(buff_owner_ary);
     179                 :     805402 :         RARRAY_PTR_USE(ary, ptr, {
     180                 :            :             MEMCPY(ptr+beg, argv, VALUE, argc);
     181                 :            :         });
     182                 :            :     }
     183                 :            :     else {
     184                 :            :         int i;
     185         [ +  + ]:  172051989 :         RARRAY_PTR_USE(ary, ptr, {
     186                 :            :             for (i=0; i<argc; i++) {
     187                 :            :                 RB_OBJ_WRITE(buff_owner_ary, &ptr[i+beg], argv[i]);
     188                 :            :             }
     189                 :            :         });
     190                 :            :     }
     191                 :            : #else
     192                 :            :     /* giveup write barrier (traditional way) */
     193                 :            :     RARRAY_PTR(buff_owner_ary);
     194                 :            :     MEMCPY(RARRAY_PTR(ary)+beg, argv, VALUE, argc);
     195                 :            : #endif
     196                 :   58364347 : }
     197                 :            : 
     198                 :            : static void
     199                 :            : ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv)
     200                 :            : {
     201                 :   45706865 :     ary_memcpy0(ary, beg, argc, argv, ary);
     202                 :            : }
     203                 :            : 
     204                 :            : static void
     205                 :    4943977 : ary_resize_capa(VALUE ary, long capacity)
     206                 :            : {
     207                 :            :     assert(RARRAY_LEN(ary) <= capacity);
     208                 :            :     assert(!OBJ_FROZEN(ary));
     209                 :            :     assert(!ARY_SHARED_P(ary));
     210         [ +  + ]:    4943977 :     if (capacity > RARRAY_EMBED_LEN_MAX) {
     211 [ +  - ][ +  - ]:    4886384 :         if (ARY_EMBED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
     212                 :    3351165 :             long len = ARY_EMBED_LEN(ary);
     213                 :    3351165 :             VALUE *ptr = ALLOC_N(VALUE, (capacity));
     214                 :    3351165 :             MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
     215 [ +  - ][ +  - ]:    3351165 :             FL_UNSET_EMBED(ary);
                 [ +  - ]
     216                 :    3351165 :             ARY_SET_PTR(ary, ptr);
     217                 :    3351165 :             ARY_SET_HEAP_LEN(ary, len);
     218                 :            :         }
     219                 :            :         else {
     220                 :    1535219 :             SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, capacity, RARRAY(ary)->as.heap.aux.capa);
     221                 :            :         }
     222                 :    4886384 :         ARY_SET_CAPA(ary, (capacity));
     223                 :            :     }
     224                 :            :     else {
     225 [ +  - ][ +  - ]:      57593 :         if (!ARY_EMBED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
     226                 :        662 :             long len = RARRAY_LEN(ary);
     227                 :        662 :             const VALUE *ptr = RARRAY_CONST_PTR(ary);
     228                 :            : 
     229         [ -  + ]:        662 :             if (len > capacity) len = capacity;
     230                 :        662 :             MEMCPY((VALUE *)RARRAY(ary)->as.ary, ptr, VALUE, len);
     231 [ +  - ][ +  - ]:        662 :             FL_SET_EMBED(ary);
                 [ +  - ]
     232 [ +  - ][ +  - ]:        662 :             ARY_SET_LEN(ary, len);
         [ +  - ][ -  + ]
                 [ +  - ]
     233                 :        662 :             ruby_sized_xfree((VALUE *)ptr, RARRAY(ary)->as.heap.aux.capa);
     234                 :            :         }
     235                 :            :     }
     236                 :    4943977 : }
     237                 :            : 
     238                 :            : static inline void
     239                 :       1314 : ary_shrink_capa(VALUE ary)
     240                 :            : {
     241                 :       1314 :     long capacity = ARY_HEAP_LEN(ary);
     242                 :       1314 :     long old_capa = RARRAY(ary)->as.heap.aux.capa;
     243                 :            :     assert(!ARY_SHARED_P(ary));
     244                 :            :     assert(old_capa >= capacity);
     245         [ +  + ]:       1314 :     if (old_capa > capacity)
     246                 :        147 :         SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, capacity, old_capa);
     247                 :       1314 : }
     248                 :            : 
     249                 :            : static void
     250                 :    4764247 : ary_double_capa(VALUE ary, long min)
     251                 :            : {
     252 [ +  - ][ +  - ]:    4764247 :     long new_capa = ARY_CAPA(ary) / 2;
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
     253                 :            : 
     254         [ +  + ]:    4764247 :     if (new_capa < ARY_DEFAULT_SIZE) {
     255                 :    3964274 :         new_capa = ARY_DEFAULT_SIZE;
     256                 :            :     }
     257         [ -  + ]:    4764247 :     if (new_capa >= ARY_MAX_SIZE - min) {
     258                 :          0 :         new_capa = (ARY_MAX_SIZE - min) / 2;
     259                 :            :     }
     260                 :    4764247 :     new_capa += min;
     261                 :    4764247 :     ary_resize_capa(ary, new_capa);
     262                 :    4764247 : }
     263                 :            : 
     264                 :            : static void
     265                 :     299406 : rb_ary_decrement_share(VALUE shared)
     266                 :            : {
     267         [ +  - ]:     299406 :     if (shared) {
     268                 :     299406 :         long num = ARY_SHARED_NUM(shared) - 1;
     269         [ +  + ]:     299406 :         if (num == 0) {
     270                 :      64878 :             rb_ary_free(shared);
     271                 :      64878 :             rb_gc_force_recycle(shared);
     272                 :            :         }
     273         [ +  - ]:     234528 :         else if (num > 0) {
     274                 :     234528 :             ARY_SET_SHARED_NUM(shared, num);
     275                 :            :         }
     276                 :            :     }
     277                 :     299406 : }
     278                 :            : 
     279                 :            : static void
     280                 :     297019 : rb_ary_unshare(VALUE ary)
     281                 :            : {
     282                 :     297019 :     VALUE shared = RARRAY(ary)->as.heap.aux.shared;
     283                 :     297019 :     rb_ary_decrement_share(shared);
     284 [ +  - ][ +  - ]:     297019 :     FL_UNSET_SHARED(ary);
                 [ +  - ]
     285                 :     297019 : }
     286                 :            : 
     287                 :            : static inline void
     288                 :     196443 : rb_ary_unshare_safe(VALUE ary)
     289                 :            : {
     290 [ +  - ][ +  - ]:     196443 :     if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     291                 :     112262 :         rb_ary_unshare(ary);
     292                 :            :     }
     293                 :     196443 : }
     294                 :            : 
     295                 :            : static VALUE
     296                 :            : rb_ary_increment_share(VALUE shared)
     297                 :            : {
     298                 :     492014 :     long num = ARY_SHARED_NUM(shared);
     299 [ +  - ][ +  - ]:     492014 :     if (num >= 0) {
     300                 :     492014 :         ARY_SET_SHARED_NUM(shared, num + 1);
     301                 :            :     }
     302                 :            :     return shared;
     303                 :            : }
     304                 :            : 
     305                 :            : static void
     306                 :     377093 : rb_ary_set_shared(VALUE ary, VALUE shared)
     307                 :            : {
     308                 :            :     rb_ary_increment_share(shared);
     309 [ +  - ][ +  - ]:     377093 :     FL_SET_SHARED(ary);
                 [ +  - ]
     310                 :     377093 :     ARY_SET_SHARED(ary, shared);
     311                 :     377093 : }
     312                 :            : 
     313                 :            : static inline void
     314                 :  188968261 : rb_ary_modify_check(VALUE ary)
     315                 :            : {
     316 [ +  - ][ +  - ]:  188968261 :     rb_check_frozen(ary);
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
     317                 :  188968167 : }
     318                 :            : 
     319                 :            : void
     320                 :   36310370 : rb_ary_modify(VALUE ary)
     321                 :            : {
     322                 :   36310370 :     rb_ary_modify_check(ary);
     323 [ +  - ][ +  - ]:   36310327 :     if (ARY_SHARED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
     324                 :     184409 :         long shared_len, len = RARRAY_LEN(ary);
     325                 :     184409 :         VALUE shared = ARY_SHARED(ary);
     326         [ +  + ]:     184409 :         if (len <= RARRAY_EMBED_LEN_MAX) {
     327                 :        171 :             const VALUE *ptr = ARY_HEAP_PTR(ary);
     328 [ +  - ][ +  - ]:        171 :             FL_UNSET_SHARED(ary);
                 [ +  - ]
     329 [ +  - ][ +  - ]:        171 :             FL_SET_EMBED(ary);
                 [ +  - ]
     330                 :        171 :             MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
     331                 :        171 :             rb_ary_decrement_share(shared);
     332                 :        171 :             ARY_SET_EMBED_LEN(ary, len);
     333                 :            :         }
     334 [ +  + ][ +  + ]:     188748 :         else if (ARY_SHARED_OCCUPIED(shared) && len > ((shared_len = RARRAY_LEN(shared))>>1)) {
     335                 :       4350 :             long shift = RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared);
     336 [ +  - ][ +  - ]:       2175 :             FL_UNSET_SHARED(ary);
                 [ +  - ]
     337                 :       4350 :             ARY_SET_PTR(ary, RARRAY_CONST_PTR(shared));
     338                 :       2175 :             ARY_SET_CAPA(ary, shared_len);
     339                 :       4350 :             RARRAY_PTR_USE(ary, ptr, {
     340                 :            :                 MEMMOVE(ptr, ptr+shift, VALUE, len);
     341                 :            :             });
     342 [ +  - ][ +  - ]:       2175 :             FL_SET_EMBED(shared);
                 [ +  - ]
     343                 :       2175 :             rb_ary_decrement_share(shared);
     344                 :            :         }
     345                 :            :         else {
     346                 :     182063 :             VALUE *ptr = ALLOC_N(VALUE, len);
     347                 :     364126 :             MEMCPY(ptr, RARRAY_CONST_PTR(ary), VALUE, len);
     348                 :     182063 :             rb_ary_unshare(ary);
     349                 :     182063 :             ARY_SET_CAPA(ary, len);
     350                 :     182063 :             ARY_SET_PTR(ary, ptr);
     351                 :            :         }
     352                 :            : 
     353                 :     184409 :         rb_gc_writebarrier_remember(ary);
     354                 :            :     }
     355                 :   36310327 : }
     356                 :            : 
     357                 :            : static VALUE
     358                 :  138229170 : ary_ensure_room_for_push(VALUE ary, long add_len)
     359                 :            : {
     360                 :  138229170 :     long old_len = RARRAY_LEN(ary);
     361                 :  138229170 :     long new_len = old_len + add_len;
     362                 :            :     long capa;
     363                 :            : 
     364         [ -  + ]:  138229170 :     if (old_len > ARY_MAX_SIZE - add_len) {
     365                 :          0 :         rb_raise(rb_eIndexError, "index %ld too big", new_len);
     366                 :            :     }
     367 [ +  - ][ +  - ]:  138229170 :     if (ARY_SHARED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
     368         [ +  + ]:      63118 :         if (new_len > RARRAY_EMBED_LEN_MAX) {
     369                 :      62980 :             VALUE shared = ARY_SHARED(ary);
     370         [ +  + ]:      62980 :             if (ARY_SHARED_OCCUPIED(shared)) {
     371         [ +  + ]:        846 :                 if (RARRAY_CONST_PTR(ary) - RARRAY_CONST_PTR(shared) + new_len <= RARRAY_LEN(shared)) {
     372                 :        736 :                     rb_ary_modify_check(ary);
     373                 :        736 :                     return shared;
     374                 :            :                 }
     375                 :            :                 else {
     376                 :            :                     /* if array is shared, then it is likely it participate in push/shift pattern */
     377                 :        110 :                     rb_ary_modify(ary);
     378 [ +  - ][ +  - ]:        110 :                     capa = ARY_CAPA(ary);
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
     379         [ +  + ]:        110 :                     if (new_len > capa - (capa >> 6)) {
     380                 :          1 :                         ary_double_capa(ary, new_len);
     381                 :            :                     }
     382                 :        110 :                     return ary;
     383                 :            :                 }
     384                 :            :             }
     385                 :            :         }
     386                 :      62272 :         rb_ary_modify(ary);
     387                 :            :     }
     388                 :            :     else {
     389                 :  138166052 :         rb_ary_modify_check(ary);
     390                 :            :     }
     391 [ +  - ][ +  - ]:  138228314 :     capa = ARY_CAPA(ary);
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
     392         [ +  + ]:  138228314 :     if (new_len > capa) {
     393                 :    4596127 :         ary_double_capa(ary, new_len);
     394                 :            :     }
     395                 :            : 
     396                 :  138228314 :     return ary;
     397                 :            : }
     398                 :            : 
     399                 :            : /*
     400                 :            :  *  call-seq:
     401                 :            :  *      ary.freeze -> ary
     402                 :            :  *
     403                 :            :  *  Calls Object#freeze on +ary+ to prevent any further
     404                 :            :  *  modification. A RuntimeError will be raised if a modification
     405                 :            :  *  attempt is made.
     406                 :            :  *
     407                 :            :  */
     408                 :            : 
     409                 :            : VALUE
     410                 :     233245 : rb_ary_freeze(VALUE ary)
     411                 :            : {
     412                 :     233245 :     return rb_obj_freeze(ary);
     413                 :            : }
     414                 :            : 
     415                 :            : /* This can be used to take a snapshot of an array (with
     416                 :            :    e.g. rb_ary_replace) and check later whether the array has been
     417                 :            :    modified from the snapshot.  The snapshot is cheap, though if
     418                 :            :    something does modify the array it will pay the cost of copying
     419                 :            :    it.  If Array#pop or Array#shift has been called, the array will
     420                 :            :    be still shared with the snapshot, but the array length will
     421                 :            :    differ. */
     422                 :            : VALUE
     423                 :     389555 : rb_ary_shared_with_p(VALUE ary1, VALUE ary2)
     424                 :            : {
     425 [ +  - ][ +  - ]:     774886 :     if (!ARY_EMBED_P(ary1) && ARY_SHARED_P(ary1) &&
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
                 [ +  + ]
     426 [ +  - ][ +  - ]:     770645 :         !ARY_EMBED_P(ary2) && ARY_SHARED_P(ary2) &&
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
     427         [ +  + ]:     381751 :         RARRAY(ary1)->as.heap.aux.shared == RARRAY(ary2)->as.heap.aux.shared &&
     428                 :     381751 :         RARRAY(ary1)->as.heap.len == RARRAY(ary2)->as.heap.len) {
     429                 :            :         return Qtrue;
     430                 :            :     }
     431                 :       8852 :     return Qfalse;
     432                 :            : }
     433                 :            : 
     434                 :            : static VALUE
     435                 :            : ary_alloc(VALUE klass)
     436                 :            : {
     437                 :   75229962 :     NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
     438                 :            :     /* Created array is:
     439                 :            :      *   FL_SET_EMBED((VALUE)ary);
     440                 :            :      *   ARY_SET_EMBED_LEN((VALUE)ary, 0);
     441                 :            :      */
     442                 :            :     return (VALUE)ary;
     443                 :            : }
     444                 :            : 
     445                 :            : static VALUE
     446                 :     565246 : empty_ary_alloc(VALUE klass)
     447                 :            : {
     448                 :            :     RUBY_DTRACE_CREATE_HOOK(ARRAY, 0);
     449                 :     565246 :     return ary_alloc(klass);
     450                 :            : }
     451                 :            : 
     452                 :            : static VALUE
     453                 :   73858927 : ary_new(VALUE klass, long capa)
     454                 :            : {
     455                 :            :     VALUE ary,*ptr;
     456                 :            : 
     457         [ +  + ]:   73858927 :     if (capa < 0) {
     458                 :          3 :         rb_raise(rb_eArgError, "negative array size (or size too big)");
     459                 :            :     }
     460         [ +  + ]:   73858924 :     if (capa > ARY_MAX_SIZE) {
     461                 :          1 :         rb_raise(rb_eArgError, "array size too big");
     462                 :            :     }
     463                 :            : 
     464                 :            :     RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
     465                 :            : 
     466                 :   73858923 :     ary = ary_alloc(klass);
     467         [ +  + ]:   73858923 :     if (capa > RARRAY_EMBED_LEN_MAX) {
     468                 :   14186562 :         ptr = ALLOC_N(VALUE, capa);
     469 [ +  - ][ +  - ]:   14186562 :         FL_UNSET_EMBED(ary);
                 [ +  - ]
     470                 :   14186562 :         ARY_SET_PTR(ary, ptr);
     471                 :   14186562 :         ARY_SET_CAPA(ary, capa);
     472                 :   14186562 :         ARY_SET_HEAP_LEN(ary, 0);
     473                 :            :     }
     474                 :            : 
     475                 :   73858923 :     return ary;
     476                 :            : }
     477                 :            : 
     478                 :            : VALUE
     479                 :    4314977 : rb_ary_new_capa(long capa)
     480                 :            : {
     481                 :   18823296 :     return ary_new(rb_cArray, capa);
     482                 :            : }
     483                 :            : 
     484                 :            : VALUE
     485                 :    5138424 : rb_ary_new(void)
     486                 :            : {
     487                 :    5138424 :     return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
     488                 :            : }
     489                 :            : 
     490                 :            : VALUE
     491                 :       1074 : (rb_ary_new_from_args)(long n, ...)
     492                 :            : {
     493                 :            :     va_list ar;
     494                 :            :     VALUE ary;
     495                 :            :     long i;
     496                 :            : 
     497                 :       1074 :     ary = rb_ary_new2(n);
     498                 :            : 
     499                 :       1074 :     va_start(ar, n);
     500         [ +  + ]:       3734 :     for (i=0; i<n; i++) {
     501         [ +  + ]:       2660 :         ARY_SET(ary, i, va_arg(ar, VALUE));
     502                 :            :     }
     503                 :       1074 :     va_end(ar);
     504                 :            : 
     505 [ +  - ][ +  - ]:       1074 :     ARY_SET_LEN(ary, n);
         [ +  - ][ +  + ]
                 [ +  + ]
     506                 :       1074 :     return ary;
     507                 :            : }
     508                 :            : 
     509                 :            : MJIT_FUNC_EXPORTED VALUE
     510                 :   41635430 : rb_ary_tmp_new_from_values(VALUE klass, long n, const VALUE *elts)
     511                 :            : {
     512                 :            :     VALUE ary;
     513                 :            : 
     514                 :   41635430 :     ary = ary_new(klass, n);
     515         [ +  + ]:   41635430 :     if (n > 0 && elts) {
     516                 :            :         ary_memcpy(ary, 0, n, elts);
     517 [ +  - ][ +  - ]:   35574867 :         ARY_SET_LEN(ary, n);
         [ +  - ][ +  + ]
                 [ +  + ]
     518                 :            :     }
     519                 :            : 
     520                 :   41635430 :     return ary;
     521                 :            : }
     522                 :            : 
     523                 :            : VALUE
     524                 :   38849552 : rb_ary_new_from_values(long n, const VALUE *elts)
     525                 :            : {
     526                 :   41201179 :     return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
     527                 :            : }
     528                 :            : 
     529                 :            : VALUE
     530                 :    6139636 : rb_ary_tmp_new(long capa)
     531                 :            : {
     532                 :    6140882 :     return ary_new(0, capa);
     533                 :            : }
     534                 :            : 
     535                 :            : VALUE
     536                 :       7672 : rb_ary_tmp_new_fill(long capa)
     537                 :            : {
     538                 :       7672 :     VALUE ary = ary_new(0, capa);
     539                 :       7672 :     ary_memfill(ary, 0, capa, Qnil);
     540 [ +  - ][ +  - ]:       7672 :     ARY_SET_LEN(ary, capa);
         [ +  - ][ +  + ]
                 [ +  + ]
     541                 :       7672 :     return ary;
     542                 :            : }
     543                 :            : 
     544                 :            : void
     545                 :   68484500 : rb_ary_free(VALUE ary)
     546                 :            : {
     547 [ +  - ][ +  - ]:   68484500 :     if (ARY_OWNS_HEAP_P(ary)) {
         [ +  - ][ +  + ]
     548                 :            :         RB_DEBUG_COUNTER_INC(obj_ary_ptr);
     549                 :   13384652 :         ruby_sized_xfree((void *)ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
     550                 :            :     }
     551                 :            :     else {
     552                 :            :         RB_DEBUG_COUNTER_INC(obj_ary_embed);
     553                 :            :     }
     554                 :   68484500 : }
     555                 :            : 
     556                 :            : RUBY_FUNC_EXPORTED size_t
     557                 :     443921 : rb_ary_memsize(VALUE ary)
     558                 :            : {
     559 [ +  - ][ +  - ]:     443921 :     if (ARY_OWNS_HEAP_P(ary)) {
         [ +  - ][ +  + ]
     560 [ +  - ][ +  - ]:      98925 :         return ARY_CAPA(ary) * sizeof(VALUE);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  + ]
     561                 :            :     }
     562                 :            :     else {
     563                 :            :         return 0;
     564                 :            :     }
     565                 :            : }
     566                 :            : 
     567                 :            : static inline void
     568                 :            : ary_discard(VALUE ary)
     569                 :            : {
     570                 :      17572 :     rb_ary_free(ary);
     571                 :      17572 :     RBASIC(ary)->flags |= RARRAY_EMBED_FLAG;
     572                 :      17572 :     RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK;
     573                 :            : }
     574                 :            : 
     575                 :            : static VALUE
     576                 :     503641 : ary_make_shared(VALUE ary)
     577                 :            : {
     578                 :            :     assert(!ARY_EMBED_P(ary));
     579 [ +  - ][ +  - ]:     503641 :     if (ARY_SHARED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
     580                 :     258351 :         return ARY_SHARED(ary);
     581                 :            :     }
     582 [ +  - ][ +  - ]:     245290 :     else if (ARY_SHARED_ROOT_P(ary)) {
         [ +  - ][ +  + ]
     583                 :            :         return ary;
     584                 :            :     }
     585 [ +  - ][ +  - ]:     245270 :     else if (OBJ_FROZEN(ary)) {
         [ +  - ][ +  + ]
     586                 :       1314 :         ary_shrink_capa(ary);
     587 [ +  - ][ +  - ]:       1314 :         FL_SET_SHARED_ROOT(ary);
                 [ +  - ]
     588                 :       1314 :         ARY_SET_SHARED_NUM(ary, 1);
     589                 :       1314 :         return ary;
     590                 :            :     }
     591                 :            :     else {
     592 [ +  - ][ +  - ]:     243956 :         long capa = ARY_CAPA(ary), len = RARRAY_LEN(ary);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
     593                 :     243956 :         NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
     594 [ +  - ][ +  - ]:     243956 :         FL_UNSET_EMBED(shared);
                 [ +  - ]
     595                 :            : 
     596 [ +  - ][ +  - ]:     243956 :         ARY_SET_LEN((VALUE)shared, capa);
         [ +  - ][ +  - ]
                 [ -  + ]
     597                 :     243956 :         ARY_SET_PTR((VALUE)shared, RARRAY_CONST_PTR(ary));
     598                 :     243956 :         ary_mem_clear((VALUE)shared, len, capa - len);
     599 [ +  - ][ +  - ]:     243956 :         FL_SET_SHARED_ROOT(shared);
                 [ +  - ]
     600                 :     243956 :         ARY_SET_SHARED_NUM((VALUE)shared, 1);
     601 [ +  - ][ +  - ]:     243956 :         FL_SET_SHARED(ary);
                 [ +  - ]
     602                 :     243956 :         ARY_SET_SHARED(ary, (VALUE)shared);
     603                 :     243956 :         OBJ_FREEZE(shared);
     604                 :     243956 :         return (VALUE)shared;
     605                 :            :     }
     606                 :            : }
     607                 :            : 
     608                 :            : static VALUE
     609                 :     153218 : ary_make_substitution(VALUE ary)
     610                 :            : {
     611                 :     153218 :     long len = RARRAY_LEN(ary);
     612                 :            : 
     613         [ +  + ]:     153218 :     if (len <= RARRAY_EMBED_LEN_MAX) {
     614                 :      38297 :         VALUE subst = rb_ary_new2(len);
     615                 :      38297 :         ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary));
     616                 :      38297 :         ARY_SET_EMBED_LEN(subst, len);
     617                 :      38297 :         return subst;
     618                 :            :     }
     619                 :            :     else {
     620                 :     229842 :         return rb_ary_increment_share(ary_make_shared(ary));
     621                 :            :     }
     622                 :            : }
     623                 :            : 
     624                 :            : VALUE
     625                 :     389527 : rb_assoc_new(VALUE car, VALUE cdr)
     626                 :            : {
     627                 :     779054 :     return rb_ary_new3(2, car, cdr);
     628                 :            : }
     629                 :            : 
     630                 :            : VALUE
     631                 :        259 : rb_to_array_type(VALUE ary)
     632                 :            : {
     633                 :    5481591 :     return rb_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
     634                 :            : }
     635                 :            : #define to_ary rb_to_array_type
     636                 :            : 
     637                 :            : VALUE
     638                 :   10447653 : rb_check_array_type(VALUE ary)
     639                 :            : {
     640                 :   25754234 :     return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);
     641                 :            : }
     642                 :            : 
     643                 :            : MJIT_FUNC_EXPORTED VALUE
     644                 :   14845268 : rb_check_to_array(VALUE ary)
     645                 :            : {
     646                 :   14845268 :     return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_a);
     647                 :            : }
     648                 :            : 
     649                 :            : /*
     650                 :            :  *  call-seq:
     651                 :            :  *     Array.try_convert(obj) -> array or nil
     652                 :            :  *
     653                 :            :  *  Tries to convert +obj+ into an array, using +to_ary+ method.  Returns the
     654                 :            :  *  converted array or +nil+ if +obj+ cannot be converted for any reason.
     655                 :            :  *  This method can be used to check if an argument is an array.
     656                 :            :  *
     657                 :            :  *     Array.try_convert([1])   #=> [1]
     658                 :            :  *     Array.try_convert("1")   #=> nil
     659                 :            :  *
     660                 :            :  *     if tmp = Array.try_convert(arg)
     661                 :            :  *       # the argument is an array
     662                 :            :  *     elsif tmp = String.try_convert(arg)
     663                 :            :  *       # the argument is a string
     664                 :            :  *     end
     665                 :            :  *
     666                 :            :  */
     667                 :            : 
     668                 :            : static VALUE
     669                 :     833664 : rb_ary_s_try_convert(VALUE dummy, VALUE ary)
     670                 :            : {
     671                 :     833662 :     return rb_check_array_type(ary);
     672                 :            : }
     673                 :            : 
     674                 :            : /*
     675                 :            :  *  call-seq:
     676                 :            :  *     Array.new(size=0, default=nil)
     677                 :            :  *     Array.new(array)
     678                 :            :  *     Array.new(size) {|index| block }
     679                 :            :  *
     680                 :            :  *  Returns a new array.
     681                 :            :  *
     682                 :            :  *  In the first form, if no arguments are sent, the new array will be empty.
     683                 :            :  *  When a +size+ and an optional +default+ are sent, an array is created with
     684                 :            :  *  +size+ copies of +default+.  Take notice that all elements will reference the
     685                 :            :  *  same object +default+.
     686                 :            :  *
     687                 :            :  *  The second form creates a copy of the array passed as a parameter (the
     688                 :            :  *  array is generated by calling to_ary on the parameter).
     689                 :            :  *
     690                 :            :  *    first_array = ["Matz", "Guido"]
     691                 :            :  *
     692                 :            :  *    second_array = Array.new(first_array) #=> ["Matz", "Guido"]
     693                 :            :  *
     694                 :            :  *    first_array.equal? second_array       #=> false
     695                 :            :  *
     696                 :            :  *  In the last form, an array of the given size is created.  Each element in
     697                 :            :  *  this array is created by passing the element's index to the given block
     698                 :            :  *  and storing the return value.
     699                 :            :  *
     700                 :            :  *    Array.new(3) {|index| index ** 2}
     701                 :            :  *    # => [0, 1, 4]
     702                 :            :  *
     703                 :            :  *  == Common gotchas
     704                 :            :  *
     705                 :            :  *  When sending the second parameter, the same object will be used as the
     706                 :            :  *  value for all the array elements:
     707                 :            :  *
     708                 :            :  *     a = Array.new(2, Hash.new)
     709                 :            :  *     # => [{}, {}]
     710                 :            :  *
     711                 :            :  *     a[0]['cat'] = 'feline'
     712                 :            :  *     a # => [{"cat"=>"feline"}, {"cat"=>"feline"}]
     713                 :            :  *
     714                 :            :  *     a[1]['cat'] = 'Felix'
     715                 :            :  *     a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]
     716                 :            :  *
     717                 :            :  *  Since all the Array elements store the same hash, changes to one of them
     718                 :            :  *  will affect them all.
     719                 :            :  *
     720                 :            :  *  If multiple copies are what you want, you should use the block
     721                 :            :  *  version which uses the result of that block each time an element
     722                 :            :  *  of the array needs to be initialized:
     723                 :            :  *
     724                 :            :  *     a = Array.new(2) {Hash.new}
     725                 :            :  *     a[0]['cat'] = 'feline'
     726                 :            :  *     a # => [{"cat"=>"feline"}, {}]
     727                 :            :  *
     728                 :            :  */
     729                 :            : 
     730                 :            : static VALUE
     731                 :      78352 : rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
     732                 :            : {
     733                 :            :     long len;
     734                 :            :     VALUE size, val;
     735                 :            : 
     736                 :      78352 :     rb_ary_modify(ary);
     737         [ +  + ]:      78350 :     if (argc == 0) {
     738 [ +  - ][ +  - ]:       8643 :         if (ARY_OWNS_HEAP_P(ary) && RARRAY_CONST_PTR(ary) != 0) {
         [ +  - ][ +  + ]
                 [ +  - ]
     739                 :          1 :             ruby_sized_xfree((void *)RARRAY_CONST_PTR(ary), ARY_HEAP_SIZE(ary));
     740                 :            :         }
     741                 :       8642 :         rb_ary_unshare_safe(ary);
     742 [ +  - ][ +  - ]:       8642 :         FL_SET_EMBED(ary);
                 [ +  - ]
     743                 :       8642 :         ARY_SET_EMBED_LEN(ary, 0);
     744         [ +  + ]:       8642 :         if (rb_block_given_p()) {
     745                 :          4 :             rb_warning("given block not used");
     746                 :            :         }
     747                 :            :         return ary;
     748                 :            :     }
     749                 :     487956 :     rb_scan_args(argc, argv, "02", &size, &val);
     750 [ +  + ][ +  + ]:      69704 :     if (argc == 1 && !FIXNUM_P(size)) {
     751                 :        272 :         val = rb_check_array_type(size);
     752         [ +  + ]:        136 :         if (!NIL_P(val)) {
     753                 :        132 :             rb_ary_replace(ary, val);
     754                 :        132 :             return ary;
     755                 :            :         }
     756                 :            :     }
     757                 :            : 
     758                 :     139140 :     len = NUM2LONG(size);
     759                 :            :     /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
     760         [ +  + ]:      69568 :     if (len < 0) {
     761                 :          5 :         rb_raise(rb_eArgError, "negative array size");
     762                 :            :     }
     763         [ +  + ]:      69563 :     if (len > ARY_MAX_SIZE) {
     764                 :          3 :         rb_raise(rb_eArgError, "array size too big");
     765                 :            :     }
     766                 :            :     /* recheck after argument conversion */
     767                 :      69560 :     rb_ary_modify(ary);
     768                 :      69560 :     ary_resize_capa(ary, len);
     769         [ +  + ]:      69560 :     if (rb_block_given_p()) {
     770                 :            :         long i;
     771                 :            : 
     772         [ +  + ]:      23986 :         if (argc == 2) {
     773                 :      23986 :             rb_warn("block supersedes default value argument");
     774                 :            :         }
     775         [ +  + ]:      74443 :         for (i=0; i<len; i++) {
     776                 :      50460 :             rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
     777 [ +  - ][ +  - ]:      50457 :             ARY_SET_LEN(ary, i + 1);
         [ +  - ][ +  + ]
                 [ +  + ]
     778                 :            :         }
     779                 :            :     }
     780                 :            :     else {
     781                 :      45574 :         ary_memfill(ary, 0, len, val);
     782 [ +  - ][ +  - ]:      45574 :         ARY_SET_LEN(ary, len);
         [ +  - ][ +  + ]
                 [ +  + ]
     783                 :            :     }
     784                 :            :     return ary;
     785                 :            : }
     786                 :            : 
     787                 :            : /*
     788                 :            :  * Returns a new array populated with the given objects.
     789                 :            :  *
     790                 :            :  *   Array.[]( 1, 'a', /^A/)  # => [1, "a", /^A/]
     791                 :            :  *   Array[ 1, 'a', /^A/ ]    # => [1, "a", /^A/]
     792                 :            :  *   [ 1, 'a', /^A/ ]         # => [1, "a", /^A/]
     793                 :            :  */
     794                 :            : 
     795                 :            : static VALUE
     796                 :       1216 : rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
     797                 :            : {
     798                 :       1216 :     VALUE ary = ary_new(klass, argc);
     799         [ +  + ]:       1216 :     if (argc > 0 && argv) {
     800                 :       1061 :         ary_memcpy(ary, 0, argc, argv);
     801 [ +  - ][ +  - ]:       1061 :         ARY_SET_LEN(ary, argc);
         [ +  - ][ +  + ]
                 [ +  + ]
     802                 :            :     }
     803                 :            : 
     804                 :       1216 :     return ary;
     805                 :            : }
     806                 :            : 
     807                 :            : void
     808                 :   32277378 : rb_ary_store(VALUE ary, long idx, VALUE val)
     809                 :            : {
     810                 :   32277378 :     long len = RARRAY_LEN(ary);
     811                 :            : 
     812         [ +  + ]:   32277378 :     if (idx < 0) {
     813                 :        553 :         idx += len;
     814         [ +  + ]:        553 :         if (idx < 0) {
     815                 :          3 :             rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
     816                 :            :                      idx - len, -len);
     817                 :            :         }
     818                 :            :     }
     819         [ +  + ]:   32276825 :     else if (idx >= ARY_MAX_SIZE) {
     820                 :          2 :         rb_raise(rb_eIndexError, "index %ld too big", idx);
     821                 :            :     }
     822                 :            : 
     823                 :   32277373 :     rb_ary_modify(ary);
     824 [ +  - ][ +  - ]:   32277371 :     if (idx >= ARY_CAPA(ary)) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
     825                 :     141894 :         ary_double_capa(ary, idx);
     826                 :            :     }
     827         [ +  + ]:   32277371 :     if (idx > len) {
     828                 :      85429 :         ary_mem_clear(ary, len, idx - len + 1);
     829                 :            :     }
     830                 :            : 
     831         [ +  + ]:   32277371 :     if (idx >= len) {
     832 [ +  - ][ +  - ]:   24764939 :         ARY_SET_LEN(ary, idx + 1);
         [ +  - ][ +  + ]
                 [ +  + ]
     833                 :            :     }
     834                 :   64554742 :     ARY_SET(ary, idx, val);
     835                 :   32277371 : }
     836                 :            : 
     837                 :            : static VALUE
     838                 :     805793 : ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
     839                 :            : {
     840                 :            :     assert(offset >= 0);
     841                 :            :     assert(len >= 0);
     842                 :            :     assert(offset+len <= RARRAY_LEN(ary));
     843                 :            : 
     844         [ +  + ]:     805793 :     if (len <= RARRAY_EMBED_LEN_MAX) {
     845                 :     617836 :         VALUE result = ary_alloc(klass);
     846                 :     617836 :         ary_memcpy(result, 0, len, RARRAY_CONST_PTR(ary) + offset);
     847                 :     617836 :         ARY_SET_EMBED_LEN(result, len);
     848                 :     617836 :         return result;
     849                 :            :     }
     850                 :            :     else {
     851                 :     187957 :         VALUE shared, result = ary_alloc(klass);
     852 [ +  - ][ +  - ]:     187957 :         FL_UNSET_EMBED(result);
                 [ +  - ]
     853                 :            : 
     854                 :     187957 :         shared = ary_make_shared(ary);
     855                 :     375914 :         ARY_SET_PTR(result, RARRAY_CONST_PTR(ary));
     856 [ +  - ][ +  - ]:     375914 :         ARY_SET_LEN(result, RARRAY_LEN(ary));
         [ +  - ][ +  - ]
                 [ -  + ]
     857                 :     187957 :         rb_ary_set_shared(result, shared);
     858                 :            : 
     859                 :     187957 :         ARY_INCREASE_PTR(result, offset);
     860 [ +  - ][ +  - ]:     187957 :         ARY_SET_LEN(result, len);
         [ +  - ][ +  - ]
                 [ -  + ]
     861                 :     187957 :         return result;
     862                 :            :     }
     863                 :            : }
     864                 :            : 
     865                 :            : static VALUE
     866                 :        126 : ary_make_shared_copy(VALUE ary)
     867                 :            : {
     868                 :        126 :     return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary));
     869                 :            : }
     870                 :            : 
     871                 :            : enum ary_take_pos_flags
     872                 :            : {
     873                 :            :     ARY_TAKE_FIRST = 0,
     874                 :            :     ARY_TAKE_LAST = 1
     875                 :            : };
     876                 :            : 
     877                 :            : static VALUE
     878                 :       1322 : ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
     879                 :            : {
     880                 :            :     VALUE nv;
     881                 :            :     long n;
     882                 :            :     long len;
     883                 :       1322 :     long offset = 0;
     884                 :            : 
     885                 :       9254 :     rb_scan_args(argc, argv, "1", &nv);
     886                 :       2624 :     n = NUM2LONG(nv);
     887                 :       1304 :     len = RARRAY_LEN(ary);
     888         [ +  + ]:       1304 :     if (n > len) {
     889                 :            :         n = len;
     890                 :            :     }
     891         [ +  + ]:        988 :     else if (n < 0) {
     892                 :          7 :         rb_raise(rb_eArgError, "negative array size");
     893                 :            :     }
     894         [ +  + ]:       1297 :     if (last) {
     895                 :         50 :         offset = len - n;
     896                 :            :     }
     897                 :       1297 :     return ary_make_partial(ary, rb_cArray, offset, n);
     898                 :            : }
     899                 :            : 
     900                 :            : /*
     901                 :            :  *  call-seq:
     902                 :            :  *     ary << obj            -> ary
     903                 :            :  *
     904                 :            :  *  Append---Pushes the given object on to the end of this array. This
     905                 :            :  *  expression returns the array itself, so several appends
     906                 :            :  *  may be chained together.
     907                 :            :  *
     908                 :            :  *     a = [ 1, 2 ]
     909                 :            :  *     a << "c" << "d" << [ 3, 4 ]
     910                 :            :  *             #=>  [ 1, 2, "c", "d", [ 3, 4 ] ]
     911                 :            :  *     a
     912                 :            :  *             #=>  [ 1, 2, "c", "d", [ 3, 4 ] ]
     913                 :            :  *
     914                 :            :  */
     915                 :            : 
     916                 :            : VALUE
     917                 :  128525929 : rb_ary_push(VALUE ary, VALUE item)
     918                 :            : {
     919                 :  128525929 :     long idx = RARRAY_LEN(ary);
     920                 :  128525929 :     VALUE target_ary = ary_ensure_room_for_push(ary, 1);
     921                 :  257051848 :     RARRAY_PTR_USE(ary, ptr, {
     922                 :            :         RB_OBJ_WRITE(target_ary, &ptr[idx], item);
     923                 :            :     });
     924 [ +  - ][ +  - ]:  128525924 :     ARY_SET_LEN(ary, idx + 1);
         [ +  - ][ +  + ]
                 [ +  + ]
     925                 :  128525924 :     return ary;
     926                 :            : }
     927                 :            : 
     928                 :            : VALUE
     929                 :    6351585 : rb_ary_cat(VALUE ary, const VALUE *argv, long len)
     930                 :            : {
     931                 :    6351585 :     long oldlen = RARRAY_LEN(ary);
     932                 :    6351585 :     VALUE target_ary = ary_ensure_room_for_push(ary, len);
     933                 :    6351580 :     ary_memcpy0(ary, oldlen, len, argv, target_ary);
     934 [ +  - ][ +  - ]:    6351580 :     ARY_SET_LEN(ary, oldlen + len);
         [ +  - ][ +  + ]
                 [ +  + ]
     935                 :    6351580 :     return ary;
     936                 :            : }
     937                 :            : 
     938                 :            : /*
     939                 :            :  *  call-seq:
     940                 :            :  *     ary.push(obj, ...)    -> ary
     941                 :            :  *     ary.append(obj, ...)  -> ary
     942                 :            :  *
     943                 :            :  *  Append --- Pushes the given object(s) on to the end of this array. This
     944                 :            :  *  expression returns the array itself, so several appends
     945                 :            :  *  may be chained together. See also Array#pop for the opposite
     946                 :            :  *  effect.
     947                 :            :  *
     948                 :            :  *     a = [ "a", "b", "c" ]
     949                 :            :  *     a.push("d", "e", "f")
     950                 :            :  *             #=> ["a", "b", "c", "d", "e", "f"]
     951                 :            :  *     [1, 2, 3].push(4).push(5)
     952                 :            :  *             #=> [1, 2, 3, 4, 5]
     953                 :            :  */
     954                 :            : 
     955                 :            : static VALUE
     956                 :    6070616 : rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
     957                 :            : {
     958                 :    6070616 :     return rb_ary_cat(ary, argv, argc);
     959                 :            : }
     960                 :            : 
     961                 :            : VALUE
     962                 :    5208448 : rb_ary_pop(VALUE ary)
     963                 :            : {
     964                 :            :     long n;
     965                 :    5208448 :     rb_ary_modify_check(ary);
     966                 :    5208446 :     n = RARRAY_LEN(ary);
     967         [ +  + ]:    5208446 :     if (n == 0) return Qnil;
     968 [ +  - ][ +  - ]:    9791546 :     if (ARY_OWNS_HEAP_P(ary) &&
         [ +  - ][ +  + ]
                 [ +  + ]
     969 [ +  - ][ +  - ]:    6465332 :         n * 3 < ARY_CAPA(ary) &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
     970 [ +  - ][ +  - ]:    1829359 :         ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
     971                 :            :     {
     972                 :      68656 :         ary_resize_capa(ary, n * 2);
     973                 :            :     }
     974                 :    5155573 :     --n;
     975 [ +  - ][ +  - ]:    5155573 :     ARY_SET_LEN(ary, n);
         [ +  - ][ +  + ]
                 [ +  + ]
     976                 :    5155573 :     return RARRAY_AREF(ary, n);
     977                 :            : }
     978                 :            : 
     979                 :            : /*
     980                 :            :  *  call-seq:
     981                 :            :  *     ary.pop    -> obj or nil
     982                 :            :  *     ary.pop(n) -> new_ary
     983                 :            :  *
     984                 :            :  *  Removes the last element from +self+ and returns it, or
     985                 :            :  *  +nil+ if the array is empty.
     986                 :            :  *
     987                 :            :  *  If a number +n+ is given, returns an array of the last +n+ elements
     988                 :            :  *  (or less) just like <code>array.slice!(-n, n)</code> does. See also
     989                 :            :  *  Array#push for the opposite effect.
     990                 :            :  *
     991                 :            :  *     a = [ "a", "b", "c", "d" ]
     992                 :            :  *     a.pop     #=> "d"
     993                 :            :  *     a.pop(2)  #=> ["b", "c"]
     994                 :            :  *     a         #=> ["a"]
     995                 :            :  */
     996                 :            : 
     997                 :            : static VALUE
     998                 :    3480656 : rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
     999                 :            : {
    1000                 :            :     VALUE result;
    1001                 :            : 
    1002         [ +  + ]:    3480656 :     if (argc == 0) {
    1003                 :    3480628 :         return rb_ary_pop(ary);
    1004                 :            :     }
    1005                 :            : 
    1006                 :         28 :     rb_ary_modify_check(ary);
    1007                 :         26 :     result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
    1008 [ +  - ][ +  - ]:         44 :     ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
         [ +  - ][ +  + ]
                 [ +  + ]
    1009                 :         22 :     return result;
    1010                 :            : }
    1011                 :            : 
    1012                 :            : VALUE
    1013                 :    3565149 : rb_ary_shift(VALUE ary)
    1014                 :            : {
    1015                 :            :     VALUE top;
    1016                 :    3565149 :     long len = RARRAY_LEN(ary);
    1017                 :            : 
    1018                 :    3565149 :     rb_ary_modify_check(ary);
    1019         [ +  + ]:    3565147 :     if (len == 0) return Qnil;
    1020                 :    3545915 :     top = RARRAY_AREF(ary, 0);
    1021 [ +  - ][ +  - ]:    3545915 :     if (!ARY_SHARED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1022         [ +  + ]:    1702925 :         if (len < ARY_DEFAULT_SIZE) {
    1023                 :    3383022 :             RARRAY_PTR_USE(ary, ptr, {
    1024                 :            :                 MEMMOVE(ptr, ptr+1, VALUE, len-1);
    1025                 :            :             }); /* WB: no new reference */
    1026 [ +  - ][ +  - ]:    2867038 :             ARY_INCREASE_LEN(ary, -1);
         [ +  - ][ +  + ]
                 [ +  + ]
    1027                 :    1691511 :             return top;
    1028                 :            :         }
    1029                 :            :         assert(!ARY_EMBED_P(ary)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
    1030                 :            : 
    1031                 :      22828 :         ARY_SET(ary, 0, Qnil);
    1032                 :      11414 :         ary_make_shared(ary);
    1033                 :            :     }
    1034         [ +  + ]:    1842990 :     else if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
    1035                 :    1835242 :         RARRAY_PTR_USE(ary, ptr, ptr[0] = Qnil);
    1036                 :            :     }
    1037                 :    1854404 :     ARY_INCREASE_PTR(ary, 1);           /* shift ptr */
    1038 [ +  - ][ +  - ]:    1854404 :     ARY_INCREASE_LEN(ary, -1);
         [ +  - ][ +  - ]
                 [ -  + ]
    1039                 :            : 
    1040                 :    1854404 :     return top;
    1041                 :            : }
    1042                 :            : 
    1043                 :            : /*
    1044                 :            :  *  call-seq:
    1045                 :            :  *     ary.shift    -> obj or nil
    1046                 :            :  *     ary.shift(n) -> new_ary
    1047                 :            :  *
    1048                 :            :  *  Removes the first element of +self+ and returns it (shifting all
    1049                 :            :  *  other elements down by one). Returns +nil+ if the array
    1050                 :            :  *  is empty.
    1051                 :            :  *
    1052                 :            :  *  If a number +n+ is given, returns an array of the first +n+ elements
    1053                 :            :  *  (or less) just like <code>array.slice!(0, n)</code> does. With +ary+
    1054                 :            :  *  containing only the remainder elements, not including what was shifted to
    1055                 :            :  *  +new_ary+. See also Array#unshift for the opposite effect.
    1056                 :            :  *
    1057                 :            :  *     args = [ "-m", "-q", "filename" ]
    1058                 :            :  *     args.shift     #=> "-m"
    1059                 :            :  *     args           #=> ["-q", "filename"]
    1060                 :            :  *
    1061                 :            :  *     args = [ "-m", "-q", "filename" ]
    1062                 :            :  *     args.shift(2)  #=> ["-m", "-q"]
    1063                 :            :  *     args           #=> ["filename"]
    1064                 :            :  */
    1065                 :            : 
    1066                 :            : static VALUE
    1067                 :    3429393 : rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
    1068                 :            : {
    1069                 :            :     VALUE result;
    1070                 :            :     long n;
    1071                 :            : 
    1072         [ +  + ]:    3429393 :     if (argc == 0) {
    1073                 :    3429366 :         return rb_ary_shift(ary);
    1074                 :            :     }
    1075                 :            : 
    1076                 :         27 :     rb_ary_modify_check(ary);
    1077                 :         27 :     result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
    1078                 :         23 :     n = RARRAY_LEN(result);
    1079                 :         23 :     rb_ary_behead(ary,n);
    1080                 :            : 
    1081                 :         23 :     return result;
    1082                 :            : }
    1083                 :            : 
    1084                 :            : MJIT_FUNC_EXPORTED VALUE
    1085                 :   10444552 : rb_ary_behead(VALUE ary, long n)
    1086                 :            : {
    1087         [ +  + ]:   10444552 :     if(n<=0) return ary;
    1088                 :            : 
    1089                 :    2220362 :     rb_ary_modify_check(ary);
    1090 [ +  - ][ +  - ]:    2220362 :     if (ARY_SHARED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1091         [ +  + ]:          5 :         if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
    1092                 :            :           setup_occupied_shared:
    1093                 :            :             ary_mem_clear(ary, 0, n);
    1094                 :            :         }
    1095                 :         11 :         ARY_INCREASE_PTR(ary, n);
    1096                 :            :     }
    1097                 :            :     else {
    1098         [ +  + ]:    2220357 :         if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
    1099                 :    6661053 :             RARRAY_PTR_USE(ary, ptr, {
    1100                 :            :                 MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n);
    1101                 :            :             }); /* WB: no new reference */
    1102                 :            :         }
    1103                 :            :         else {
    1104                 :          6 :             ary_make_shared(ary);
    1105                 :          6 :             goto setup_occupied_shared;
    1106                 :            :         }
    1107                 :            :     }
    1108 [ +  - ][ +  - ]:    4439232 :     ARY_INCREASE_LEN(ary, -n);
         [ +  - ][ +  + ]
                 [ +  + ]
    1109                 :            : 
    1110                 :            :     return ary;
    1111                 :            : }
    1112                 :            : 
    1113                 :            : static VALUE
    1114                 :    2954799 : ary_ensure_room_for_unshift(VALUE ary, int argc)
    1115                 :            : {
    1116                 :    2954799 :     long len = RARRAY_LEN(ary);
    1117                 :    2954799 :     long new_len = len + argc;
    1118                 :            :     long capa;
    1119                 :            :     const VALUE *head, *sharedp;
    1120                 :            : 
    1121         [ -  + ]:    2954799 :     if (len > ARY_MAX_SIZE - argc) {
    1122                 :          0 :         rb_raise(rb_eIndexError, "index %ld too big", new_len);
    1123                 :            :     }
    1124                 :            : 
    1125 [ +  - ][ +  - ]:    2954799 :     if (ARY_SHARED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1126                 :    1492762 :         VALUE shared = ARY_SHARED(ary);
    1127                 :    1492762 :         capa = RARRAY_LEN(shared);
    1128 [ +  + ][ +  + ]:    1492762 :         if (ARY_SHARED_OCCUPIED(shared) && capa > new_len) {
    1129                 :    1491238 :             head = RARRAY_CONST_PTR(ary);
    1130                 :    1491238 :             sharedp = RARRAY_CONST_PTR(shared);
    1131                 :            :             goto makeroom_if_need;
    1132                 :            :         }
    1133                 :            :     }
    1134                 :            : 
    1135                 :    1463561 :     rb_ary_modify(ary);
    1136 [ +  - ][ +  - ]:    1463558 :     capa = ARY_CAPA(ary);
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
    1137         [ +  + ]:    1463558 :     if (capa - (capa >> 6) <= new_len) {
    1138                 :      24421 :         ary_double_capa(ary, new_len);
    1139                 :            :     }
    1140                 :            : 
    1141                 :            :     /* use shared array for big "queues" */
    1142         [ +  + ]:    1463558 :     if (new_len > ARY_DEFAULT_SIZE * 4) {
    1143                 :            :         /* make a room for unshifted items */
    1144 [ +  - ][ +  - ]:        207 :         capa = ARY_CAPA(ary);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
    1145                 :        207 :         ary_make_shared(ary);
    1146                 :            : 
    1147                 :        207 :         head = sharedp = RARRAY_CONST_PTR(ary);
    1148                 :        207 :         goto makeroom;
    1149                 :            :       makeroom_if_need:
    1150         [ +  + ]:    1491238 :         if (head - sharedp < argc) {
    1151                 :            :             long room;
    1152                 :            :           makeroom:
    1153                 :        595 :             room = capa - new_len;
    1154                 :        595 :             room -= room >> 4;
    1155                 :        595 :             MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
    1156                 :        595 :             head = sharedp + argc + room;
    1157                 :            :         }
    1158                 :    1491445 :         ARY_SET_PTR(ary, head - argc);
    1159                 :            :         assert(ARY_SHARED_OCCUPIED(ARY_SHARED(ary)));
    1160                 :    1491445 :         return ARY_SHARED(ary);
    1161                 :            :     }
    1162                 :            :     else {
    1163                 :            :         /* sliding items */
    1164                 :    2926702 :         RARRAY_PTR_USE(ary, ptr, {
    1165                 :            :             MEMMOVE(ptr + argc, ptr, VALUE, len);
    1166                 :            :         });
    1167                 :            : 
    1168                 :    1463351 :         return ary;
    1169                 :            :     }
    1170                 :            : }
    1171                 :            : 
    1172                 :            : /*
    1173                 :            :  *  call-seq:
    1174                 :            :  *     ary.unshift(obj, ...)  -> ary
    1175                 :            :  *     ary.prepend(obj, ...)  -> ary
    1176                 :            :  *
    1177                 :            :  *  Prepends objects to the front of +self+, moving other elements upwards.
    1178                 :            :  *  See also Array#shift for the opposite effect.
    1179                 :            :  *
    1180                 :            :  *     a = [ "b", "c", "d" ]
    1181                 :            :  *     a.unshift("a")   #=> ["a", "b", "c", "d"]
    1182                 :            :  *     a.unshift(1, 2)  #=> [ 1, 2, "a", "b", "c", "d"]
    1183                 :            :  */
    1184                 :            : 
    1185                 :            : static VALUE
    1186                 :    2979765 : rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
    1187                 :            : {
    1188                 :    2979765 :     long len = RARRAY_LEN(ary);
    1189                 :            :     VALUE target_ary;
    1190                 :            : 
    1191         [ +  + ]:    2979765 :     if (argc == 0) {
    1192                 :      24966 :         rb_ary_modify_check(ary);
    1193                 :      24963 :         return ary;
    1194                 :            :     }
    1195                 :            : 
    1196                 :    2954799 :     target_ary = ary_ensure_room_for_unshift(ary, argc);
    1197                 :    2954796 :     ary_memcpy0(ary, 0, argc, argv, target_ary);
    1198 [ +  - ][ +  - ]:    2954796 :     ARY_SET_LEN(ary, len + argc);
         [ +  - ][ +  + ]
                 [ +  + ]
    1199                 :            :     return ary;
    1200                 :            : }
    1201                 :            : 
    1202                 :            : VALUE
    1203                 :      26523 : rb_ary_unshift(VALUE ary, VALUE item)
    1204                 :            : {
    1205                 :      26523 :     return rb_ary_unshift_m(1,&item,ary);
    1206                 :            : }
    1207                 :            : 
    1208                 :            : /* faster version - use this if you don't need to treat negative offset */
    1209                 :            : static inline VALUE
    1210                 :  106743917 : rb_ary_elt(VALUE ary, long offset)
    1211                 :            : {
    1212                 :  106743917 :     long len = RARRAY_LEN(ary);
    1213         [ +  + ]:  106743917 :     if (len == 0) return Qnil;
    1214         [ +  + ]:  106743902 :     if (offset < 0 || len <= offset) {
    1215                 :            :         return Qnil;
    1216                 :            :     }
    1217                 :  106743826 :     return RARRAY_AREF(ary, offset);
    1218                 :            : }
    1219                 :            : 
    1220                 :            : VALUE
    1221                 :  647712001 : rb_ary_entry(VALUE ary, long offset)
    1222                 :            : {
    1223                 :  647839457 :     return rb_ary_entry_internal(ary, offset);
    1224                 :            : }
    1225                 :            : 
    1226                 :            : VALUE
    1227                 :    1090751 : rb_ary_subseq(VALUE ary, long beg, long len)
    1228                 :            : {
    1229                 :            :     VALUE klass;
    1230                 :    1090751 :     long alen = RARRAY_LEN(ary);
    1231                 :            : 
    1232         [ +  + ]:    1090751 :     if (beg > alen) return Qnil;
    1233         [ +  + ]:    1090728 :     if (beg < 0 || len < 0) return Qnil;
    1234                 :            : 
    1235 [ +  + ][ +  + ]:    1090688 :     if (alen < len || alen < beg + len) {
    1236                 :       9761 :         len = alen - beg;
    1237                 :            :     }
    1238                 :    1090688 :     klass = rb_obj_class(ary);
    1239         [ +  + ]:    1090688 :     if (len == 0) return ary_new(klass, 0);
    1240                 :            : 
    1241                 :     804370 :     return ary_make_partial(ary, klass, beg, len);
    1242                 :            : }
    1243                 :            : 
    1244                 :            : /*
    1245                 :            :  *  call-seq:
    1246                 :            :  *     ary[index]                -> obj     or nil
    1247                 :            :  *     ary[start, length]        -> new_ary or nil
    1248                 :            :  *     ary[range]                -> new_ary or nil
    1249                 :            :  *     ary.slice(index)          -> obj     or nil
    1250                 :            :  *     ary.slice(start, length)  -> new_ary or nil
    1251                 :            :  *     ary.slice(range)          -> new_ary or nil
    1252                 :            :  *
    1253                 :            :  *  Element Reference --- Returns the element at +index+, or returns a
    1254                 :            :  *  subarray starting at the +start+ index and continuing for +length+
    1255                 :            :  *  elements, or returns a subarray specified by +range+ of indices.
    1256                 :            :  *
    1257                 :            :  *  Negative indices count backward from the end of the array (-1 is the last
    1258                 :            :  *  element).  For +start+ and +range+ cases the starting index is just before
    1259                 :            :  *  an element.  Additionally, an empty array is returned when the starting
    1260                 :            :  *  index for an element range is at the end of the array.
    1261                 :            :  *
    1262                 :            :  *  Returns +nil+ if the index (or starting index) are out of range.
    1263                 :            :  *
    1264                 :            :  *     a = [ "a", "b", "c", "d", "e" ]
    1265                 :            :  *     a[2] +  a[0] + a[1]    #=> "cab"
    1266                 :            :  *     a[6]                   #=> nil
    1267                 :            :  *     a[1, 2]                #=> [ "b", "c" ]
    1268                 :            :  *     a[1..3]                #=> [ "b", "c", "d" ]
    1269                 :            :  *     a[4..7]                #=> [ "e" ]
    1270                 :            :  *     a[6..10]               #=> nil
    1271                 :            :  *     a[-3, 3]               #=> [ "c", "d", "e" ]
    1272                 :            :  *     # special cases
    1273                 :            :  *     a[5]                   #=> nil
    1274                 :            :  *     a[6, 1]                #=> nil
    1275                 :            :  *     a[5, 1]                #=> []
    1276                 :            :  *     a[5..10]               #=> []
    1277                 :            :  *
    1278                 :            :  */
    1279                 :            : 
    1280                 :            : VALUE
    1281                 :     257669 : rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
    1282                 :            : {
    1283                 :     257669 :     rb_check_arity(argc, 1, 2);
    1284         [ +  + ]:     257668 :     if (argc == 2) {
    1285                 :     257033 :         return rb_ary_aref2(ary, argv[0], argv[1]);
    1286                 :            :     }
    1287                 :        635 :     return rb_ary_aref1(ary, argv[0]);
    1288                 :            : }
    1289                 :            : 
    1290                 :            : VALUE
    1291                 :     257033 : rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
    1292                 :            : {
    1293                 :     257033 :     long beg = NUM2LONG(b);
    1294                 :     257029 :     long len = NUM2LONG(e);
    1295         [ +  + ]:     257029 :     if (beg < 0) {
    1296                 :         57 :         beg += RARRAY_LEN(ary);
    1297                 :            :     }
    1298                 :     257029 :     return rb_ary_subseq(ary, beg, len);
    1299                 :            : }
    1300                 :            : 
    1301                 :            : MJIT_FUNC_EXPORTED VALUE
    1302                 :     544262 : rb_ary_aref1(VALUE ary, VALUE arg)
    1303                 :            : {
    1304                 :            :     long beg, len;
    1305                 :            : 
    1306                 :            :     /* special case - speeding up */
    1307         [ +  + ]:     544262 :     if (FIXNUM_P(arg)) {
    1308                 :        368 :         return rb_ary_entry(ary, FIX2LONG(arg));
    1309                 :            :     }
    1310                 :            :     /* check if idx is Range */
    1311      [ +  +  + ]:     543894 :     switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
    1312                 :            :       case Qfalse:
    1313                 :            :         break;
    1314                 :            :       case Qnil:
    1315                 :            :         return Qnil;
    1316                 :            :       default:
    1317                 :     543835 :         return rb_ary_subseq(ary, beg, len);
    1318                 :            :     }
    1319                 :          2 :     return rb_ary_entry(ary, NUM2LONG(arg));
    1320                 :            : }
    1321                 :            : 
    1322                 :            : /*
    1323                 :            :  *  call-seq:
    1324                 :            :  *     ary.at(index)   ->   obj  or nil
    1325                 :            :  *
    1326                 :            :  *  Returns the element at +index+. A negative index counts from the end of
    1327                 :            :  *  +self+. Returns +nil+ if the index is out of range. See also
    1328                 :            :  *  Array#[].
    1329                 :            :  *
    1330                 :            :  *     a = [ "a", "b", "c", "d", "e" ]
    1331                 :            :  *     a.at(0)     #=> "a"
    1332                 :            :  *     a.at(-1)    #=> "e"
    1333                 :            :  */
    1334                 :            : 
    1335                 :            : VALUE
    1336                 :       1749 : rb_ary_at(VALUE ary, VALUE pos)
    1337                 :            : {
    1338                 :       3492 :     return rb_ary_entry(ary, NUM2LONG(pos));
    1339                 :            : }
    1340                 :            : 
    1341                 :            : /*
    1342                 :            :  *  call-seq:
    1343                 :            :  *     ary.first     ->   obj or nil
    1344                 :            :  *     ary.first(n)  ->   new_ary
    1345                 :            :  *
    1346                 :            :  *  Returns the first element, or the first +n+ elements, of the array.
    1347                 :            :  *  If the array is empty, the first form returns +nil+, and the
    1348                 :            :  *  second form returns an empty array. See also Array#last for
    1349                 :            :  *  the opposite effect.
    1350                 :            :  *
    1351                 :            :  *     a = [ "q", "r", "s", "t" ]
    1352                 :            :  *     a.first     #=> "q"
    1353                 :            :  *     a.first(2)  #=> ["q", "r"]
    1354                 :            :  */
    1355                 :            : 
    1356                 :            : static VALUE
    1357                 :    2961403 : rb_ary_first(int argc, VALUE *argv, VALUE ary)
    1358                 :            : {
    1359         [ +  + ]:    2961403 :     if (argc == 0) {
    1360         [ +  + ]:    2960171 :         if (RARRAY_LEN(ary) == 0) return Qnil;
    1361                 :    2925507 :         return RARRAY_AREF(ary, 0);
    1362                 :            :     }
    1363                 :            :     else {
    1364                 :       1232 :         return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
    1365                 :            :     }
    1366                 :            : }
    1367                 :            : 
    1368                 :            : /*
    1369                 :            :  *  call-seq:
    1370                 :            :  *     ary.last     ->  obj or nil
    1371                 :            :  *     ary.last(n)  ->  new_ary
    1372                 :            :  *
    1373                 :            :  *  Returns the last element(s) of +self+. If the array is empty,
    1374                 :            :  *  the first form returns +nil+.
    1375                 :            :  *
    1376                 :            :  *  See also Array#first for the opposite effect.
    1377                 :            :  *
    1378                 :            :  *     a = [ "w", "x", "y", "z" ]
    1379                 :            :  *     a.last     #=> "z"
    1380                 :            :  *     a.last(2)  #=> ["y", "z"]
    1381                 :            :  */
    1382                 :            : 
    1383                 :            : VALUE
    1384                 :    3944693 : rb_ary_last(int argc, const VALUE *argv, VALUE ary)
    1385                 :            : {
    1386         [ +  + ]:    3944693 :     if (argc == 0) {
    1387                 :    3944656 :         long len = RARRAY_LEN(ary);
    1388         [ +  + ]:    3944656 :         if (len == 0) return Qnil;
    1389                 :    3912663 :         return RARRAY_AREF(ary, len-1);
    1390                 :            :     }
    1391                 :            :     else {
    1392                 :         37 :         return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
    1393                 :            :     }
    1394                 :            : }
    1395                 :            : 
    1396                 :            : /*
    1397                 :            :  *  call-seq:
    1398                 :            :  *     ary.fetch(index)                    -> obj
    1399                 :            :  *     ary.fetch(index, default)           -> obj
    1400                 :            :  *     ary.fetch(index) {|index| block}    -> obj
    1401                 :            :  *
    1402                 :            :  *  Tries to return the element at position +index+, but throws an IndexError
    1403                 :            :  *  exception if the referenced +index+ lies outside of the array bounds.  This
    1404                 :            :  *  error can be prevented by supplying a second argument, which will act as a
    1405                 :            :  *  +default+ value.
    1406                 :            :  *
    1407                 :            :  *  Alternatively, if a block is given it will only be executed when an
    1408                 :            :  *  invalid +index+ is referenced.
    1409                 :            :  *
    1410                 :            :  *  Negative values of +index+ count from the end of the array.
    1411                 :            :  *
    1412                 :            :  *     a = [ 11, 22, 33, 44 ]
    1413                 :            :  *     a.fetch(1)               #=> 22
    1414                 :            :  *     a.fetch(-1)              #=> 44
    1415                 :            :  *     a.fetch(4, 'cat')        #=> "cat"
    1416                 :            :  *     a.fetch(100) {|i| puts "#{i} is out of bounds"}
    1417                 :            :  *                              #=> "100 is out of bounds"
    1418                 :            :  */
    1419                 :            : 
    1420                 :            : static VALUE
    1421                 :      11369 : rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
    1422                 :            : {
    1423                 :            :     VALUE pos, ifnone;
    1424                 :            :     long block_given;
    1425                 :            :     long idx;
    1426                 :            : 
    1427                 :      79583 :     rb_scan_args(argc, argv, "11", &pos, &ifnone);
    1428                 :      11369 :     block_given = rb_block_given_p();
    1429         [ +  + ]:      11369 :     if (block_given && argc == 2) {
    1430                 :          2 :         rb_warn("block supersedes default value argument");
    1431                 :            :     }
    1432                 :      22715 :     idx = NUM2LONG(pos);
    1433                 :            : 
    1434         [ +  + ]:      11346 :     if (idx < 0) {
    1435                 :          9 :         idx +=  RARRAY_LEN(ary);
    1436                 :            :     }
    1437 [ +  + ][ +  + ]:      22686 :     if (idx < 0 || RARRAY_LEN(ary) <= idx) {
    1438         [ +  + ]:       8653 :         if (block_given) return rb_yield(pos);
    1439         [ +  + ]:          9 :         if (argc == 1) {
    1440                 :          5 :             rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld",
    1441         [ +  + ]:          5 :                         idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary));
    1442                 :            :         }
    1443                 :          4 :         return ifnone;
    1444                 :            :     }
    1445                 :       2693 :     return RARRAY_AREF(ary, idx);
    1446                 :            : }
    1447                 :            : 
    1448                 :            : /*
    1449                 :            :  *  call-seq:
    1450                 :            :  *     ary.find_index(obj)             ->  int or nil
    1451                 :            :  *     ary.find_index {|item| block}  ->  int or nil
    1452                 :            :  *     ary.find_index                  ->  Enumerator
    1453                 :            :  *     ary.index(obj)             ->  int or nil
    1454                 :            :  *     ary.index {|item| block}   ->  int or nil
    1455                 :            :  *     ary.index                  ->  Enumerator
    1456                 :            :  *
    1457                 :            :  *  Returns the _index_ of the first object in +ary+ such that the object is
    1458                 :            :  *  <code>==</code> to +obj+.
    1459                 :            :  *
    1460                 :            :  *  If a block is given instead of an argument, returns the _index_ of the
    1461                 :            :  *  first object for which the block returns +true+.  Returns +nil+ if no
    1462                 :            :  *  match is found.
    1463                 :            :  *
    1464                 :            :  *  See also Array#rindex.
    1465                 :            :  *
    1466                 :            :  *  An Enumerator is returned if neither a block nor argument is given.
    1467                 :            :  *
    1468                 :            :  *     a = [ "a", "b", "c" ]
    1469                 :            :  *     a.index("b")              #=> 1
    1470                 :            :  *     a.index("z")              #=> nil
    1471                 :            :  *     a.index {|x| x == "b"}    #=> 1
    1472                 :            :  */
    1473                 :            : 
    1474                 :            : static VALUE
    1475                 :      36288 : rb_ary_index(int argc, VALUE *argv, VALUE ary)
    1476                 :            : {
    1477                 :            :     VALUE val;
    1478                 :            :     long i;
    1479                 :            : 
    1480         [ +  + ]:      36288 :     if (argc == 0) {
    1481         [ +  + ]:       3879 :         RETURN_ENUMERATOR(ary, 0, 0);
    1482         [ +  + ]:      21694 :         for (i=0; i<RARRAY_LEN(ary); i++) {
    1483         [ +  + ]:      10154 :             if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
    1484                 :       1245 :                 return LONG2NUM(i);
    1485                 :            :             }
    1486                 :            :         }
    1487                 :            :         return Qnil;
    1488                 :            :     }
    1489                 :      32409 :     rb_check_arity(argc, 0, 1);
    1490                 :      32409 :     val = argv[0];
    1491         [ +  + ]:      32409 :     if (rb_block_given_p())
    1492                 :      32409 :         rb_warn("given block not used");
    1493         [ +  + ]:     334771 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    1494                 :     182080 :         VALUE e = RARRAY_AREF(ary, i);
    1495         [ +  + ]:     182080 :         if (rb_equal(e, val)) {
    1496                 :      30899 :             return LONG2NUM(i);
    1497                 :            :         }
    1498                 :            :     }
    1499                 :            :     return Qnil;
    1500                 :            : }
    1501                 :            : 
    1502                 :            : /*
    1503                 :            :  *  call-seq:
    1504                 :            :  *     ary.rindex(obj)             ->  int or nil
    1505                 :            :  *     ary.rindex {|item| block}   ->  int or nil
    1506                 :            :  *     ary.rindex                  ->  Enumerator
    1507                 :            :  *
    1508                 :            :  *  Returns the _index_ of the last object in +self+ <code>==</code> to +obj+.
    1509                 :            :  *
    1510                 :            :  *  If a block is given instead of an argument, returns the _index_ of the
    1511                 :            :  *  first object for which the block returns +true+, starting from the last
    1512                 :            :  *  object.
    1513                 :            :  *
    1514                 :            :  *  Returns +nil+ if no match is found.
    1515                 :            :  *
    1516                 :            :  *  See also Array#index.
    1517                 :            :  *
    1518                 :            :  *  If neither block nor argument is given, an Enumerator is returned instead.
    1519                 :            :  *
    1520                 :            :  *     a = [ "a", "b", "b", "b", "c" ]
    1521                 :            :  *     a.rindex("b")             #=> 3
    1522                 :            :  *     a.rindex("z")             #=> nil
    1523                 :            :  *     a.rindex {|x| x == "b"}   #=> 3
    1524                 :            :  */
    1525                 :            : 
    1526                 :            : static VALUE
    1527                 :        315 : rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
    1528                 :            : {
    1529                 :            :     VALUE val;
    1530                 :        315 :     long i = RARRAY_LEN(ary), len;
    1531                 :            : 
    1532         [ +  + ]:        315 :     if (argc == 0) {
    1533         [ +  + ]:          9 :         RETURN_ENUMERATOR(ary, 0, 0);
    1534         [ +  + ]:         14 :         while (i--) {
    1535         [ +  + ]:         11 :             if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
    1536                 :          3 :                 return LONG2NUM(i);
    1537         [ +  + ]:          8 :             if (i > (len = RARRAY_LEN(ary))) {
    1538                 :          8 :                 i = len;
    1539                 :            :             }
    1540                 :            :         }
    1541                 :            :         return Qnil;
    1542                 :            :     }
    1543                 :        306 :     rb_check_arity(argc, 0, 1);
    1544                 :        306 :     val = argv[0];
    1545         [ +  + ]:        306 :     if (rb_block_given_p())
    1546                 :          2 :         rb_warn("given block not used");
    1547         [ +  + ]:        624 :     while (i--) {
    1548                 :        525 :         VALUE e = RARRAY_AREF(ary, i);
    1549         [ +  + ]:        525 :         if (rb_equal(e, val)) {
    1550                 :        513 :             return LONG2NUM(i);
    1551                 :            :         }
    1552                 :            :     }
    1553                 :            :     return Qnil;
    1554                 :            : }
    1555                 :            : 
    1556                 :            : VALUE
    1557                 :       1986 : rb_ary_to_ary(VALUE obj)
    1558                 :            : {
    1559                 :       1986 :     VALUE tmp = rb_check_array_type(obj);
    1560                 :            : 
    1561         [ +  + ]:       1986 :     if (!NIL_P(tmp)) return tmp;
    1562                 :        192 :     return rb_ary_new3(1, obj);
    1563                 :            : }
    1564                 :            : 
    1565                 :            : static void
    1566                 :    3360184 : rb_ary_splice(VALUE ary, long beg, long len, const VALUE *rptr, long rlen)
    1567                 :            : {
    1568                 :            :     long olen;
    1569                 :            :     long rofs;
    1570                 :            : 
    1571         [ +  + ]:    3360184 :     if (len < 0) rb_raise(rb_eIndexError, "negative length (%ld)", len);
    1572                 :    3360177 :     olen = RARRAY_LEN(ary);
    1573         [ +  + ]:    3360177 :     if (beg < 0) {
    1574                 :         28 :         beg += olen;
    1575         [ +  + ]:         28 :         if (beg < 0) {
    1576                 :          5 :             rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
    1577                 :            :                      beg - olen, -olen);
    1578                 :            :         }
    1579                 :            :     }
    1580 [ +  + ][ +  + ]:    3360172 :     if (olen < len || olen < beg + len) {
    1581                 :        329 :         len = olen - beg;
    1582                 :            :     }
    1583                 :            : 
    1584                 :            :     {
    1585                 :    3360172 :         const VALUE *optr = RARRAY_CONST_PTR(ary);
    1586 [ +  + ][ +  + ]:    3360172 :         rofs = (rptr >= optr && rptr < optr + olen) ? rptr - optr : -1;
    1587                 :            :     }
    1588                 :            : 
    1589         [ +  + ]:    3360172 :     if (beg >= olen) {
    1590                 :            :         VALUE target_ary;
    1591         [ +  + ]:    3351658 :         if (beg > ARY_MAX_SIZE - rlen) {
    1592                 :          2 :             rb_raise(rb_eIndexError, "index %ld too big", beg);
    1593                 :            :         }
    1594                 :    3351656 :         target_ary = ary_ensure_room_for_push(ary, rlen-len); /* len is 0 or negative */
    1595                 :    3351656 :         len = beg + rlen;
    1596                 :    3351656 :         ary_mem_clear(ary, olen, beg - olen);
    1597         [ +  + ]:    3351656 :         if (rlen > 0) {
    1598         [ +  + ]:    3351079 :             if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
    1599                 :    3351075 :             ary_memcpy0(ary, beg, rlen, rptr, target_ary);
    1600                 :            :         }
    1601 [ +  - ][ +  - ]:    3351656 :         ARY_SET_LEN(ary, len);
         [ +  - ][ +  + ]
                 [ +  + ]
    1602                 :            :     }
    1603                 :            :     else {
    1604                 :            :         long alen;
    1605                 :            : 
    1606         [ -  + ]:       8514 :         if (olen - len > ARY_MAX_SIZE - rlen) {
    1607                 :          0 :             rb_raise(rb_eIndexError, "index %ld too big", olen + rlen - len);
    1608                 :            :         }
    1609                 :       8514 :         rb_ary_modify(ary);
    1610                 :       8514 :         alen = olen + rlen - len;
    1611 [ +  - ][ +  - ]:       8514 :         if (alen >= ARY_CAPA(ary)) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
    1612                 :       1801 :             ary_double_capa(ary, alen);
    1613                 :            :         }
    1614                 :            : 
    1615         [ +  + ]:       8514 :         if (len != rlen) {
    1616                 :      16680 :             RARRAY_PTR_USE(ary, ptr,
    1617                 :            :                            MEMMOVE(ptr + beg + rlen, ptr + beg + len,
    1618                 :            :                                    VALUE, olen - (beg + len)));
    1619 [ +  - ][ +  - ]:       8340 :             ARY_SET_LEN(ary, alen);
         [ +  - ][ +  + ]
                 [ +  + ]
    1620                 :            :         }
    1621         [ +  + ]:       8514 :         if (rlen > 0) {
    1622         [ +  + ]:       3792 :             if (rofs != -1) rptr = RARRAY_CONST_PTR(ary) + rofs;
    1623                 :      11355 :             MEMMOVE(RARRAY_PTR(ary) + beg, rptr, VALUE, rlen);
    1624                 :            :         }
    1625                 :            :     }
    1626                 :    3360170 : }
    1627                 :            : 
    1628                 :            : void
    1629                 :    1328221 : rb_ary_set_len(VALUE ary, long len)
    1630                 :            : {
    1631                 :            :     long capa;
    1632                 :            : 
    1633                 :    1328221 :     rb_ary_modify_check(ary);
    1634 [ +  - ][ +  - ]:    1328221 :     if (ARY_SHARED_P(ary)) {
         [ +  - ][ +  - ]
                 [ -  + ]
    1635                 :          0 :         rb_raise(rb_eRuntimeError, "can't set length of shared ");
    1636                 :            :     }
    1637 [ +  - ][ +  - ]:    1328221 :     if (len > (capa = (long)ARY_CAPA(ary))) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
    1638                 :          0 :         rb_bug("probable buffer overflow: %ld for %ld", len, capa);
    1639                 :            :     }
    1640 [ +  - ][ +  - ]:    1328221 :     ARY_SET_LEN(ary, len);
         [ +  - ][ +  + ]
                 [ +  + ]
    1641                 :    1328221 : }
    1642                 :            : 
    1643                 :            : /*!
    1644                 :            :  * expands or shrinks \a ary to \a len elements.
    1645                 :            :  * expanded region will be filled with Qnil.
    1646                 :            :  * \param ary  an array
    1647                 :            :  * \param len  new size
    1648                 :            :  * \return     \a ary
    1649                 :            :  * \post       the size of \a ary is \a len.
    1650                 :            :  */
    1651                 :            : VALUE
    1652                 :     207111 : rb_ary_resize(VALUE ary, long len)
    1653                 :            : {
    1654                 :            :     long olen;
    1655                 :            : 
    1656                 :     207111 :     rb_ary_modify(ary);
    1657                 :     207111 :     olen = RARRAY_LEN(ary);
    1658         [ +  + ]:     207111 :     if (len == olen) return ary;
    1659         [ -  + ]:     205825 :     if (len > ARY_MAX_SIZE) {
    1660                 :          0 :         rb_raise(rb_eIndexError, "index %ld too big", len);
    1661                 :            :     }
    1662         [ +  + ]:     205825 :     if (len > olen) {
    1663 [ +  - ][ +  - ]:          5 :         if (len >= ARY_CAPA(ary)) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
    1664                 :          3 :             ary_double_capa(ary, len);
    1665                 :            :         }
    1666                 :          5 :         ary_mem_clear(ary, olen, len - olen);
    1667 [ +  - ][ +  - ]:          5 :         ARY_SET_LEN(ary, len);
         [ +  - ][ +  - ]
                 [ -  + ]
    1668                 :            :     }
    1669 [ +  - ][ +  - ]:     205820 :     else if (ARY_EMBED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
    1670                 :     176044 :         ARY_SET_EMBED_LEN(ary, len);
    1671                 :            :     }
    1672         [ +  + ]:      29776 :     else if (len <= RARRAY_EMBED_LEN_MAX) {
    1673                 :            :         VALUE tmp[RARRAY_EMBED_LEN_MAX];
    1674                 :      12249 :         MEMCPY(tmp, ARY_HEAP_PTR(ary), VALUE, len);
    1675                 :            :         ary_discard(ary);
    1676                 :      12249 :         MEMCPY((VALUE *)ARY_EMBED_PTR(ary), tmp, VALUE, len); /* WB: no new reference */
    1677                 :      12249 :         ARY_SET_EMBED_LEN(ary, len);
    1678                 :            :     }
    1679                 :            :     else {
    1680         [ +  + ]:      17527 :         if (olen > len + ARY_DEFAULT_SIZE) {
    1681                 :      11014 :             SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, len, RARRAY(ary)->as.heap.aux.capa);
    1682                 :      11014 :             ARY_SET_CAPA(ary, len);
    1683                 :            :         }
    1684                 :      17527 :         ARY_SET_HEAP_LEN(ary, len);
    1685                 :            :     }
    1686                 :            :     return ary;
    1687                 :            : }
    1688                 :            : 
    1689                 :            : /*
    1690                 :            :  *  call-seq:
    1691                 :            :  *     ary[index]         = obj                      ->  obj
    1692                 :            :  *     ary[start, length] = obj or other_ary or nil  ->  obj or other_ary or nil
    1693                 :            :  *     ary[range]         = obj or other_ary or nil  ->  obj or other_ary or nil
    1694                 :            :  *
    1695                 :            :  *  Element Assignment --- Sets the element at +index+, or replaces a subarray
    1696                 :            :  *  from the +start+ index for +length+ elements, or replaces a subarray
    1697                 :            :  *  specified by the +range+ of indices.
    1698                 :            :  *
    1699                 :            :  *  If indices are greater than the current capacity of the array, the array
    1700                 :            :  *  grows automatically.  Elements are inserted into the array at +start+ if
    1701                 :            :  *  +length+ is zero.
    1702                 :            :  *
    1703                 :            :  *  Negative indices will count backward from the end of the array.  For
    1704                 :            :  *  +start+ and +range+ cases the starting index is just before an element.
    1705                 :            :  *
    1706                 :            :  *  An IndexError is raised if a negative index points past the beginning of
    1707                 :            :  *  the array.
    1708                 :            :  *
    1709                 :            :  *  See also Array#push, and Array#unshift.
    1710                 :            :  *
    1711                 :            :  *     a = Array.new
    1712                 :            :  *     a[4] = "4";                 #=> [nil, nil, nil, nil, "4"]
    1713                 :            :  *     a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
    1714                 :            :  *     a[1..2] = [ 1, 2 ]          #=> ["a", 1, 2, nil, "4"]
    1715                 :            :  *     a[0, 2] = "?"               #=> ["?", 2, nil, "4"]
    1716                 :            :  *     a[0..2] = "A"               #=> ["A", "4"]
    1717                 :            :  *     a[-1]   = "Z"               #=> ["A", "Z"]
    1718                 :            :  *     a[1..-1] = nil              #=> ["A", nil]
    1719                 :            :  *     a[1..-1] = []               #=> ["A"]
    1720                 :            :  *     a[0, 0] = [ 1, 2 ]          #=> [1, 2, "A"]
    1721                 :            :  *     a[3, 0] = "B"               #=> [1, 2, "A", "B"]
    1722                 :            :  */
    1723                 :            : 
    1724                 :            : static VALUE
    1725                 :       2020 : rb_ary_aset(int argc, VALUE *argv, VALUE ary)
    1726                 :            : {
    1727                 :            :     long offset, beg, len;
    1728                 :            :     VALUE rpl;
    1729                 :            : 
    1730         [ +  + ]:       2020 :     if (argc == 3) {
    1731                 :       1717 :         rb_ary_modify_check(ary);
    1732                 :       3430 :         beg = NUM2LONG(argv[0]);
    1733                 :       3430 :         len = NUM2LONG(argv[1]);
    1734                 :       1715 :         goto range;
    1735                 :            :     }
    1736                 :        303 :     rb_check_arity(argc, 2, 2);
    1737                 :        301 :     rb_ary_modify_check(ary);
    1738         [ +  + ]:        297 :     if (FIXNUM_P(argv[0])) {
    1739                 :         16 :         offset = FIX2LONG(argv[0]);
    1740                 :         16 :         goto fixnum;
    1741                 :            :     }
    1742         [ +  + ]:        281 :     if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
    1743                 :            :         /* check if idx is Range */
    1744                 :            :       range:
    1745                 :       1982 :         rpl = rb_ary_to_ary(argv[argc-1]);
    1746                 :       1982 :         rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl));
    1747                 :       1968 :         RB_GC_GUARD(rpl);
    1748                 :       1968 :         return argv[argc-1];
    1749                 :            :     }
    1750                 :            : 
    1751                 :          2 :     offset = NUM2LONG(argv[0]);
    1752                 :            : fixnum:
    1753                 :         18 :     rb_ary_store(ary, offset, argv[1]);
    1754                 :         17 :     return argv[1];
    1755                 :            : }
    1756                 :            : 
    1757                 :            : /*
    1758                 :            :  *  call-seq:
    1759                 :            :  *     ary.insert(index, obj...)  -> ary
    1760                 :            :  *
    1761                 :            :  *  Inserts the given values before the element with the given +index+.
    1762                 :            :  *
    1763                 :            :  *  Negative indices count backwards from the end of the array, where +-1+ is
    1764                 :            :  *  the last element. If a negative index is used, the given values will be
    1765                 :            :  *  inserted after that element, so using an index of +-1+ will insert the
    1766                 :            :  *  values at the end of the array.
    1767                 :            :  *
    1768                 :            :  *     a = %w{ a b c d }
    1769                 :            :  *     a.insert(2, 99)         #=> ["a", "b", 99, "c", "d"]
    1770                 :            :  *     a.insert(-2, 1, 2, 3)   #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
    1771                 :            :  */
    1772                 :            : 
    1773                 :            : static VALUE
    1774                 :       3229 : rb_ary_insert(int argc, VALUE *argv, VALUE ary)
    1775                 :            : {
    1776                 :            :     long pos;
    1777                 :            : 
    1778                 :       3229 :     rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    1779                 :       3226 :     rb_ary_modify_check(ary);
    1780                 :       6445 :     pos = NUM2LONG(argv[0]);
    1781         [ +  + ]:       3222 :     if (argc == 1) return ary;
    1782         [ +  + ]:       3213 :     if (pos == -1) {
    1783                 :          4 :         pos = RARRAY_LEN(ary);
    1784                 :            :     }
    1785         [ +  + ]:       3209 :     else if (pos < 0) {
    1786                 :          9 :         long minpos = -RARRAY_LEN(ary) - 1;
    1787         [ +  + ]:          9 :         if (pos < minpos) {
    1788                 :          3 :             rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
    1789                 :            :                      pos, minpos);
    1790                 :            :         }
    1791                 :          6 :         pos++;
    1792                 :            :     }
    1793                 :       3210 :     rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
    1794                 :       3210 :     return ary;
    1795                 :            : }
    1796                 :            : 
    1797                 :            : static VALUE
    1798                 :            : rb_ary_length(VALUE ary);
    1799                 :            : 
    1800                 :            : static VALUE
    1801                 :         33 : ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
    1802                 :            : {
    1803                 :         33 :     return rb_ary_length(ary);
    1804                 :            : }
    1805                 :            : 
    1806                 :            : /*
    1807                 :            :  *  call-seq:
    1808                 :            :  *     ary.each {|item| block}    -> ary
    1809                 :            :  *     ary.each                   -> Enumerator
    1810                 :            :  *
    1811                 :            :  *  Calls the given block once for each element in +self+, passing that element
    1812                 :            :  *  as a parameter.  Returns the array itself.
    1813                 :            :  *
    1814                 :            :  *  If no block is given, an Enumerator is returned.
    1815                 :            :  *
    1816                 :            :  *     a = [ "a", "b", "c" ]
    1817                 :            :  *     a.each {|x| print x, " -- " }
    1818                 :            :  *
    1819                 :            :  *  produces:
    1820                 :            :  *
    1821                 :            :  *     a -- b -- c --
    1822                 :            :  */
    1823                 :            : 
    1824                 :            : VALUE
    1825                 :   14183295 : rb_ary_each(VALUE ary)
    1826                 :            : {
    1827                 :            :     long i;
    1828                 :            : 
    1829         [ +  + ]:   14183295 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    1830         [ +  + ]:  130105739 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    1831                 :   58239926 :         rb_yield(RARRAY_AREF(ary, i));
    1832                 :            :     }
    1833                 :            :     return ary;
    1834                 :            : }
    1835                 :            : 
    1836                 :            : /*
    1837                 :            :  *  call-seq:
    1838                 :            :  *     ary.each_index {|index| block}    -> ary
    1839                 :            :  *     ary.each_index                    -> Enumerator
    1840                 :            :  *
    1841                 :            :  *  Same as Array#each, but passes the +index+ of the element instead of the
    1842                 :            :  *  element itself.
    1843                 :            :  *
    1844                 :            :  *  An Enumerator is returned if no block is given.
    1845                 :            :  *
    1846                 :            :  *     a = [ "a", "b", "c" ]
    1847                 :            :  *     a.each_index {|x| print x, " -- " }
    1848                 :            :  *
    1849                 :            :  *  produces:
    1850                 :            :  *
    1851                 :            :  *     0 -- 1 -- 2 --
    1852                 :            :  */
    1853                 :            : 
    1854                 :            : static VALUE
    1855                 :      28865 : rb_ary_each_index(VALUE ary)
    1856                 :            : {
    1857                 :            :     long i;
    1858         [ +  + ]:      28865 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    1859                 :            : 
    1860         [ +  + ]:      97697 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    1861                 :      53061 :         rb_yield(LONG2NUM(i));
    1862                 :            :     }
    1863                 :            :     return ary;
    1864                 :            : }
    1865                 :            : 
    1866                 :            : /*
    1867                 :            :  *  call-seq:
    1868                 :            :  *     ary.reverse_each {|item| block}    -> ary
    1869                 :            :  *     ary.reverse_each                   -> Enumerator
    1870                 :            :  *
    1871                 :            :  *  Same as Array#each, but traverses +self+ in reverse order.
    1872                 :            :  *
    1873                 :            :  *     a = [ "a", "b", "c" ]
    1874                 :            :  *     a.reverse_each {|x| print x, " " }
    1875                 :            :  *
    1876                 :            :  *  produces:
    1877                 :            :  *
    1878                 :            :  *     c b a
    1879                 :            :  */
    1880                 :            : 
    1881                 :            : static VALUE
    1882                 :     667550 : rb_ary_reverse_each(VALUE ary)
    1883                 :            : {
    1884                 :            :     long len;
    1885                 :            : 
    1886         [ +  + ]:     667550 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    1887                 :     659916 :     len = RARRAY_LEN(ary);
    1888         [ +  + ]:    6845185 :     while (len--) {
    1889                 :            :         long nlen;
    1890                 :    6200428 :         rb_yield(RARRAY_AREF(ary, len));
    1891                 :    6185269 :         nlen = RARRAY_LEN(ary);
    1892         [ +  + ]:    6185269 :         if (nlen < len) {
    1893                 :    6185269 :             len = nlen;
    1894                 :            :         }
    1895                 :            :     }
    1896                 :            :     return ary;
    1897                 :            : }
    1898                 :            : 
    1899                 :            : /*
    1900                 :            :  *  call-seq:
    1901                 :            :  *     ary.length -> int
    1902                 :            :  *
    1903                 :            :  *  Returns the number of elements in +self+. May be zero.
    1904                 :            :  *
    1905                 :            :  *     [ 1, 2, 3, 4, 5 ].length   #=> 5
    1906                 :            :  *     [].length                  #=> 0
    1907                 :            :  */
    1908                 :            : 
    1909                 :            : static VALUE
    1910                 :       9283 : rb_ary_length(VALUE ary)
    1911                 :            : {
    1912                 :       9283 :     long len = RARRAY_LEN(ary);
    1913                 :       9283 :     return LONG2NUM(len);
    1914                 :            : }
    1915                 :            : 
    1916                 :            : /*
    1917                 :            :  *  call-seq:
    1918                 :            :  *     ary.empty?   -> true or false
    1919                 :            :  *
    1920                 :            :  *  Returns +true+ if +self+ contains no elements.
    1921                 :            :  *
    1922                 :            :  *     [].empty?   #=> true
    1923                 :            :  */
    1924                 :            : 
    1925                 :            : static VALUE
    1926                 :       2790 : rb_ary_empty_p(VALUE ary)
    1927                 :            : {
    1928         [ +  + ]:       2790 :     if (RARRAY_LEN(ary) == 0)
    1929                 :            :         return Qtrue;
    1930                 :       2671 :     return Qfalse;
    1931                 :            : }
    1932                 :            : 
    1933                 :            : VALUE
    1934                 :    7396918 : rb_ary_dup(VALUE ary)
    1935                 :            : {
    1936                 :    7396918 :     long len = RARRAY_LEN(ary);
    1937                 :    7396918 :     VALUE dup = rb_ary_new2(len);
    1938                 :    7396918 :     ary_memcpy(dup, 0, len, RARRAY_CONST_PTR(ary));
    1939 [ +  - ][ +  - ]:    7396918 :     ARY_SET_LEN(dup, len);
         [ +  - ][ +  + ]
                 [ +  + ]
    1940                 :    7396918 :     return dup;
    1941                 :            : }
    1942                 :            : 
    1943                 :            : VALUE
    1944                 :    1941280 : rb_ary_resurrect(VALUE ary)
    1945                 :            : {
    1946                 :    5823840 :     return rb_ary_new4(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
    1947                 :            : }
    1948                 :            : 
    1949                 :            : extern VALUE rb_output_fs;
    1950                 :            : 
    1951                 :            : static void ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first);
    1952                 :            : 
    1953                 :            : static VALUE
    1954                 :     482125 : recursive_join(VALUE obj, VALUE argp, int recur)
    1955                 :            : {
    1956                 :     482125 :     VALUE *arg = (VALUE *)argp;
    1957                 :     482125 :     VALUE ary = arg[0];
    1958                 :     482125 :     VALUE sep = arg[1];
    1959                 :     482125 :     VALUE result = arg[2];
    1960                 :     482125 :     int *first = (int *)arg[3];
    1961                 :            : 
    1962         [ +  + ]:     482125 :     if (recur) {
    1963                 :          1 :         rb_raise(rb_eArgError, "recursive array join");
    1964                 :            :     }
    1965                 :            :     else {
    1966                 :     482124 :         ary_join_1(obj, ary, sep, 0, result, first);
    1967                 :            :     }
    1968                 :     482123 :     return Qnil;
    1969                 :            : }
    1970                 :            : 
    1971                 :            : static void
    1972                 :     529904 : ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
    1973                 :            : {
    1974                 :            :     long i;
    1975                 :            :     VALUE val;
    1976                 :            : 
    1977         [ +  + ]:    1027674 :     if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
    1978         [ +  + ]:    5619374 :     for (i=0; i<max; i++) {
    1979                 :    5089471 :         val = RARRAY_AREF(ary, i);
    1980         [ +  + ]:    5089471 :         if (i > 0 && !NIL_P(sep))
    1981                 :    4309346 :             rb_str_buf_append(result, sep);
    1982                 :    5089471 :         rb_str_buf_append(result, val);
    1983 [ +  - ][ +  - ]:    5089470 :         if (OBJ_TAINTED(val)) OBJ_TAINT(result);
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1984                 :            :     }
    1985                 :     529903 : }
    1986                 :            : 
    1987                 :            : static void
    1988                 :    1151676 : ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
    1989                 :            : {
    1990                 :            :     VALUE val, tmp;
    1991                 :            : 
    1992         [ +  + ]:    3472886 :     for (; i<RARRAY_LEN(ary); i++) {
    1993         [ +  + ]:    1448531 :         if (i > 0 && !NIL_P(sep))
    1994                 :     922941 :             rb_str_buf_append(result, sep);
    1995                 :            : 
    1996                 :    1448531 :         val = RARRAY_AREF(ary, i);
    1997 [ +  + ][ +  + ]:    1448531 :         if (RB_TYPE_P(val, T_STRING)) {
                 [ +  + ]
    1998                 :            :           str_join:
    1999                 :     966401 :             rb_str_buf_append(result, val);
    2000         [ +  + ]:     966401 :             if (*first) {
    2001                 :       2291 :                 rb_enc_copy(result, val);
    2002                 :       2291 :                 *first = FALSE;
    2003                 :            :             }
    2004                 :            :         }
    2005 [ +  + ][ +  + ]:     678483 :         else if (RB_TYPE_P(val, T_ARRAY)) {
                 [ +  + ]
    2006                 :            :             obj = val;
    2007                 :            :           ary_join:
    2008         [ +  + ]:     482129 :             if (val == ary) {
    2009                 :          4 :                 rb_raise(rb_eArgError, "recursive array join");
    2010                 :            :             }
    2011                 :            :             else {
    2012                 :            :                 VALUE args[4];
    2013                 :            : 
    2014                 :     482125 :                 *first = FALSE;
    2015                 :     482125 :                 args[0] = val;
    2016                 :     482125 :                 args[1] = sep;
    2017                 :     482125 :                 args[2] = result;
    2018                 :     482125 :                 args[3] = (VALUE)first;
    2019                 :     482125 :                 rb_exec_recursive(recursive_join, obj, (VALUE)args);
    2020                 :            :             }
    2021                 :            :         }
    2022                 :            :         else {
    2023                 :     196357 :             tmp = rb_check_string_type(val);
    2024         [ +  + ]:     196357 :             if (!NIL_P(tmp)) {
    2025                 :            :                 val = tmp;
    2026                 :            :                 goto str_join;
    2027                 :            :             }
    2028                 :     196353 :             tmp = rb_check_array_type(val);
    2029         [ +  + ]:     196353 :             if (!NIL_P(tmp)) {
    2030                 :            :                 obj = val;
    2031                 :            :                 val = tmp;
    2032                 :            :                 goto ary_join;
    2033                 :            :             }
    2034                 :     196350 :             val = rb_obj_as_string(val);
    2035                 :            :             goto str_join;
    2036                 :            :         }
    2037                 :            :     }
    2038                 :     575831 : }
    2039                 :            : 
    2040                 :            : VALUE
    2041                 :     552284 : rb_ary_join(VALUE ary, VALUE sep)
    2042                 :            : {
    2043                 :     552284 :     long len = 1, i;
    2044                 :     552284 :     int taint = FALSE;
    2045                 :            :     VALUE val, tmp, result;
    2046                 :            : 
    2047         [ +  + ]:     552284 :     if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new(0, 0);
    2048 [ +  - ][ +  - ]:     529906 :     if (OBJ_TAINTED(ary)) taint = TRUE;
         [ +  - ][ +  + ]
    2049                 :            : 
    2050         [ +  + ]:     529906 :     if (!NIL_P(sep)) {
    2051                 :     477703 :         StringValue(sep);
    2052         [ +  + ]:    1007605 :         len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
    2053                 :            :     }
    2054         [ +  + ]:   10708846 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    2055                 :    5183185 :         val = RARRAY_AREF(ary, i);
    2056                 :    5183185 :         tmp = rb_check_string_type(val);
    2057                 :            : 
    2058         [ +  + ]:    5183185 :         if (NIL_P(tmp) || tmp != val) {
    2059                 :            :             int first;
    2060                 :      93714 :             result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10);
    2061                 :      93714 :             rb_enc_associate(result, rb_usascii_encoding());
    2062 [ +  + ][ +  - ]:      93714 :             if (taint) OBJ_TAINT(result);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2063                 :      93714 :             ary_join_0(ary, sep, i, result);
    2064                 :      93714 :             first = i == 0;
    2065                 :      93714 :             ary_join_1(ary, ary, sep, i, result, &first);
    2066                 :            :             return result;
    2067                 :            :         }
    2068                 :            : 
    2069         [ +  + ]:    5089471 :         len += RSTRING_LEN(tmp);
    2070                 :            :     }
    2071                 :            : 
    2072                 :     436190 :     result = rb_str_buf_new(len);
    2073 [ -  + ][ #  # ]:     436190 :     if (taint) OBJ_TAINT(result);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2074                 :     436190 :     ary_join_0(ary, sep, RARRAY_LEN(ary), result);
    2075                 :            : 
    2076                 :     436189 :     return result;
    2077                 :            : }
    2078                 :            : 
    2079                 :            : /*
    2080                 :            :  *  call-seq:
    2081                 :            :  *     ary.join(separator=$,)    -> str
    2082                 :            :  *
    2083                 :            :  *  Returns a string created by converting each element of the array to
    2084                 :            :  *  a string, separated by the given +separator+.
    2085                 :            :  *  If the +separator+ is +nil+, it uses current <code>$,</code>.
    2086                 :            :  *  If both the +separator+ and <code>$,</code> are +nil+,
    2087                 :            :  *  it uses an empty string.
    2088                 :            :  *
    2089                 :            :  *     [ "a", "b", "c" ].join        #=> "abc"
    2090                 :            :  *     [ "a", "b", "c" ].join("-")   #=> "a-b-c"
    2091                 :            :  *
    2092                 :            :  *  For nested arrays, join is applied recursively:
    2093                 :            :  *
    2094                 :            :  *     [ "a", [1, 2, [:x, :y]], "b" ].join("-")   #=> "a-1-2-x-y-b"
    2095                 :            :  */
    2096                 :            : 
    2097                 :            : static VALUE
    2098                 :     552241 : rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
    2099                 :            : {
    2100                 :            :     VALUE sep;
    2101                 :            : 
    2102                 :    3865687 :     rb_scan_args(argc, argv, "01", &sep);
    2103         [ +  + ]:     552241 :     if (NIL_P(sep)) sep = rb_output_fs;
    2104                 :            : 
    2105                 :     552241 :     return rb_ary_join(ary, sep);
    2106                 :            : }
    2107                 :            : 
    2108                 :            : static VALUE
    2109                 :    1683884 : inspect_ary(VALUE ary, VALUE dummy, int recur)
    2110                 :            : {
    2111 [ +  - ][ +  - ]:    1683884 :     int tainted = OBJ_TAINTED(ary);
         [ +  - ][ +  + ]
    2112                 :            :     long i;
    2113                 :            :     VALUE s, str;
    2114                 :            : 
    2115         [ +  + ]:    1683884 :     if (recur) return rb_usascii_str_new_cstr("[...]");
    2116                 :    1683854 :     str = rb_str_buf_new2("[");
    2117         [ +  + ]:   10997140 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    2118                 :    3814718 :         s = rb_inspect(RARRAY_AREF(ary, i));
    2119 [ +  - ][ +  - ]:    3814716 :         if (OBJ_TAINTED(s)) tainted = TRUE;
         [ +  - ][ +  + ]
    2120         [ +  + ]:    3814716 :         if (i > 0) rb_str_buf_cat2(str, ", ");
    2121                 :    1683852 :         else rb_enc_copy(str, s);
    2122                 :    3814716 :         rb_str_buf_append(str, s);
    2123                 :            :     }
    2124                 :    1683852 :     rb_str_buf_cat2(str, "]");
    2125 [ +  + ][ +  - ]:    1683852 :     if (tainted) OBJ_TAINT(str);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2126                 :    1683852 :     return str;
    2127                 :            : }
    2128                 :            : 
    2129                 :            : /*
    2130                 :            :  *  call-seq:
    2131                 :            :  *     ary.inspect  -> string
    2132                 :            :  *     ary.to_s     -> string
    2133                 :            :  *
    2134                 :            :  *  Creates a string representation of +self+.
    2135                 :            :  *
    2136                 :            :  *     [ "a", "b", "c" ].to_s     #=> "[\"a\", \"b\", \"c\"]"
    2137                 :            :  */
    2138                 :            : 
    2139                 :            : static VALUE
    2140                 :    1696337 : rb_ary_inspect(VALUE ary)
    2141                 :            : {
    2142         [ +  + ]:    1696337 :     if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]");
    2143                 :    1683884 :     return rb_exec_recursive(inspect_ary, ary, 0);
    2144                 :            : }
    2145                 :            : 
    2146                 :            : VALUE
    2147                 :          2 : rb_ary_to_s(VALUE ary)
    2148                 :            : {
    2149                 :          2 :     return rb_ary_inspect(ary);
    2150                 :            : }
    2151                 :            : 
    2152                 :            : /*
    2153                 :            :  *  call-seq:
    2154                 :            :  *     ary.to_a     -> ary
    2155                 :            :  *
    2156                 :            :  *  Returns +self+.
    2157                 :            :  *
    2158                 :            :  *  If called on a subclass of Array, converts the receiver to an Array object.
    2159                 :            :  */
    2160                 :            : 
    2161                 :            : static VALUE
    2162                 :     101918 : rb_ary_to_a(VALUE ary)
    2163                 :            : {
    2164         [ +  + ]:     101918 :     if (rb_obj_class(ary) != rb_cArray) {
    2165                 :          8 :         VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
    2166                 :          4 :         rb_ary_replace(dup, ary);
    2167                 :          4 :         return dup;
    2168                 :            :     }
    2169                 :            :     return ary;
    2170                 :            : }
    2171                 :            : 
    2172                 :            : /*
    2173                 :            :  *  call-seq:
    2174                 :            :  *     ary.to_h            -> hash
    2175                 :            :  *     ary.to_h { block }  -> hash
    2176                 :            :  *
    2177                 :            :  *  Returns the result of interpreting <i>ary</i> as an array of
    2178                 :            :  *  <tt>[key, value]</tt> pairs.
    2179                 :            :  *
    2180                 :            :  *     [[:foo, :bar], [1, 2]].to_h
    2181                 :            :  *       # => {:foo => :bar, 1 => 2}
    2182                 :            :  *
    2183                 :            :  *  If a block is given, the results of the block on each element of
    2184                 :            :  *  the array will be used as pairs.
    2185                 :            :  *
    2186                 :            :  *     ["foo", "bar"].to_h {|s| [s.ord, s]}
    2187                 :            :  *       # => {102=>"foo", 98=>"bar"}
    2188                 :            :  */
    2189                 :            : 
    2190                 :            : static VALUE
    2191                 :         17 : rb_ary_to_h(VALUE ary)
    2192                 :            : {
    2193                 :            :     long i;
    2194                 :         17 :     VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
    2195                 :         17 :     int block_given = rb_block_given_p();
    2196                 :            : 
    2197         [ +  + ]:        134 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    2198                 :         58 :         const VALUE e = rb_ary_elt(ary, i);
    2199         [ +  + ]:         58 :         const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
    2200                 :         58 :         const VALUE key_value_pair = rb_check_array_type(elt);
    2201         [ +  + ]:         58 :         if (NIL_P(key_value_pair)) {
    2202                 :          5 :             rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)",
    2203                 :            :                      rb_obj_class(elt), i);
    2204                 :            :         }
    2205         [ +  + ]:         53 :         if (RARRAY_LEN(key_value_pair) != 2) {
    2206                 :          3 :             rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)",
    2207                 :            :                 i, RARRAY_LEN(key_value_pair));
    2208                 :            :         }
    2209                 :         50 :         rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1));
    2210                 :            :     }
    2211                 :          9 :     return hash;
    2212                 :            : }
    2213                 :            : 
    2214                 :            : /*
    2215                 :            :  *  call-seq:
    2216                 :            :  *     ary.to_ary -> ary
    2217                 :            :  *
    2218                 :            :  *  Returns +self+.
    2219                 :            :  */
    2220                 :            : 
    2221                 :            : static VALUE
    2222                 :        102 : rb_ary_to_ary_m(VALUE ary)
    2223                 :            : {
    2224                 :        102 :     return ary;
    2225                 :            : }
    2226                 :            : 
    2227                 :            : static void
    2228                 :            : ary_reverse(VALUE *p1, VALUE *p2)
    2229                 :            : {
    2230 [ +  + ][ +  + ]:     411686 :     while (p1 < p2) {
         [ +  + ][ +  + ]
    2231                 :     388193 :         VALUE tmp = *p1;
    2232                 :     388193 :         *p1++ = *p2;
    2233                 :     388193 :         *p2-- = tmp;
    2234                 :            :     }
    2235                 :            : }
    2236                 :            : 
    2237                 :            : VALUE
    2238                 :      27153 : rb_ary_reverse(VALUE ary)
    2239                 :            : {
    2240                 :            :     VALUE *p2;
    2241                 :      27153 :     long len = RARRAY_LEN(ary);
    2242                 :            : 
    2243                 :      27153 :     rb_ary_modify(ary);
    2244         [ +  + ]:      27152 :     if (len > 1) {
    2245                 :      23460 :         RARRAY_PTR_USE(ary, p1, {
    2246                 :            :             p2 = p1 + len - 1;  /* points last item */
    2247                 :            :             ary_reverse(p1, p2);
    2248                 :            :         }); /* WB: no new reference */
    2249                 :            :     }
    2250                 :      27152 :     return ary;
    2251                 :            : }
    2252                 :            : 
    2253                 :            : /*
    2254                 :            :  *  call-seq:
    2255                 :            :  *     ary.reverse!   -> ary
    2256                 :            :  *
    2257                 :            :  *  Reverses +self+ in place.
    2258                 :            :  *
    2259                 :            :  *     a = [ "a", "b", "c" ]
    2260                 :            :  *     a.reverse!       #=> ["c", "b", "a"]
    2261                 :            :  *     a                #=> ["c", "b", "a"]
    2262                 :            :  */
    2263                 :            : 
    2264                 :            : static VALUE
    2265                 :      27133 : rb_ary_reverse_bang(VALUE ary)
    2266                 :            : {
    2267                 :      27133 :     return rb_ary_reverse(ary);
    2268                 :            : }
    2269                 :            : 
    2270                 :            : /*
    2271                 :            :  *  call-seq:
    2272                 :            :  *     ary.reverse    -> new_ary
    2273                 :            :  *
    2274                 :            :  *  Returns a new array containing +self+'s elements in reverse order.
    2275                 :            :  *
    2276                 :            :  *     [ "a", "b", "c" ].reverse   #=> ["c", "b", "a"]
    2277                 :            :  *     [ 1 ].reverse               #=> [1]
    2278                 :            :  */
    2279                 :            : 
    2280                 :            : static VALUE
    2281                 :      29566 : rb_ary_reverse_m(VALUE ary)
    2282                 :            : {
    2283                 :      29566 :     long len = RARRAY_LEN(ary);
    2284                 :      29566 :     VALUE dup = rb_ary_new2(len);
    2285                 :            : 
    2286         [ +  + ]:      29566 :     if (len > 0) {
    2287                 :      14166 :         const VALUE *p1 = RARRAY_CONST_PTR(ary);
    2288                 :      14166 :         VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1;
    2289         [ +  + ]:     714231 :         do *p2-- = *p1++; while (--len > 0);
    2290                 :            :     }
    2291 [ +  - ][ +  - ]:      59132 :     ARY_SET_LEN(dup, RARRAY_LEN(ary));
         [ +  - ][ +  + ]
                 [ +  + ]
    2292                 :      29566 :     return dup;
    2293                 :            : }
    2294                 :            : 
    2295                 :            : static inline long
    2296                 :            : rotate_count(long cnt, long len)
    2297                 :            : {
    2298 [ +  + ][ +  + ]:         52 :     return (cnt < 0) ? (len - (~cnt % len) - 1) : (cnt % len);
    2299                 :            : }
    2300                 :            : 
    2301                 :            : VALUE
    2302                 :         34 : rb_ary_rotate(VALUE ary, long cnt)
    2303                 :            : {
    2304                 :         34 :     rb_ary_modify(ary);
    2305                 :            : 
    2306         [ +  - ]:         29 :     if (cnt != 0) {
    2307                 :         87 :         VALUE *ptr = RARRAY_PTR(ary);
    2308                 :         29 :         long len = RARRAY_LEN(ary);
    2309                 :            : 
    2310 [ +  + ][ +  + ]:         50 :         if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
    2311                 :         13 :             --len;
    2312         [ +  + ]:         13 :             if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
    2313         [ +  + ]:         13 :             if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
    2314         [ +  - ]:         13 :             if (len > 0) ary_reverse(ptr, ptr + len);
    2315                 :         13 :             return ary;
    2316                 :            :         }
    2317                 :            :     }
    2318                 :            : 
    2319                 :            :     return Qnil;
    2320                 :            : }
    2321                 :            : 
    2322                 :            : /*
    2323                 :            :  *  call-seq:
    2324                 :            :  *     ary.rotate!(count=1)   -> ary
    2325                 :            :  *
    2326                 :            :  *  Rotates +self+ in place so that the element at +count+ comes first, and
    2327                 :            :  *  returns +self+.
    2328                 :            :  *
    2329                 :            :  *  If +count+ is negative then it rotates in the opposite direction, starting
    2330                 :            :  *  from the end of the array where +-1+ is the last element.
    2331                 :            :  *
    2332                 :            :  *     a = [ "a", "b", "c", "d" ]
    2333                 :            :  *     a.rotate!        #=> ["b", "c", "d", "a"]
    2334                 :            :  *     a                #=> ["b", "c", "d", "a"]
    2335                 :            :  *     a.rotate!(2)     #=> ["d", "a", "b", "c"]
    2336                 :            :  *     a.rotate!(-3)    #=> ["a", "b", "c", "d"]
    2337                 :            :  */
    2338                 :            : 
    2339                 :            : static VALUE
    2340                 :         34 : rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
    2341                 :            : {
    2342                 :         34 :     long n = 1;
    2343                 :            : 
    2344      [ +  +  + ]:         34 :     switch (argc) {
    2345                 :         23 :       case 1: n = NUM2LONG(argv[0]);
    2346                 :            :       case 0: break;
    2347                 :          7 :       default: rb_scan_args(argc, argv, "01", NULL);
    2348                 :            :     }
    2349                 :         31 :     rb_ary_rotate(ary, n);
    2350                 :         27 :     return ary;
    2351                 :            : }
    2352                 :            : 
    2353                 :            : /*
    2354                 :            :  *  call-seq:
    2355                 :            :  *     ary.rotate(count=1)    -> new_ary
    2356                 :            :  *
    2357                 :            :  *  Returns a new array by rotating +self+ so that the element at +count+ is
    2358                 :            :  *  the first element of the new array.
    2359                 :            :  *
    2360                 :            :  *  If +count+ is negative then it rotates in the opposite direction, starting
    2361                 :            :  *  from the end of +self+ where +-1+ is the last element.
    2362                 :            :  *
    2363                 :            :  *     a = [ "a", "b", "c", "d" ]
    2364                 :            :  *     a.rotate         #=> ["b", "c", "d", "a"]
    2365                 :            :  *     a                #=> ["a", "b", "c", "d"]
    2366                 :            :  *     a.rotate(2)      #=> ["c", "d", "a", "b"]
    2367                 :            :  *     a.rotate(-3)     #=> ["b", "c", "d", "a"]
    2368                 :            :  */
    2369                 :            : 
    2370                 :            : static VALUE
    2371                 :         44 : rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
    2372                 :            : {
    2373                 :            :     VALUE rotated;
    2374                 :            :     const VALUE *ptr;
    2375                 :         44 :     long len, cnt = 1;
    2376                 :            : 
    2377      [ +  +  + ]:         44 :     switch (argc) {
    2378                 :         31 :       case 1: cnt = NUM2LONG(argv[0]);
    2379                 :            :       case 0: break;
    2380                 :          7 :       default: rb_scan_args(argc, argv, "01", NULL);
    2381                 :            :     }
    2382                 :            : 
    2383                 :         41 :     len = RARRAY_LEN(ary);
    2384                 :         41 :     rotated = rb_ary_new2(len);
    2385         [ +  + ]:         41 :     if (len > 0) {
    2386                 :         31 :         cnt = rotate_count(cnt, len);
    2387                 :         31 :         ptr = RARRAY_CONST_PTR(ary);
    2388                 :         31 :         len -= cnt;
    2389                 :         31 :         ary_memcpy(rotated, 0, len, ptr + cnt);
    2390                 :            :         ary_memcpy(rotated, len, cnt, ptr);
    2391                 :            :     }
    2392 [ +  - ][ +  - ]:         82 :     ARY_SET_LEN(rotated, RARRAY_LEN(ary));
         [ +  - ][ +  + ]
                 [ +  + ]
    2393                 :         41 :     return rotated;
    2394                 :            : }
    2395                 :            : 
    2396                 :            : struct ary_sort_data {
    2397                 :            :     VALUE ary;
    2398                 :            :     struct cmp_opt_data cmp_opt;
    2399                 :            : };
    2400                 :            : 
    2401                 :            : static VALUE
    2402                 :            : sort_reentered(VALUE ary)
    2403                 :            : {
    2404   [ -  +  -  + ]:    7995939 :     if (RBASIC(ary)->klass) {
           [ -  +  +  + ]
    2405                 :        999 :         rb_raise(rb_eRuntimeError, "sort reentered");
    2406                 :            :     }
    2407                 :            :     return Qnil;
    2408                 :            : }
    2409                 :            : 
    2410                 :            : static int
    2411                 :      51488 : sort_1(const void *ap, const void *bp, void *dummy)
    2412                 :            : {
    2413                 :      51488 :     struct ary_sort_data *data = dummy;
    2414                 :     102976 :     VALUE retval = sort_reentered(data->ary);
    2415                 :      51488 :     VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
    2416                 :            :     VALUE args[2];
    2417                 :            :     int n;
    2418                 :            : 
    2419                 :      51488 :     args[0] = a;
    2420                 :      51488 :     args[1] = b;
    2421                 :      51488 :     retval = rb_yield_values2(2, args);
    2422                 :      52481 :     n = rb_cmpint(retval, a, b);
    2423                 :      52478 :     sort_reentered(data->ary);
    2424                 :      51479 :     return n;
    2425                 :            : }
    2426                 :            : 
    2427                 :            : static int
    2428                 :    7771487 : sort_2(const void *ap, const void *bp, void *dummy)
    2429                 :            : {
    2430                 :    7771487 :     struct ary_sort_data *data = dummy;
    2431                 :   15542974 :     VALUE retval = sort_reentered(data->ary);
    2432                 :    7771487 :     VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
    2433                 :            :     int n;
    2434                 :            : 
    2435 [ +  + ][ +  - ]:    7771487 :     if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, Fixnum)) {
         [ +  + ][ +  + ]
                 [ +  + ]
    2436         [ +  + ]:     845561 :         if ((long)a > (long)b) return 1;
    2437         [ +  + ]:     817006 :         if ((long)a < (long)b) return -1;
    2438                 :      66619 :         return 0;
    2439                 :            :     }
    2440 [ +  + ][ +  - ]:    6925926 :     if (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, String)) {
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
                 [ +  - ]
    2441                 :    6805432 :         return rb_str_cmp(a, b);
    2442                 :            :     }
    2443 [ +  + ][ +  + ]:     120494 :     if (RB_FLOAT_TYPE_P(a) && CMP_OPTIMIZABLE(data->cmp_opt, Float)) {
         [ +  - ][ -  + ]
         [ -  + ][ +  - ]
                 [ +  - ]
    2444                 :          2 :         return rb_float_cmp(a, b);
    2445                 :            :     }
    2446                 :            : 
    2447                 :     120492 :     retval = rb_funcallv(a, id_cmp, 1, &b);
    2448                 :     120491 :     n = rb_cmpint(retval, a, b);
    2449                 :     120486 :     sort_reentered(data->ary);
    2450                 :            : 
    2451                 :            :     return n;
    2452                 :            : }
    2453                 :            : 
    2454                 :            : /*
    2455                 :            :  *  call-seq:
    2456                 :            :  *     ary.sort!                   -> ary
    2457                 :            :  *     ary.sort! {|a, b| block}    -> ary
    2458                 :            :  *
    2459                 :            :  *  Sorts +self+ in place.
    2460                 :            :  *
    2461                 :            :  *  Comparisons for the sort will be done using the <code><=></code> operator
    2462                 :            :  *  or using an optional code block.
    2463                 :            :  *
    2464                 :            :  *  The block must implement a comparison between +a+ and +b+ and return
    2465                 :            :  *  an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+
    2466                 :            :  *  are equivalent, or an integer greater than 0 when +a+ follows +b+.
    2467                 :            :  *
    2468                 :            :  *  The result is not guaranteed to be stable.  When the comparison of two
    2469                 :            :  *  elements returns +0+, the order of the elements is unpredictable.
    2470                 :            :  *
    2471                 :            :  *     ary = [ "d", "a", "e", "c", "b" ]
    2472                 :            :  *     ary.sort!                     #=> ["a", "b", "c", "d", "e"]
    2473                 :            :  *     ary.sort! {|a, b| b <=> a}    #=> ["e", "d", "c", "b", "a"]
    2474                 :            :  *
    2475                 :            :  *  See also Enumerable#sort_by.
    2476                 :            :  */
    2477                 :            : 
    2478                 :            : VALUE
    2479                 :     387122 : rb_ary_sort_bang(VALUE ary)
    2480                 :            : {
    2481                 :     387122 :     rb_ary_modify(ary);
    2482                 :            :     assert(!ARY_SHARED_P(ary));
    2483         [ +  + ]:     387121 :     if (RARRAY_LEN(ary) > 1) {
    2484                 :     153218 :         VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
    2485                 :            :         struct ary_sort_data data;
    2486                 :     153218 :         long len = RARRAY_LEN(ary);
    2487                 :            : 
    2488                 :     153218 :         RBASIC_CLEAR_CLASS(tmp);
    2489                 :     153218 :         data.ary = tmp;
    2490                 :     153218 :         data.cmp_opt.opt_methods = 0;
    2491                 :     153218 :         data.cmp_opt.opt_inited = 0;
    2492         [ +  + ]:     153218 :         RARRAY_PTR_USE(tmp, ptr, {
    2493                 :            :             ruby_qsort(ptr, len, sizeof(VALUE),
    2494                 :            :                        rb_block_given_p()?sort_1:sort_2, &data);
    2495                 :            :         }); /* WB: no new reference */
    2496                 :     153203 :         rb_ary_modify(ary);
    2497 [ +  - ][ +  - ]:     153202 :         if (ARY_EMBED_P(tmp)) {
         [ +  - ][ +  + ]
                 [ +  + ]
    2498 [ +  - ][ +  - ]:      38287 :             if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
         [ +  - ][ +  - ]
                 [ -  + ]
    2499                 :          0 :                 rb_ary_unshare(ary);
    2500 [ #  # ][ #  # ]:          0 :                 FL_SET_EMBED(ary);
                 [ #  # ]
    2501                 :            :             }
    2502                 :      38287 :             ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
    2503 [ +  - ][ +  - ]:      38287 :             ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
         [ +  - ][ -  + ]
                 [ +  - ]
    2504                 :            :         }
    2505                 :            :         else {
    2506 [ +  - ][ +  - ]:     114915 :             if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
         [ +  - ][ +  + ]
         [ +  + ][ -  + ]
    2507 [ #  # ][ #  # ]:          0 :                 FL_UNSET_SHARED(ary);
                 [ #  # ]
    2508                 :          0 :                 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
    2509                 :            :             }
    2510                 :            :             else {
    2511                 :            :                 assert(!ARY_SHARED_P(tmp));
    2512 [ +  - ][ +  - ]:     114915 :                 if (ARY_EMBED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
    2513 [ +  - ][ +  - ]:          1 :                     FL_UNSET_EMBED(ary);
                 [ +  - ]
    2514                 :            :                 }
    2515 [ +  - ][ +  - ]:     114914 :                 else if (ARY_SHARED_P(ary)) {
         [ +  - ][ +  - ]
                 [ -  + ]
    2516                 :            :                     /* ary might be destructively operated in the given block */
    2517                 :          0 :                     rb_ary_unshare(ary);
    2518                 :            :                 }
    2519                 :            :                 else {
    2520                 :     114914 :                     ruby_sized_xfree((void *)ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary));
    2521                 :            :                 }
    2522                 :     229830 :                 ARY_SET_PTR(ary, RARRAY_CONST_PTR(tmp));
    2523                 :     114915 :                 ARY_SET_HEAP_LEN(ary, len);
    2524                 :     114915 :                 ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
    2525                 :            :             }
    2526                 :            :             /* tmp was lost ownership for the ptr */
    2527 [ +  - ][ +  - ]:     114915 :             FL_UNSET(tmp, FL_FREEZE);
                 [ +  - ]
    2528 [ +  - ][ +  - ]:     114915 :             FL_SET_EMBED(tmp);
                 [ +  - ]
    2529                 :     114915 :             ARY_SET_EMBED_LEN(tmp, 0);
    2530 [ +  - ][ +  - ]:     114915 :             FL_SET(tmp, FL_FREEZE);
                 [ +  - ]
    2531                 :            :         }
    2532                 :            :         /* tmp will be GC'ed. */
    2533                 :     153202 :         RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
    2534                 :            :     }
    2535                 :     387105 :     return ary;
    2536                 :            : }
    2537                 :            : 
    2538                 :            : /*
    2539                 :            :  *  call-seq:
    2540                 :            :  *     ary.sort                   -> new_ary
    2541                 :            :  *     ary.sort {|a, b| block}    -> new_ary
    2542                 :            :  *
    2543                 :            :  *  Returns a new array created by sorting +self+.
    2544                 :            :  *
    2545                 :            :  *  Comparisons for the sort will be done using the <code><=></code> operator
    2546                 :            :  *  or using an optional code block.
    2547                 :            :  *
    2548                 :            :  *  The block must implement a comparison between +a+ and +b+ and return
    2549                 :            :  *  an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+
    2550                 :            :  *  are equivalent, or an integer greater than 0 when +a+ follows +b+.
    2551                 :            :  *
    2552                 :            :  *  The result is not guaranteed to be stable.  When the comparison of two
    2553                 :            :  *  elements returns +0+, the order of the elements is unpredictable.
    2554                 :            :  *
    2555                 :            :  *     ary = [ "d", "a", "e", "c", "b" ]
    2556                 :            :  *     ary.sort                     #=> ["a", "b", "c", "d", "e"]
    2557                 :            :  *     ary.sort {|a, b| b <=> a}    #=> ["e", "d", "c", "b", "a"]
    2558                 :            :  *
    2559                 :            :  *  See also Enumerable#sort_by.
    2560                 :            :  */
    2561                 :            : 
    2562                 :            : VALUE
    2563                 :     178000 : rb_ary_sort(VALUE ary)
    2564                 :            : {
    2565                 :     178000 :     ary = rb_ary_dup(ary);
    2566                 :     178000 :     rb_ary_sort_bang(ary);
    2567                 :     177994 :     return ary;
    2568                 :            : }
    2569                 :            : 
    2570                 :            : static VALUE rb_ary_bsearch_index(VALUE ary);
    2571                 :            : 
    2572                 :            : /*
    2573                 :            :  *  call-seq:
    2574                 :            :  *     ary.bsearch {|x| block }  -> elem
    2575                 :            :  *
    2576                 :            :  *  By using binary search, finds a value from this array which meets
    2577                 :            :  *  the given condition in O(log n) where n is the size of the array.
    2578                 :            :  *
    2579                 :            :  *  You can use this method in two modes: a find-minimum mode and
    2580                 :            :  *  a find-any mode.  In either case, the elements of the array must be
    2581                 :            :  *  monotone (or sorted) with respect to the block.
    2582                 :            :  *
    2583                 :            :  *  In find-minimum mode (this is a good choice for typical use cases),
    2584                 :            :  *  the block must always return true or false, and there must be an index i
    2585                 :            :  *  (0 <= i <= ary.size) so that:
    2586                 :            :  *
    2587                 :            :  *  - the block returns false for any element whose index is less than
    2588                 :            :  *    i, and
    2589                 :            :  *  - the block returns true for any element whose index is greater
    2590                 :            :  *    than or equal to i.
    2591                 :            :  *
    2592                 :            :  *  This method returns the i-th element.  If i is equal to ary.size,
    2593                 :            :  *  it returns nil.
    2594                 :            :  *
    2595                 :            :  *     ary = [0, 4, 7, 10, 12]
    2596                 :            :  *     ary.bsearch {|x| x >=   4 } #=> 4
    2597                 :            :  *     ary.bsearch {|x| x >=   6 } #=> 7
    2598                 :            :  *     ary.bsearch {|x| x >=  -1 } #=> 0
    2599                 :            :  *     ary.bsearch {|x| x >= 100 } #=> nil
    2600                 :            :  *
    2601                 :            :  *  In find-any mode (this behaves like libc's bsearch(3)), the block
    2602                 :            :  *  must always return a number, and there must be two indices i and j
    2603                 :            :  *  (0 <= i <= j <= ary.size) so that:
    2604                 :            :  *
    2605                 :            :  *  - the block returns a positive number for ary[k] if 0 <= k < i,
    2606                 :            :  *  - the block returns zero for ary[k] if i <= k < j, and
    2607                 :            :  *  - the block returns a negative number for ary[k] if
    2608                 :            :  *    j <= k < ary.size.
    2609                 :            :  *
    2610                 :            :  *  Under this condition, this method returns any element whose index
    2611                 :            :  *  is within i...j.  If i is equal to j (i.e., there is no element
    2612                 :            :  *  that satisfies the block), this method returns nil.
    2613                 :            :  *
    2614                 :            :  *     ary = [0, 4, 7, 10, 12]
    2615                 :            :  *     # try to find v such that 4 <= v < 8
    2616                 :            :  *     ary.bsearch {|x| 1 - x / 4 } #=> 4 or 7
    2617                 :            :  *     # try to find v such that 8 <= v < 10
    2618                 :            :  *     ary.bsearch {|x| 4 - x / 2 } #=> nil
    2619                 :            :  *
    2620                 :            :  *  You must not mix the two modes at a time; the block must always
    2621                 :            :  *  return either true/false, or always return a number.  It is
    2622                 :            :  *  undefined which value is actually picked up at each iteration.
    2623                 :            :  */
    2624                 :            : 
    2625                 :            : static VALUE
    2626                 :         40 : rb_ary_bsearch(VALUE ary)
    2627                 :            : {
    2628                 :         40 :     VALUE index_result = rb_ary_bsearch_index(ary);
    2629                 :            : 
    2630         [ +  + ]:         31 :     if (FIXNUM_P(index_result)) {
    2631                 :         12 :         return rb_ary_entry(ary, FIX2LONG(index_result));
    2632                 :            :     }
    2633                 :            :     return index_result;
    2634                 :            : }
    2635                 :            : 
    2636                 :            : /*
    2637                 :            :  *  call-seq:
    2638                 :            :  *     ary.bsearch_index {|x| block }  -> int or nil
    2639                 :            :  *
    2640                 :            :  *  By using binary search, finds an index of a value from this array which
    2641                 :            :  *  meets the given condition in O(log n) where n is the size of the array.
    2642                 :            :  *
    2643                 :            :  *  It supports two modes, depending on the nature of the block. They are
    2644                 :            :  *  exactly the same as in the case of the #bsearch method, with the only difference
    2645                 :            :  *  being that this method returns the index of the element instead of the
    2646                 :            :  *  element itself. For more details consult the documentation for #bsearch.
    2647                 :            :  */
    2648                 :            : 
    2649                 :            : static VALUE
    2650                 :         77 : rb_ary_bsearch_index(VALUE ary)
    2651                 :            : {
    2652                 :        154 :     long low = 0, high = RARRAY_LEN(ary), mid;
    2653                 :         77 :     int smaller = 0, satisfied = 0;
    2654                 :            :     VALUE v, val;
    2655                 :            : 
    2656         [ +  + ]:         77 :     RETURN_ENUMERATOR(ary, 0, 0);
    2657         [ +  + ]:        180 :     while (low < high) {
    2658                 :        134 :         mid = low + ((high - low) / 2);
    2659                 :        134 :         val = rb_ary_entry(ary, mid);
    2660                 :        134 :         v = rb_yield(val);
    2661         [ +  + ]:        129 :         if (FIXNUM_P(v)) {
    2662         [ +  + ]:         42 :             if (v == INT2FIX(0)) return INT2FIX(mid);
    2663                 :         31 :             smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */
    2664                 :            :         }
    2665         [ +  + ]:         87 :         else if (v == Qtrue) {
    2666                 :            :             satisfied = 1;
    2667                 :            :             smaller = 1;
    2668                 :            :         }
    2669         [ +  + ]:         60 :         else if (v == Qfalse || v == Qnil) {
    2670                 :            :             smaller = 0;
    2671                 :            :         }
    2672         [ +  + ]:         27 :         else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
    2673                 :         21 :             const VALUE zero = INT2FIX(0);
    2674   [ +  +  +  - ]:         21 :             switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) {
    2675                 :          1 :               case 0: return INT2FIX(mid);
    2676                 :         12 :               case 1: smaller = 1; break;
    2677                 :         20 :               case -1: smaller = 0;
    2678                 :            :             }
    2679                 :            :         }
    2680                 :            :         else {
    2681                 :          6 :             rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE
    2682                 :            :                      " (must be numeric, true, false or nil)",
    2683                 :            :                      rb_obj_class(v));
    2684                 :            :         }
    2685         [ +  + ]:        111 :         if (smaller) {
    2686                 :            :             high = mid;
    2687                 :            :         }
    2688                 :            :         else {
    2689                 :        111 :             low = mid + 1;
    2690                 :            :         }
    2691                 :            :     }
    2692         [ +  + ]:         46 :     if (!satisfied) return Qnil;
    2693                 :         15 :     return INT2FIX(low);
    2694                 :            : }
    2695                 :            : 
    2696                 :            : 
    2697                 :            : static VALUE
    2698                 :         62 : sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
    2699                 :            : {
    2700                 :         62 :     return rb_yield(i);
    2701                 :            : }
    2702                 :            : 
    2703                 :            : /*
    2704                 :            :  *  call-seq:
    2705                 :            :  *     ary.sort_by! {|obj| block}      -> ary
    2706                 :            :  *     ary.sort_by!                    -> Enumerator
    2707                 :            :  *
    2708                 :            :  *  Sorts +self+ in place using a set of keys generated by mapping the
    2709                 :            :  *  values in +self+ through the given block.
    2710                 :            :  *
    2711                 :            :  *  The result is not guaranteed to be stable.  When two keys are equal,
    2712                 :            :  *  the order of the corresponding elements is unpredictable.
    2713                 :            :  *
    2714                 :            :  *  If no block is given, an Enumerator is returned instead.
    2715                 :            :  *
    2716                 :            :  *  See also Enumerable#sort_by.
    2717                 :            :  */
    2718                 :            : 
    2719                 :            : static VALUE
    2720                 :        135 : rb_ary_sort_by_bang(VALUE ary)
    2721                 :            : {
    2722                 :            :     VALUE sorted;
    2723                 :            : 
    2724         [ +  + ]:        135 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    2725                 :        132 :     rb_ary_modify(ary);
    2726         [ +  + ]:        130 :     sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
    2727                 :        124 :     rb_ary_replace(ary, sorted);
    2728                 :        124 :     return ary;
    2729                 :            : }
    2730                 :            : 
    2731                 :            : 
    2732                 :            : /*
    2733                 :            :  *  call-seq:
    2734                 :            :  *     ary.collect {|item| block}    -> new_ary
    2735                 :            :  *     ary.map     {|item| block}    -> new_ary
    2736                 :            :  *     ary.collect                   -> Enumerator
    2737                 :            :  *     ary.map                       -> Enumerator
    2738                 :            :  *
    2739                 :            :  *  Invokes the given block once for each element of +self+.
    2740                 :            :  *
    2741                 :            :  *  Creates a new array containing the values returned by the block.
    2742                 :            :  *
    2743                 :            :  *  See also Enumerable#collect.
    2744                 :            :  *
    2745                 :            :  *  If no block is given, an Enumerator is returned instead.
    2746                 :            :  *
    2747                 :            :  *     a = [ "a", "b", "c", "d" ]
    2748                 :            :  *     a.collect {|x| x + "!"}           #=> ["a!", "b!", "c!", "d!"]
    2749                 :            :  *     a.map.with_index {|x, i| x * i}   #=> ["", "b", "cc", "ddd"]
    2750                 :            :  *     a                                 #=> ["a", "b", "c", "d"]
    2751                 :            :  */
    2752                 :            : 
    2753                 :            : static VALUE
    2754                 :    2216998 : rb_ary_collect(VALUE ary)
    2755                 :            : {
    2756                 :            :     long i;
    2757                 :            :     VALUE collect;
    2758                 :            : 
    2759         [ +  + ]:    2216998 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    2760                 :    4395684 :     collect = rb_ary_new2(RARRAY_LEN(ary));
    2761         [ +  + ]:   23712560 :     for (i = 0; i < RARRAY_LEN(ary); i++) {
    2762                 :    9658588 :         rb_ary_push(collect, rb_yield_force_blockarg(RARRAY_AREF(ary, i)));
    2763                 :            :     }
    2764                 :            :     return collect;
    2765                 :            : }
    2766                 :            : 
    2767                 :            : 
    2768                 :            : /*
    2769                 :            :  *  call-seq:
    2770                 :            :  *     ary.collect! {|item| block }   -> ary
    2771                 :            :  *     ary.map!     {|item| block }   -> ary
    2772                 :            :  *     ary.collect!                   -> Enumerator
    2773                 :            :  *     ary.map!                       -> Enumerator
    2774                 :            :  *
    2775                 :            :  *  Invokes the given block once for each element of +self+, replacing the
    2776                 :            :  *  element with the value returned by the block.
    2777                 :            :  *
    2778                 :            :  *  See also Enumerable#collect.
    2779                 :            :  *
    2780                 :            :  *  If no block is given, an Enumerator is returned instead.
    2781                 :            :  *
    2782                 :            :  *     a = [ "a", "b", "c", "d" ]
    2783                 :            :  *     a.map! {|x| x + "!" }
    2784                 :            :  *     a #=>  [ "a!", "b!", "c!", "d!" ]
    2785                 :            :  *     a.collect!.with_index {|x, i| x[0...i] }
    2786                 :            :  *     a #=>  ["", "b", "c!", "d!"]
    2787                 :            :  */
    2788                 :            : 
    2789                 :            : static VALUE
    2790                 :     245501 : rb_ary_collect_bang(VALUE ary)
    2791                 :            : {
    2792                 :            :     long i;
    2793                 :            : 
    2794         [ +  + ]:     245501 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    2795                 :     245492 :     rb_ary_modify(ary);
    2796         [ +  + ]:    1641584 :     for (i = 0; i < RARRAY_LEN(ary); i++) {
    2797                 :     575315 :         rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)));
    2798                 :            :     }
    2799                 :            :     return ary;
    2800                 :            : }
    2801                 :            : 
    2802                 :            : VALUE
    2803                 :          7 : rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func) (VALUE, long))
    2804                 :            : {
    2805                 :         14 :     VALUE result = rb_ary_new2(argc);
    2806                 :            :     long beg, len, i, j;
    2807                 :            : 
    2808         [ +  + ]:         20 :     for (i=0; i<argc; i++) {
    2809         [ +  + ]:         14 :         if (FIXNUM_P(argv[i])) {
    2810                 :          8 :             rb_ary_push(result, (*func)(obj, FIX2LONG(argv[i])));
    2811                 :          8 :             continue;
    2812                 :            :         }
    2813                 :            :         /* check if idx is Range */
    2814         [ +  + ]:          6 :         if (rb_range_beg_len(argv[i], &beg, &len, olen, 1)) {
    2815                 :          5 :             long end = olen < beg+len ? olen : beg+len;
    2816         [ +  + ]:         20 :             for (j = beg; j < end; j++) {
    2817                 :         15 :                 rb_ary_push(result, (*func)(obj, j));
    2818                 :            :             }
    2819         [ -  + ]:          5 :             if (beg + len > j)
    2820                 :          0 :                 rb_ary_resize(result, RARRAY_LEN(result) + (beg + len) - j);
    2821                 :          5 :             continue;
    2822                 :            :         }
    2823                 :          0 :         rb_ary_push(result, (*func)(obj, NUM2LONG(argv[i])));
    2824                 :            :     }
    2825                 :          6 :     return result;
    2826                 :            : }
    2827                 :            : 
    2828                 :            : static VALUE
    2829                 :       2190 : append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
    2830                 :            : {
    2831                 :            :     long beg, len;
    2832         [ +  + ]:       2190 :     if (FIXNUM_P(idx)) {
    2833                 :       2158 :         beg = FIX2LONG(idx);
    2834                 :            :     }
    2835                 :            :     /* check if idx is Range */
    2836         [ +  + ]:         32 :     else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) {
    2837         [ +  + ]:         27 :         if (len > 0) {
    2838                 :         25 :             const VALUE *const src = RARRAY_CONST_PTR(ary);
    2839                 :         25 :             const long end = beg + len;
    2840                 :         25 :             const long prevlen = RARRAY_LEN(result);
    2841         [ +  + ]:         25 :             if (beg < olen) {
    2842         [ +  + ]:         21 :                 rb_ary_cat(result, src + beg, end > olen ? olen-beg : len);
    2843                 :            :             }
    2844         [ +  + ]:         25 :             if (end > olen) {
    2845                 :          6 :                 rb_ary_store(result, prevlen + len - 1, Qnil);
    2846                 :            :             }
    2847                 :            :         }
    2848                 :         27 :         return result;
    2849                 :            :     }
    2850                 :            :     else {
    2851                 :          3 :         beg = NUM2LONG(idx);
    2852                 :            :     }
    2853                 :       2161 :     return rb_ary_push(result, rb_ary_entry(ary, beg));
    2854                 :            : }
    2855                 :            : 
    2856                 :            : /*
    2857                 :            :  *  call-seq:
    2858                 :            :  *     ary.values_at(selector, ...)  -> new_ary
    2859                 :            :  *
    2860                 :            :  *  Returns an array containing the elements in +self+ corresponding to the
    2861                 :            :  *  given +selector+(s).
    2862                 :            :  *
    2863                 :            :  *  The selectors may be either integer indices or ranges.
    2864                 :            :  *
    2865                 :            :  *  See also Array#select.
    2866                 :            :  *
    2867                 :            :  *     a = %w{ a b c d e f }
    2868                 :            :  *     a.values_at(1, 3, 5)          # => ["b", "d", "f"]
    2869                 :            :  *     a.values_at(1, 3, 5, 7)       # => ["b", "d", "f", nil]
    2870                 :            :  *     a.values_at(-1, -2, -2, -7)   # => ["f", "e", "e", nil]
    2871                 :            :  *     a.values_at(4..6, 3...6)      # => ["e", "f", nil, "d", "e", "f"]
    2872                 :            :  */
    2873                 :            : 
    2874                 :            : static VALUE
    2875                 :        502 : rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
    2876                 :            : {
    2877                 :       1004 :     long i, olen = RARRAY_LEN(ary);
    2878                 :       1004 :     VALUE result = rb_ary_new_capa(argc);
    2879         [ +  + ]:       2690 :     for (i = 0; i < argc; ++i) {
    2880                 :       2190 :         append_values_at_single(result, ary, olen, argv[i]);
    2881                 :            :     }
    2882                 :        500 :     RB_GC_GUARD(ary);
    2883                 :        500 :     return result;
    2884                 :            : }
    2885                 :            : 
    2886                 :            : 
    2887                 :            : /*
    2888                 :            :  *  call-seq:
    2889                 :            :  *     ary.select {|item| block}   -> new_ary
    2890                 :            :  *     ary.select                  -> Enumerator
    2891                 :            :  *
    2892                 :            :  *  Returns a new array containing all elements of +ary+
    2893                 :            :  *  for which the given +block+ returns a true value.
    2894                 :            :  *
    2895                 :            :  *  If no block is given, an Enumerator is returned instead.
    2896                 :            :  *
    2897                 :            :  *     [1,2,3,4,5].select {|num|  num.even? }     #=> [2, 4]
    2898                 :            :  *
    2899                 :            :  *     a = %w{ a b c d e f }
    2900                 :            :  *     a.select {|v| v =~ /[aeiou]/}    #=> ["a", "e"]
    2901                 :            :  *
    2902                 :            :  *  See also Enumerable#select.
    2903                 :            :  */
    2904                 :            : 
    2905                 :            : static VALUE
    2906                 :      29781 : rb_ary_select(VALUE ary)
    2907                 :            : {
    2908                 :            :     VALUE result;
    2909                 :            :     long i;
    2910                 :            : 
    2911         [ +  + ]:      29781 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    2912                 :      59540 :     result = rb_ary_new2(RARRAY_LEN(ary));
    2913         [ +  + ]:    1671412 :     for (i = 0; i < RARRAY_LEN(ary); i++) {
    2914         [ +  + ]:     805938 :         if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
    2915                 :     226159 :             rb_ary_push(result, rb_ary_elt(ary, i));
    2916                 :            :         }
    2917                 :            :     }
    2918                 :            :     return result;
    2919                 :            : }
    2920                 :            : 
    2921                 :            : struct select_bang_arg {
    2922                 :            :     VALUE ary;
    2923                 :            :     long len[2];
    2924                 :            : };
    2925                 :            : 
    2926                 :            : static VALUE
    2927                 :         20 : select_bang_i(VALUE a)
    2928                 :            : {
    2929                 :         20 :     volatile struct select_bang_arg *arg = (void *)a;
    2930                 :         20 :     VALUE ary = arg->ary;
    2931                 :            :     long i1, i2;
    2932                 :            : 
    2933         [ +  + ]:        214 :     for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
    2934                 :         88 :         VALUE v = RARRAY_AREF(ary, i1);
    2935         [ +  + ]:         88 :         if (!RTEST(rb_yield(v))) continue;
    2936         [ +  + ]:         38 :         if (i1 != i2) {
    2937                 :         14 :             rb_ary_store(ary, i2, v);
    2938                 :            :         }
    2939                 :         38 :         arg->len[1] = ++i2;
    2940                 :            :     }
    2941         [ +  + ]:         19 :     return (i1 == i2) ? Qnil : ary;
    2942                 :            : }
    2943                 :            : 
    2944                 :            : static VALUE
    2945                 :     151306 : select_bang_ensure(VALUE a)
    2946                 :            : {
    2947                 :     151306 :     volatile struct select_bang_arg *arg = (void *)a;
    2948                 :     151306 :     VALUE ary = arg->ary;
    2949                 :     151306 :     long len = RARRAY_LEN(ary);
    2950                 :     151306 :     long i1 = arg->len[0], i2 = arg->len[1];
    2951                 :            : 
    2952         [ +  + ]:     151306 :     if (i2 < len && i2 < i1) {
    2953                 :       6431 :         long tail = 0;
    2954         [ +  + ]:       6431 :         if (i1 < len) {
    2955                 :          3 :             tail = len - i1;
    2956                 :          6 :             RARRAY_PTR_USE(ary, ptr, {
    2957                 :            :                     MEMMOVE(ptr + i2, ptr + i1, VALUE, tail);
    2958                 :            :                 });
    2959                 :            :         }
    2960 [ +  - ][ +  - ]:       6431 :         ARY_SET_LEN(ary, i2 + tail);
         [ +  - ][ +  + ]
                 [ +  + ]
    2961                 :            :     }
    2962                 :     151306 :     return ary;
    2963                 :            : }
    2964                 :            : 
    2965                 :            : /*
    2966                 :            :  *  call-seq:
    2967                 :            :  *     ary.select!  {|item| block } -> ary or nil
    2968                 :            :  *     ary.select!                  -> Enumerator
    2969                 :            :  *
    2970                 :            :  *  Invokes the given block passing in successive elements from +self+,
    2971                 :            :  *  deleting elements for which the block returns a +false+ value.
    2972                 :            :  *
    2973                 :            :  *  The array may not be changed instantly every time the block is called.
    2974                 :            :  *
    2975                 :            :  *  If changes were made, it will return +self+, otherwise it returns +nil+.
    2976                 :            :  *
    2977                 :            :  *  See also Array#keep_if
    2978                 :            :  *
    2979                 :            :  *  If no block is given, an Enumerator is returned instead.
    2980                 :            :  *
    2981                 :            :  */
    2982                 :            : 
    2983                 :            : static VALUE
    2984                 :         40 : rb_ary_select_bang(VALUE ary)
    2985                 :            : {
    2986                 :            :     struct select_bang_arg args;
    2987                 :            : 
    2988         [ +  + ]:         40 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    2989                 :         32 :     rb_ary_modify(ary);
    2990                 :            : 
    2991                 :         20 :     args.ary = ary;
    2992                 :         20 :     args.len[0] = args.len[1] = 0;
    2993                 :         20 :     return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
    2994                 :            : }
    2995                 :            : 
    2996                 :            : /*
    2997                 :            :  *  call-seq:
    2998                 :            :  *     ary.keep_if {|item| block}   -> ary
    2999                 :            :  *     ary.keep_if                  -> Enumerator
    3000                 :            :  *
    3001                 :            :  *  Deletes every element of +self+ for which the given block evaluates to
    3002                 :            :  *  +false+.
    3003                 :            :  *
    3004                 :            :  *  See also Array#select!
    3005                 :            :  *
    3006                 :            :  *  If no block is given, an Enumerator is returned instead.
    3007                 :            :  *
    3008                 :            :  *     a = %w{ a b c d e f }
    3009                 :            :  *     a.keep_if {|v| v =~ /[aeiou]/}    #=> ["a", "e"]
    3010                 :            :  */
    3011                 :            : 
    3012                 :            : static VALUE
    3013                 :         14 : rb_ary_keep_if(VALUE ary)
    3014                 :            : {
    3015         [ +  + ]:         14 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    3016                 :         10 :     rb_ary_select_bang(ary);
    3017                 :          6 :     return ary;
    3018                 :            : }
    3019                 :            : 
    3020                 :            : static void
    3021                 :     106224 : ary_resize_smaller(VALUE ary, long len)
    3022                 :            : {
    3023                 :     106224 :     rb_ary_modify(ary);
    3024         [ +  - ]:     106224 :     if (RARRAY_LEN(ary) > len) {
    3025 [ +  - ][ +  - ]:     106224 :         ARY_SET_LEN(ary, len);
         [ +  - ][ +  + ]
                 [ +  + ]
    3026 [ +  - ][ +  - ]:     188945 :         if (len * 2 < ARY_CAPA(ary) &&
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
                 [ +  + ]
    3027 [ +  - ][ +  - ]:      82721 :             ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
    3028                 :       2088 :             ary_resize_capa(ary, len * 2);
    3029                 :            :         }
    3030                 :            :     }
    3031                 :     106224 : }
    3032                 :            : 
    3033                 :            : /*
    3034                 :            :  *  call-seq:
    3035                 :            :  *     ary.delete(obj)            -> item or nil
    3036                 :            :  *     ary.delete(obj) {block}    -> item or result of block
    3037                 :            :  *
    3038                 :            :  *  Deletes all items from +self+ that are equal to +obj+.
    3039                 :            :  *
    3040                 :            :  *  Returns the last deleted item, or +nil+ if no matching item is found.
    3041                 :            :  *
    3042                 :            :  *  If the optional code block is given, the result of the block is returned if
    3043                 :            :  *  the item is not found.  (To remove +nil+ elements and get an informative
    3044                 :            :  *  return value, use Array#compact!)
    3045                 :            :  *
    3046                 :            :  *     a = [ "a", "b", "b", "b", "c" ]
    3047                 :            :  *     a.delete("b")                   #=> "b"
    3048                 :            :  *     a                               #=> ["a", "c"]
    3049                 :            :  *     a.delete("z")                   #=> nil
    3050                 :            :  *     a.delete("z") {"not found"}     #=> "not found"
    3051                 :            :  */
    3052                 :            : 
    3053                 :            : VALUE
    3054                 :      63400 : rb_ary_delete(VALUE ary, VALUE item)
    3055                 :            : {
    3056                 :      63400 :     VALUE v = item;
    3057                 :            :     long i1, i2;
    3058                 :            : 
    3059         [ +  + ]:     489580 :     for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
    3060                 :     181391 :         VALUE e = RARRAY_AREF(ary, i1);
    3061                 :            : 
    3062         [ +  + ]:     181391 :         if (rb_equal(e, item)) {
    3063                 :      63679 :             v = e;
    3064                 :      63679 :             continue;
    3065                 :            :         }
    3066         [ +  + ]:     117712 :         if (i1 != i2) {
    3067                 :      11056 :             rb_ary_store(ary, i2, e);
    3068                 :            :         }
    3069                 :     117711 :         i2++;
    3070                 :            :     }
    3071         [ +  + ]:      63399 :     if (RARRAY_LEN(ary) == i2) {
    3072         [ +  + ]:       1787 :         if (rb_block_given_p()) {
    3073                 :        137 :             return rb_yield(item);
    3074                 :            :         }
    3075                 :            :         return Qnil;
    3076                 :            :     }
    3077                 :            : 
    3078                 :      61612 :     ary_resize_smaller(ary, i2);
    3079                 :            : 
    3080                 :      61612 :     return v;
    3081                 :            : }
    3082                 :            : 
    3083                 :            : void
    3084                 :          0 : rb_ary_delete_same(VALUE ary, VALUE item)
    3085                 :            : {
    3086                 :            :     long i1, i2;
    3087                 :            : 
    3088         [ #  # ]:          0 :     for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
    3089                 :          0 :         VALUE e = RARRAY_AREF(ary, i1);
    3090                 :            : 
    3091         [ #  # ]:          0 :         if (e == item) {
    3092                 :          0 :             continue;
    3093                 :            :         }
    3094         [ #  # ]:          0 :         if (i1 != i2) {
    3095                 :          0 :             rb_ary_store(ary, i2, e);
    3096                 :            :         }
    3097                 :          0 :         i2++;
    3098                 :            :     }
    3099         [ #  # ]:          0 :     if (RARRAY_LEN(ary) == i2) {
    3100                 :          0 :         return;
    3101                 :            :     }
    3102                 :            : 
    3103                 :          0 :     ary_resize_smaller(ary, i2);
    3104                 :            : }
    3105                 :            : 
    3106                 :            : VALUE
    3107                 :     253215 : rb_ary_delete_at(VALUE ary, long pos)
    3108                 :            : {
    3109                 :     253215 :     long len = RARRAY_LEN(ary);
    3110                 :            :     VALUE del;
    3111                 :            : 
    3112         [ +  + ]:     253215 :     if (pos >= len) return Qnil;
    3113         [ +  + ]:     253208 :     if (pos < 0) {
    3114                 :        108 :         pos += len;
    3115         [ +  + ]:        108 :         if (pos < 0) return Qnil;
    3116                 :            :     }
    3117                 :            : 
    3118                 :     253202 :     rb_ary_modify(ary);
    3119                 :     253201 :     del = RARRAY_AREF(ary, pos);
    3120                 :     506402 :     RARRAY_PTR_USE(ary, ptr, {
    3121                 :            :         MEMMOVE(ptr+pos, ptr+pos+1, VALUE, len-pos-1);
    3122                 :            :     });
    3123 [ +  - ][ +  - ]:     456013 :     ARY_INCREASE_LEN(ary, -1);
         [ +  - ][ +  + ]
                 [ +  + ]
    3124                 :            : 
    3125                 :     253201 :     return del;
    3126                 :            : }
    3127                 :            : 
    3128                 :            : /*
    3129                 :            :  *  call-seq:
    3130                 :            :  *     ary.delete_at(index)  -> obj or nil
    3131                 :            :  *
    3132                 :            :  *  Deletes the element at the specified +index+, returning that element, or
    3133                 :            :  *  +nil+ if the +index+ is out of range.
    3134                 :            :  *
    3135                 :            :  *  See also Array#slice!
    3136                 :            :  *
    3137                 :            :  *     a = ["ant", "bat", "cat", "dog"]
    3138                 :            :  *     a.delete_at(2)    #=> "cat"
    3139                 :            :  *     a                 #=> ["ant", "bat", "dog"]
    3140                 :            :  *     a.delete_at(99)   #=> nil
    3141                 :            :  */
    3142                 :            : 
    3143                 :            : static VALUE
    3144                 :        805 : rb_ary_delete_at_m(VALUE ary, VALUE pos)
    3145                 :            : {
    3146                 :        803 :     return rb_ary_delete_at(ary, NUM2LONG(pos));
    3147                 :            : }
    3148                 :            : 
    3149                 :            : /*
    3150                 :            :  *  call-seq:
    3151                 :            :  *     ary.slice!(index)         -> obj or nil
    3152                 :            :  *     ary.slice!(start, length) -> new_ary or nil
    3153                 :            :  *     ary.slice!(range)         -> new_ary or nil
    3154                 :            :  *
    3155                 :            :  *  Deletes the element(s) given by an +index+ (optionally up to +length+
    3156                 :            :  *  elements) or by a +range+.
    3157                 :            :  *
    3158                 :            :  *  Returns the deleted object (or objects), or +nil+ if the +index+ is out of
    3159                 :            :  *  range.
    3160                 :            :  *
    3161                 :            :  *     a = [ "a", "b", "c" ]
    3162                 :            :  *     a.slice!(1)     #=> "b"
    3163                 :            :  *     a               #=> ["a", "c"]
    3164                 :            :  *     a.slice!(-1)    #=> "c"
    3165                 :            :  *     a               #=> ["a"]
    3166                 :            :  *     a.slice!(100)   #=> nil
    3167                 :            :  *     a               #=> ["a"]
    3168                 :            :  */
    3169                 :            : 
    3170                 :            : static VALUE
    3171                 :       4622 : rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
    3172                 :            : {
    3173                 :            :     VALUE arg1, arg2;
    3174                 :            :     long pos, len, orig_len;
    3175                 :            : 
    3176                 :       4622 :     rb_ary_modify_check(ary);
    3177         [ +  + ]:       4621 :     if (argc == 2) {
    3178                 :       7858 :         pos = NUM2LONG(argv[0]);
    3179                 :       3929 :         len = NUM2LONG(argv[1]);
    3180                 :            :       delete_pos_len:
    3181         [ +  + ]:       4595 :         if (len < 0) return Qnil;
    3182                 :       4594 :         orig_len = RARRAY_LEN(ary);
    3183         [ +  + ]:       4594 :         if (pos < 0) {
    3184                 :          3 :             pos += orig_len;
    3185         [ +  + ]:          3 :             if (pos < 0) return Qnil;
    3186                 :            :         }
    3187         [ +  + ]:       4591 :         else if (orig_len < pos) return Qnil;
    3188         [ +  + ]:       4590 :         if (orig_len < pos + len) {
    3189                 :          3 :             len = orig_len - pos;
    3190                 :            :         }
    3191         [ +  + ]:       4594 :         if (len == 0) return rb_ary_new2(0);
    3192                 :       9172 :         arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
    3193                 :       4586 :         RBASIC_SET_CLASS(arg2, rb_obj_class(ary));
    3194                 :       4586 :         rb_ary_splice(ary, pos, len, 0, 0);
    3195                 :       4586 :         return arg2;
    3196                 :            :     }
    3197                 :            : 
    3198         [ +  + ]:        692 :     if (argc != 1) {
    3199                 :            :         /* error report */
    3200                 :         14 :         rb_scan_args(argc, argv, "11", NULL, NULL);
    3201                 :            :     }
    3202                 :        690 :     arg1 = argv[0];
    3203                 :            : 
    3204         [ +  + ]:        690 :     if (!FIXNUM_P(arg1)) {
    3205      [ +  +  + ]:        673 :         switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
    3206                 :            :           case Qtrue:
    3207                 :            :             /* valid range */
    3208                 :            :             goto delete_pos_len;
    3209                 :            :           case Qnil:
    3210                 :            :             /* invalid range */
    3211                 :            :             return Qnil;
    3212                 :            :           default:
    3213                 :            :             /* not a range */
    3214                 :            :             break;
    3215                 :            :         }
    3216                 :            :     }
    3217                 :            : 
    3218                 :         18 :     return rb_ary_delete_at(ary, NUM2LONG(arg1));
    3219                 :            : }
    3220                 :            : 
    3221                 :            : static VALUE
    3222                 :      41904 : ary_reject(VALUE orig, VALUE result)
    3223                 :            : {
    3224                 :            :     long i;
    3225                 :            : 
    3226         [ +  + ]:     523242 :     for (i = 0; i < RARRAY_LEN(orig); i++) {
    3227                 :     219222 :         VALUE v = RARRAY_AREF(orig, i);
    3228         [ +  + ]:     219222 :         if (!RTEST(rb_yield(v))) {
    3229                 :      71417 :             rb_ary_push(result, v);
    3230                 :            :         }
    3231                 :            :     }
    3232                 :      42399 :     return result;
    3233                 :            : }
    3234                 :            : 
    3235                 :            : static VALUE
    3236                 :     151286 : reject_bang_i(VALUE a)
    3237                 :            : {
    3238                 :     151286 :     volatile struct select_bang_arg *arg = (void *)a;
    3239                 :     151286 :     VALUE ary = arg->ary;
    3240                 :            :     long i1, i2;
    3241                 :            : 
    3242         [ +  + ]:    1857516 :     for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); arg->len[0] = ++i1) {
    3243                 :     777476 :         VALUE v = RARRAY_AREF(ary, i1);
    3244         [ +  + ]:     777476 :         if (RTEST(rb_yield(v))) continue;
    3245         [ +  + ]:     768830 :         if (i1 != i2) {
    3246                 :       6018 :             rb_ary_store(ary, i2, v);
    3247                 :            :         }
    3248                 :     768830 :         arg->len[1] = ++i2;
    3249                 :            :     }
    3250         [ +  + ]:     151282 :     return (i1 == i2) ? Qnil : ary;
    3251                 :            : }
    3252                 :            : 
    3253                 :            : static VALUE
    3254                 :     151290 : ary_reject_bang(VALUE ary)
    3255                 :            : {
    3256                 :            :     struct select_bang_arg args;
    3257                 :            : 
    3258                 :     151290 :     rb_ary_modify_check(ary);
    3259                 :     151286 :     args.ary = ary;
    3260                 :     151286 :     args.len[0] = args.len[1] = 0;
    3261                 :     151286 :     return rb_ensure(reject_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
    3262                 :            : }
    3263                 :            : 
    3264                 :            : /*
    3265                 :            :  *  call-seq:
    3266                 :            :  *     ary.reject! {|item| block}    -> ary or nil
    3267                 :            :  *     ary.reject!                   -> Enumerator
    3268                 :            :  *
    3269                 :            :  *  Deletes every element of +self+ for which the block evaluates to +true+,
    3270                 :            :  *  if no changes were made returns +nil+.
    3271                 :            :  *
    3272                 :            :  *  The array may not be changed instantly every time the block is called.
    3273                 :            :  *
    3274                 :            :  *  See also Enumerable#reject and Array#delete_if.
    3275                 :            :  *
    3276                 :            :  *  If no block is given, an Enumerator is returned instead.
    3277                 :            :  */
    3278                 :            : 
    3279                 :            : static VALUE
    3280                 :       4264 : rb_ary_reject_bang(VALUE ary)
    3281                 :            : {
    3282         [ +  + ]:       4264 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    3283                 :       4262 :     return ary_reject_bang(ary);
    3284                 :            : }
    3285                 :            : 
    3286                 :            : /*
    3287                 :            :  *  call-seq:
    3288                 :            :  *     ary.reject  {|item| block }  -> new_ary
    3289                 :            :  *     ary.reject                   -> Enumerator
    3290                 :            :  *
    3291                 :            :  *  Returns a new array containing the items in +self+ for which the given
    3292                 :            :  *  block is not +true+. The ordering of non-rejected elements is maintained.
    3293                 :            :  *
    3294                 :            :  *  See also Array#delete_if
    3295                 :            :  *
    3296                 :            :  *  If no block is given, an Enumerator is returned instead.
    3297                 :            :  */
    3298                 :            : 
    3299                 :            : static VALUE
    3300                 :      41907 : rb_ary_reject(VALUE ary)
    3301                 :            : {
    3302                 :            :     VALUE rejected_ary;
    3303                 :            : 
    3304         [ +  + ]:      41907 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    3305                 :      41904 :     rejected_ary = rb_ary_new();
    3306                 :      41904 :     ary_reject(ary, rejected_ary);
    3307                 :      42399 :     return rejected_ary;
    3308                 :            : }
    3309                 :            : 
    3310                 :            : /*
    3311                 :            :  *  call-seq:
    3312                 :            :  *     ary.delete_if {|item| block}    -> ary
    3313                 :            :  *     ary.delete_if                   -> Enumerator
    3314                 :            :  *
    3315                 :            :  *  Deletes every element of +self+ for which block evaluates to +true+.
    3316                 :            :  *
    3317                 :            :  *  The array is changed instantly every time the block is called, not after
    3318                 :            :  *  the iteration is over.
    3319                 :            :  *
    3320                 :            :  *  See also Array#reject!
    3321                 :            :  *
    3322                 :            :  *  If no block is given, an Enumerator is returned instead.
    3323                 :            :  *
    3324                 :            :  *     scores = [ 97, 42, 75 ]
    3325                 :            :  *     scores.delete_if {|score| score < 80 }   #=> [97]
    3326                 :            :  */
    3327                 :            : 
    3328                 :            : static VALUE
    3329                 :     147035 : rb_ary_delete_if(VALUE ary)
    3330                 :            : {
    3331         [ +  + ]:     147035 :     RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    3332                 :     147028 :     ary_reject_bang(ary);
    3333                 :     147025 :     return ary;
    3334                 :            : }
    3335                 :            : 
    3336                 :            : static VALUE
    3337                 :         21 : take_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, cbarg))
    3338                 :            : {
    3339                 :         21 :     VALUE *args = (VALUE *)cbarg;
    3340         [ +  + ]:         21 :     if (args[1]-- == 0) rb_iter_break();
    3341         [ -  + ]:         17 :     if (argc > 1) val = rb_ary_new4(argc, argv);
    3342                 :         17 :     rb_ary_push(args[0], val);
    3343                 :         17 :     return Qnil;
    3344                 :            : }
    3345                 :            : 
    3346                 :            : static VALUE
    3347                 :     287526 : take_items(VALUE obj, long n)
    3348                 :            : {
    3349                 :     287526 :     VALUE result = rb_check_array_type(obj);
    3350                 :            :     VALUE args[2];
    3351                 :            : 
    3352         [ +  + ]:     287526 :     if (!NIL_P(result)) return rb_ary_subseq(result, 0, n);
    3353                 :         10 :     result = rb_ary_new2(n);
    3354                 :         10 :     args[0] = result; args[1] = (VALUE)n;
    3355         [ +  + ]:         10 :     if (rb_check_block_call(obj, idEach, 0, 0, take_i, (VALUE)args) == Qundef)
    3356                 :          2 :         rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (must respond to :each)",
    3357                 :            :                  rb_obj_class(obj));
    3358                 :            :     return result;
    3359                 :            : }
    3360                 :            : 
    3361                 :            : 
    3362                 :            : /*
    3363                 :            :  *  call-seq:
    3364                 :            :  *     ary.zip(arg, ...)                  -> new_ary
    3365                 :            :  *     ary.zip(arg, ...) {|arr| block}    -> nil
    3366                 :            :  *
    3367                 :            :  *  Converts any arguments to arrays, then merges elements of +self+ with
    3368                 :            :  *  corresponding elements from each argument.
    3369                 :            :  *
    3370                 :            :  *  This generates a sequence of <code>ary.size</code> _n_-element arrays,
    3371                 :            :  *  where _n_ is one more than the count of arguments.
    3372                 :            :  *
    3373                 :            :  *  If the size of any argument is less than the size of the initial array,
    3374                 :            :  *  +nil+ values are supplied.
    3375                 :            :  *
    3376                 :            :  *  If a block is given, it is invoked for each output +array+, otherwise an
    3377                 :            :  *  array of arrays is returned.
    3378                 :            :  *
    3379                 :            :  *     a = [ 4, 5, 6 ]
    3380                 :            :  *     b = [ 7, 8, 9 ]
    3381                 :            :  *     [1, 2, 3].zip(a, b)   #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
    3382                 :            :  *     [1, 2].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8]]
    3383                 :            :  *     a.zip([1, 2], [8])    #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
    3384                 :            :  */
    3385                 :            : 
    3386                 :            : static VALUE
    3387                 :     287523 : rb_ary_zip(int argc, VALUE *argv, VALUE ary)
    3388                 :            : {
    3389                 :            :     int i, j;
    3390                 :     287523 :     long len = RARRAY_LEN(ary);
    3391                 :     287523 :     VALUE result = Qnil;
    3392                 :            : 
    3393         [ +  + ]:     575047 :     for (i=0; i<argc; i++) {
    3394                 :     287526 :         argv[i] = take_items(argv[i], len);
    3395                 :            :     }
    3396                 :            : 
    3397         [ +  + ]:     287521 :     if (rb_block_given_p()) {
    3398                 :         19 :         int arity = rb_block_arity();
    3399                 :            : 
    3400         [ +  + ]:         19 :         if (arity > 1) {
    3401                 :            :             VALUE work, *tmp;
    3402                 :            : 
    3403         [ +  - ]:         17 :             tmp = ALLOCV_N(VALUE, work, argc+1);
    3404                 :            : 
    3405         [ +  + ]:        434 :             for (i=0; i<RARRAY_LEN(ary); i++) {
    3406                 :        200 :                 tmp[0] = RARRAY_AREF(ary, i);
    3407         [ +  + ]:        400 :                 for (j=0; j<argc; j++) {
    3408                 :        200 :                     tmp[j+1] = rb_ary_elt(argv[j], i);
    3409                 :            :                 }
    3410                 :        200 :                 rb_yield_values2(argc+1, tmp);
    3411                 :            :             }
    3412                 :            : 
    3413         [ -  + ]:         17 :             if (work) ALLOCV_END(work);
    3414                 :            :         }
    3415                 :            :         else {
    3416         [ +  + ]:         16 :             for (i=0; i<RARRAY_LEN(ary); i++) {
    3417                 :         14 :                 VALUE tmp = rb_ary_new2(argc+1);
    3418                 :            : 
    3419                 :          7 :                 rb_ary_push(tmp, RARRAY_AREF(ary, i));
    3420         [ +  + ]:         17 :                 for (j=0; j<argc; j++) {
    3421                 :         10 :                     rb_ary_push(tmp, rb_ary_elt(argv[j], i));
    3422                 :            :                 }
    3423                 :          7 :                 rb_yield(tmp);
    3424                 :            :             }
    3425                 :            :         }
    3426                 :            :     }
    3427                 :            :     else {
    3428                 :     287502 :         result = rb_ary_new_capa(len);
    3429                 :            : 
    3430         [ +  + ]:     961228 :         for (i=0; i<len; i++) {
    3431                 :    1347452 :             VALUE tmp = rb_ary_new_capa(argc+1);
    3432                 :            : 
    3433                 :     673726 :             rb_ary_push(tmp, RARRAY_AREF(ary, i));
    3434         [ +  + ]:    1347458 :             for (j=0; j<argc; j++) {
    3435                 :     673732 :                 rb_ary_push(tmp, rb_ary_elt(argv[j], i));
    3436                 :            :             }
    3437                 :     673726 :             rb_ary_push(result, tmp);
    3438                 :            :         }
    3439                 :            :     }
    3440                 :            : 
    3441                 :     287521 :     return result;
    3442                 :            : }
    3443                 :            : 
    3444                 :            : /*
    3445                 :            :  *  call-seq:
    3446                 :            :  *     ary.transpose -> new_ary
    3447                 :            :  *
    3448                 :            :  *  Assumes that +self+ is an array of arrays and transposes the rows and
    3449                 :            :  *  columns.
    3450                 :            :  *
    3451                 :            :  *     a = [[1,2], [3,4], [5,6]]
    3452                 :            :  *     a.transpose   #=> [[1, 3, 5], [2, 4, 6]]
    3453                 :            :  *
    3454                 :            :  *  If the length of the subarrays don't match, an IndexError is raised.
    3455                 :            :  */
    3456                 :            : 
    3457                 :            : static VALUE
    3458                 :      11252 : rb_ary_transpose(VALUE ary)
    3459                 :            : {
    3460                 :      11252 :     long elen = -1, alen, i, j;
    3461                 :      11252 :     VALUE tmp, result = 0;
    3462                 :            : 
    3463                 :      11252 :     alen = RARRAY_LEN(ary);
    3464         [ +  + ]:      11252 :     if (alen == 0) return rb_ary_dup(ary);
    3465         [ +  + ]:      33805 :     for (i=0; i<alen; i++) {
    3466                 :      22557 :         tmp = to_ary(rb_ary_elt(ary, i));
    3467         [ +  + ]:      22556 :         if (elen < 0) {              /* first element */
    3468                 :      11250 :             elen = RARRAY_LEN(tmp);
    3469                 :      11250 :             result = rb_ary_new2(elen);
    3470         [ +  + ]:      19071 :             for (j=0; j<elen; j++) {
    3471                 :       7821 :                 rb_ary_store(result, j, rb_ary_new2(alen));
    3472                 :            :             }
    3473                 :            :         }
    3474         [ +  + ]:      11306 :         else if (elen != RARRAY_LEN(tmp)) {
    3475                 :          2 :             rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)",
    3476                 :            :                      RARRAY_LEN(tmp), elen);
    3477                 :            :         }
    3478         [ +  + ]:      38326 :         for (j=0; j<elen; j++) {
    3479                 :      15772 :             rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j));
    3480                 :            :         }
    3481                 :            :     }
    3482                 :      11248 :     return result;
    3483                 :            : }
    3484                 :            : 
    3485                 :            : /*
    3486                 :            :  *  call-seq:
    3487                 :            :  *     ary.replace(other_ary)  -> ary
    3488                 :            :  *     ary.initialize_copy(other_ary)   -> ary
    3489                 :            :  *
    3490                 :            :  *  Replaces the contents of +self+ with the contents of +other_ary+,
    3491                 :            :  *  truncating or expanding if necessary.
    3492                 :            :  *
    3493                 :            :  *     a = [ "a", "b", "c", "d", "e" ]
    3494                 :            :  *     a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
    3495                 :            :  *     a                              #=> ["x", "y", "z"]
    3496                 :            :  */
    3497                 :            : 
    3498                 :            : VALUE
    3499                 :     669448 : rb_ary_replace(VALUE copy, VALUE orig)
    3500                 :            : {
    3501                 :     669448 :     rb_ary_modify_check(copy);
    3502                 :     669444 :     orig = to_ary(orig);
    3503         [ +  + ]:     669444 :     if (copy == orig) return copy;
    3504                 :            : 
    3505         [ +  + ]:     669443 :     if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
    3506                 :     480307 :         VALUE shared = 0;
    3507                 :            : 
    3508 [ +  - ][ +  - ]:     480307 :         if (ARY_OWNS_HEAP_P(copy)) {
         [ +  - ][ +  + ]
    3509                 :        481 :             RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)));
    3510                 :            :         }
    3511 [ +  - ][ +  - ]:     479826 :         else if (ARY_SHARED_P(copy)) {
         [ +  - ][ +  + ]
                 [ +  + ]
    3512                 :         41 :             shared = ARY_SHARED(copy);
    3513 [ +  - ][ +  - ]:         41 :             FL_UNSET_SHARED(copy);
                 [ +  - ]
    3514                 :            :         }
    3515 [ +  - ][ +  - ]:     480307 :         FL_SET_EMBED(copy);
                 [ +  - ]
    3516                 :     960614 :         ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
    3517         [ +  + ]:     480307 :         if (shared) {
    3518                 :         41 :             rb_ary_decrement_share(shared);
    3519                 :            :         }
    3520 [ +  - ][ +  - ]:     960614 :         ARY_SET_LEN(copy, RARRAY_LEN(orig));
         [ +  - ][ -  + ]
                 [ +  - ]
    3521                 :            :     }
    3522                 :            :     else {
    3523                 :     189136 :         VALUE shared = ary_make_shared(orig);
    3524 [ +  - ][ +  - ]:     189136 :         if (ARY_OWNS_HEAP_P(copy)) {
         [ +  - ][ +  + ]
    3525                 :       1335 :             RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)));
    3526                 :            :         }
    3527                 :            :         else {
    3528                 :     187801 :             rb_ary_unshare_safe(copy);
    3529                 :            :         }
    3530 [ +  - ][ +  - ]:     189136 :         FL_UNSET_EMBED(copy);
                 [ +  - ]
    3531                 :     378272 :         ARY_SET_PTR(copy, RARRAY_CONST_PTR(orig));
    3532 [ +  - ][ +  - ]:     378272 :         ARY_SET_LEN(copy, RARRAY_LEN(orig));
         [ +  - ][ +  - ]
                 [ -  + ]
    3533                 :     189136 :         rb_ary_set_shared(copy, shared);
    3534                 :            :     }
    3535                 :            :     return copy;
    3536                 :            : }
    3537                 :            : 
    3538                 :            : /*
    3539                 :            :  *  call-seq:
    3540                 :            :  *     ary.clear    -> ary
    3541                 :            :  *
    3542                 :            :  *  Removes all elements from +self+.
    3543                 :            :  *
    3544                 :            :  *     a = [ "a", "b", "c", "d", "e" ]
    3545                 :            :  *     a.clear    #=> [ ]
    3546                 :            :  */
    3547                 :            : 
    3548                 :            : VALUE
    3549                 :     896079 : rb_ary_clear(VALUE ary)
    3550                 :            : {
    3551                 :     896079 :     rb_ary_modify_check(ary);
    3552 [ +  - ][ +  - ]:     896078 :     ARY_SET_LEN(ary, 0);
         [ +  - ][ +  + ]
                 [ +  + ]
    3553 [ +  - ][ +  - ]:     896078 :     if (ARY_SHARED_P(ary)) {
         [ +  - ][ +  + ]
                 [ +  + ]
    3554 [ +  - ][ +  - ]:       2691 :         if (!ARY_EMBED_P(ary)) {
         [ +  - ][ +  - ]
                 [ +  - ]
    3555                 :       2691 :             rb_ary_unshare(ary);
    3556 [ +  - ][ +  - ]:       2691 :             FL_SET_EMBED(ary);
                 [ +  - ]
    3557                 :            :         }
    3558                 :            :     }
    3559 [ +  - ][ +  - ]:     893387 :     else if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
    3560                 :      33141 :         ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
    3561                 :            :     }
    3562                 :     896078 :     return ary;
    3563                 :            : }
    3564                 :            : 
    3565                 :            : /*
    3566                 :            :  *  call-seq:
    3567                 :            :  *     ary.fill(obj)                                 -> ary
    3568                 :            :  *     ary.fill(obj, start [, length])               -> ary
    3569                 :            :  *     ary.fill(obj, range)                          -> ary
    3570                 :            :  *     ary.fill {|index| block}                      -> ary
    3571                 :            :  *     ary.fill(start [, length]) {|index| block}    -> ary
    3572                 :            :  *     ary.fill(range) {|index| block}               -> ary
    3573                 :            :  *
    3574                 :            :  *  The first three forms set the selected elements of +self+ (which
    3575                 :            :  *  may be the entire array) to +obj+.
    3576                 :            :  *
    3577                 :            :  *  A +start+ of +nil+ is equivalent to zero.
    3578                 :            :  *
    3579                 :            :  *  A +length+ of +nil+ is equivalent to the length of the array.
    3580                 :            :  *
    3581                 :            :  *  The last three forms fill the array with the value of the given block,
    3582                 :            :  *  which is passed the absolute index of each element to be filled.
    3583                 :            :  *
    3584                 :            :  *  Negative values of +start+ count from the end of the array, where +-1+ is
    3585                 :            :  *  the last element.
    3586                 :            :  *
    3587                 :            :  *     a = [ "a", "b", "c", "d" ]
    3588                 :            :  *     a.fill("x")              #=> ["x", "x", "x", "x"]
    3589                 :            :  *     a.fill("z", 2, 2)        #=> ["x", "x", "z", "z"]
    3590                 :            :  *     a.fill("y", 0..1)        #=> ["y", "y", "z", "z"]
    3591                 :            :  *     a.fill {|i| i*i}         #=> [0, 1, 4, 9]
    3592                 :            :  *     a.fill(-2) {|i| i*i*i}   #=> [0, 1, 8, 27]
    3593                 :            :  */
    3594                 :            : 
    3595                 :            : static VALUE
    3596                 :     559134 : rb_ary_fill(int argc, VALUE *argv, VALUE ary)
    3597                 :            : {
    3598                 :     559134 :     VALUE item = Qundef, arg1, arg2;
    3599                 :     559134 :     long beg = 0, end = 0, len = 0;
    3600                 :            : 
    3601         [ +  + ]:     559134 :     if (rb_block_given_p()) {
    3602                 :        406 :         rb_scan_args(argc, argv, "02", &arg1, &arg2);
    3603                 :         57 :         argc += 1;              /* hackish */
    3604                 :            :     }
    3605                 :            :     else {
    3606                 :    3913532 :         rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
    3607                 :            :     }
    3608   [ +  +  +  - ]:     559131 :     switch (argc) {
    3609                 :            :       case 1:
    3610                 :       1473 :         beg = 0;
    3611                 :       1473 :         len = RARRAY_LEN(ary);
    3612                 :       1473 :         break;
    3613                 :            :       case 2:
    3614         [ +  + ]:     557595 :         if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) {
    3615                 :            :             break;
    3616                 :            :         }
    3617                 :            :         /* fall through */
    3618                 :            :       case 3:
    3619         [ +  + ]:         80 :         beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1);
    3620         [ +  + ]:         77 :         if (beg < 0) {
    3621                 :         18 :             beg = RARRAY_LEN(ary) + beg;
    3622         [ +  + ]:         18 :             if (beg < 0) beg = 0;
    3623                 :            :         }
    3624         [ +  + ]:         99 :         len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2);
    3625                 :         76 :         break;
    3626                 :            :     }
    3627                 :     559120 :     rb_ary_modify(ary);
    3628         [ +  + ]:     559118 :     if (len < 0) {
    3629                 :            :         return ary;
    3630                 :            :     }
    3631 [ +  - ][ +  + ]:     559099 :     if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) {
    3632                 :          2 :         rb_raise(rb_eArgError, "argument too big");
    3633                 :            :     }
    3634                 :     559097 :     end = beg + len;
    3635         [ +  + ]:     559097 :     if (RARRAY_LEN(ary) < end) {
    3636 [ +  - ][ +  - ]:         19 :         if (end >= ARY_CAPA(ary)) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
    3637                 :         17 :             ary_resize_capa(ary, end);
    3638                 :            :         }
    3639                 :         38 :         ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary));
    3640 [ +  - ][ +  - ]:         19 :         ARY_SET_LEN(ary, end);
         [ +  - ][ +  + ]
                 [ +  + ]
    3641                 :            :     }
    3642                 :            : 
    3643         [ +  + ]:     559097 :     if (item == Qundef) {
    3644                 :            :         VALUE v;
    3645                 :            :         long i;
    3646                 :            : 
    3647         [ +  + ]:        146 :         for (i=beg; i<end; i++) {
    3648                 :        101 :             v = rb_yield(LONG2NUM(i));
    3649         [ +  - ]:        101 :             if (i>=RARRAY_LEN(ary)) break;
    3650                 :        202 :             ARY_SET(ary, i, v);
    3651                 :            :         }
    3652                 :            :     }
    3653                 :            :     else {
    3654                 :     559052 :         ary_memfill(ary, beg, len, item);
    3655                 :            :     }
    3656                 :            :     return ary;
    3657                 :            : }
    3658                 :            : 
    3659                 :            : /*
    3660                 :            :  *  call-seq:
    3661                 :            :  *     ary + other_ary   -> new_ary
    3662                 :            :  *
    3663                 :            :  *  Concatenation --- Returns a new array built by concatenating the
    3664                 :            :  *  two arrays together to produce a third array.
    3665                 :            :  *
    3666                 :            :  *     [ 1, 2, 3 ] + [ 4, 5 ]    #=> [ 1, 2, 3, 4, 5 ]
    3667                 :            :  *     a = [ "a", "b", "c" ]
    3668                 :            :  *     c = a + [ "d", "e", "f" ]
    3669                 :            :  *     c                         #=> [ "a", "b", "c", "d", "e", "f" ]
    3670                 :            :  *     a                         #=> [ "a", "b", "c" ]
    3671                 :            :  *
    3672                 :            :  *  Note that
    3673                 :            :  *     x += y
    3674                 :            :  *  is the same as
    3675                 :            :  *     x = x + y
    3676                 :            :  *  This means that it produces a new array. As a consequence,
    3677                 :            :  *  repeated use of <code>+=</code> on arrays can be quite inefficient.
    3678                 :            :  *
    3679                 :            :  *  See also Array#concat.
    3680                 :            :  */
    3681                 :            : 
    3682                 :            : VALUE
    3683                 :     768858 : rb_ary_plus(VALUE x, VALUE y)
    3684                 :            : {
    3685                 :            :     VALUE z;
    3686                 :            :     long len, xlen, ylen;
    3687                 :            : 
    3688                 :     768858 :     y = to_ary(y);
    3689                 :     768858 :     xlen = RARRAY_LEN(x);
    3690                 :     768858 :     ylen = RARRAY_LEN(y);
    3691                 :     768858 :     len = xlen + ylen;
    3692                 :     768858 :     z = rb_ary_new2(len);
    3693                 :            : 
    3694                 :     768858 :     ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
    3695                 :     768858 :     ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
    3696 [ +  - ][ +  - ]:     768858 :     ARY_SET_LEN(z, len);
         [ +  - ][ +  + ]
                 [ +  + ]
    3697                 :     768858 :     return z;
    3698                 :            : }
    3699                 :            : 
    3700                 :            : static VALUE
    3701                 :    3879098 : ary_append(VALUE x, VALUE y)
    3702                 :            : {
    3703                 :    3879098 :     long n = RARRAY_LEN(y);
    3704         [ +  + ]:    3879098 :     if (n > 0) {
    3705                 :    3350406 :         rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
    3706                 :            :     }
    3707                 :    3879098 :     return x;
    3708                 :            : }
    3709                 :            : 
    3710                 :            : /*
    3711                 :            :  *  call-seq:
    3712                 :            :  *     ary.concat(other_ary1, other_ary2,...)   -> ary
    3713                 :            :  *
    3714                 :            :  *  Appends the elements of +other_ary+s to +self+.
    3715                 :            :  *
    3716                 :            :  *     [ "a", "b" ].concat( ["c", "d"])   #=> [ "a", "b", "c", "d" ]
    3717                 :            :  *     [ "a" ].concat( ["b"], ["c", "d"]) #=> [ "a", "b", "c", "d" ]
    3718                 :            :  *     [ "a" ].concat #=> [ "a" ]
    3719                 :            :  *
    3720                 :            :  *     a = [ 1, 2, 3 ]
    3721                 :            :  *     a.concat( [ 4, 5 ])
    3722                 :            :  *     a                                 #=> [ 1, 2, 3, 4, 5 ]
    3723                 :            :  *
    3724                 :            :  *     a = [ 1, 2 ]
    3725                 :            :  *     a.concat(a, a)                    #=> [1, 2, 1, 2, 1, 2]
    3726                 :            :  *
    3727                 :            :  *  See also Array#+.
    3728                 :            :  */
    3729                 :            : 
    3730                 :            : static VALUE
    3731                 :     187588 : rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
    3732                 :            : {
    3733                 :     187588 :     rb_ary_modify_check(ary);
    3734                 :            : 
    3735         [ +  + ]:     187585 :     if (argc == 1) {
    3736                 :     187580 :         rb_ary_concat(ary, argv[0]);
    3737                 :            :     }
    3738         [ +  + ]:          5 :     else if (argc > 1) {
    3739                 :            :         int i;
    3740                 :          6 :         VALUE args = rb_ary_tmp_new(argc);
    3741         [ +  + ]:          9 :         for (i = 0; i < argc; i++) {
    3742                 :          6 :             rb_ary_concat(args, argv[i]);
    3743                 :            :         }
    3744                 :          3 :         ary_append(ary, args);
    3745                 :            :     }
    3746                 :            : 
    3747                 :     187583 :     return ary;
    3748                 :            : }
    3749                 :            : 
    3750                 :            : VALUE
    3751                 :    3879097 : rb_ary_concat(VALUE x, VALUE y)
    3752                 :            : {
    3753                 :    3879095 :     return ary_append(x, to_ary(y));
    3754                 :            : }
    3755                 :            : 
    3756                 :            : /*
    3757                 :            :  *  call-seq:
    3758                 :            :  *     ary * int     -> new_ary
    3759                 :            :  *     ary * str     -> new_string
    3760                 :            :  *
    3761                 :            :  *  Repetition --- With a String argument, equivalent to
    3762                 :            :  *  <code>ary.join(str)</code>.
    3763                 :            :  *
    3764                 :            :  *  Otherwise, returns a new array built by concatenating the +int+ copies of
    3765                 :            :  *  +self+.
    3766                 :            :  *
    3767                 :            :  *
    3768                 :            :  *     [ 1, 2, 3 ] * 3    #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
    3769                 :            :  *     [ 1, 2, 3 ] * ","  #=> "1,2,3"
    3770                 :            :  *
    3771                 :            :  */
    3772                 :            : 
    3773                 :            : static VALUE
    3774                 :      43851 : rb_ary_times(VALUE ary, VALUE times)
    3775                 :            : {
    3776                 :            :     VALUE ary2, tmp;
    3777                 :            :     const VALUE *ptr;
    3778                 :            :     long t, len;
    3779                 :            : 
    3780                 :      43851 :     tmp = rb_check_string_type(times);
    3781         [ +  + ]:      43851 :     if (!NIL_P(tmp)) {
    3782                 :         15 :         return rb_ary_join(ary, tmp);
    3783                 :            :     }
    3784                 :            : 
    3785                 :      43834 :     len = NUM2LONG(times);
    3786         [ +  + ]:      43834 :     if (len == 0) {
    3787                 :      36088 :         ary2 = ary_new(rb_obj_class(ary), 0);
    3788                 :      36088 :         goto out;
    3789                 :            :     }
    3790         [ +  + ]:       7746 :     if (len < 0) {
    3791                 :          3 :         rb_raise(rb_eArgError, "negative argument");
    3792                 :            :     }
    3793         [ +  + ]:       7743 :     if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
    3794                 :          1 :         rb_raise(rb_eArgError, "argument too big");
    3795                 :            :     }
    3796                 :       7742 :     len *= RARRAY_LEN(ary);
    3797                 :            : 
    3798                 :       7742 :     ary2 = ary_new(rb_obj_class(ary), len);
    3799 [ +  - ][ +  - ]:       7742 :     ARY_SET_LEN(ary2, len);
         [ +  - ][ +  + ]
                 [ +  + ]
    3800                 :            : 
    3801                 :       7742 :     ptr = RARRAY_CONST_PTR(ary);
    3802                 :       7742 :     t = RARRAY_LEN(ary);
    3803         [ +  + ]:       7742 :     if (0 < t) {
    3804                 :            :         ary_memcpy(ary2, 0, t, ptr);
    3805         [ +  + ]:      19570 :         while (t <= len/2) {
    3806                 :      11832 :             ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
    3807                 :      11832 :             t *= 2;
    3808                 :            :         }
    3809         [ +  + ]:       7738 :         if (t < len) {
    3810                 :       1975 :             ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
    3811                 :            :         }
    3812                 :            :     }
    3813                 :            :   out:
    3814 [ +  - ][ +  - ]:      43830 :     OBJ_INFECT(ary2, ary);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3815                 :            : 
    3816                 :      43830 :     return ary2;
    3817                 :            : }
    3818                 :            : 
    3819                 :            : /*
    3820                 :            :  *  call-seq:
    3821                 :            :  *     ary.assoc(obj)   -> element_ary  or  nil
    3822                 :            :  *
    3823                 :            :  *  Searches through an array whose elements are also arrays comparing +obj+
    3824                 :            :  *  with the first element of each contained array using <code>obj.==</code>.
    3825                 :            :  *
    3826                 :            :  *  Returns the first contained array that matches (that is, the first
    3827                 :            :  *  associated array), or +nil+ if no match is found.
    3828                 :            :  *
    3829                 :            :  *  See also Array#rassoc
    3830                 :            :  *
    3831                 :            :  *     s1 = [ "colors", "red", "blue", "green" ]
    3832                 :            :  *     s2 = [ "letters", "a", "b", "c" ]
    3833                 :            :  *     s3 = "foo"
    3834                 :            :  *     a  = [ s1, s2, s3 ]
    3835                 :            :  *     a.assoc("letters")  #=> [ "letters", "a", "b", "c" ]
    3836                 :            :  *     a.assoc("foo")      #=> nil
    3837                 :            :  */
    3838                 :            : 
    3839                 :            : VALUE
    3840                 :      21860 : rb_ary_assoc(VALUE ary, VALUE key)
    3841                 :            : {
    3842                 :            :     long i;
    3843                 :            :     VALUE v;
    3844                 :            : 
    3845         [ +  + ]:     158810 :     for (i = 0; i < RARRAY_LEN(ary); ++i) {
    3846                 :     141814 :         v = rb_check_array_type(RARRAY_AREF(ary, i));
    3847         [ +  + ]:     212709 :         if (!NIL_P(v) && RARRAY_LEN(v) > 0 &&
           [ +  +  +  + ]
    3848                 :      70900 :             rb_equal(RARRAY_AREF(v, 0), key))
    3849                 :      13362 :             return v;
    3850                 :            :     }
    3851                 :            :     return Qnil;
    3852                 :            : }
    3853                 :            : 
    3854                 :            : /*
    3855                 :            :  *  call-seq:
    3856                 :            :  *     ary.rassoc(obj) -> element_ary or nil
    3857                 :            :  *
    3858                 :            :  *  Searches through the array whose elements are also arrays.
    3859                 :            :  *
    3860                 :            :  *  Compares +obj+ with the second element of each contained array using
    3861                 :            :  *  <code>obj.==</code>.
    3862                 :            :  *
    3863                 :            :  *  Returns the first contained array that matches +obj+.
    3864                 :            :  *
    3865                 :            :  *  See also Array#assoc.
    3866                 :            :  *
    3867                 :            :  *     a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
    3868                 :            :  *     a.rassoc("two")    #=> [2, "two"]
    3869                 :            :  *     a.rassoc("four")   #=> nil
    3870                 :            :  */
    3871                 :            : 
    3872                 :            : VALUE
    3873                 :         15 : rb_ary_rassoc(VALUE ary, VALUE value)
    3874                 :            : {
    3875                 :            :     long i;
    3876                 :            :     VALUE v;
    3877                 :            : 
    3878         [ +  + ]:        102 :     for (i = 0; i < RARRAY_LEN(ary); ++i) {
    3879                 :         45 :         v = RARRAY_AREF(ary, i);
    3880 [ +  + ][ +  - ]:         87 :         if (RB_TYPE_P(v, T_ARRAY) &&
         [ +  + ][ +  + ]
    3881         [ +  + ]:         37 :             RARRAY_LEN(v) > 1 &&
    3882                 :         37 :             rb_equal(RARRAY_AREF(v, 1), value))
    3883                 :          9 :             return v;
    3884                 :            :     }
    3885                 :            :     return Qnil;
    3886                 :            : }
    3887                 :            : 
    3888                 :            : static VALUE
    3889                 :     356008 : recursive_equal(VALUE ary1, VALUE ary2, int recur)
    3890                 :            : {
    3891                 :            :     long i, len1;
    3892                 :            :     const VALUE *p1, *p2;
    3893                 :            : 
    3894         [ +  + ]:     356008 :     if (recur) return Qtrue; /* Subtle! */
    3895                 :            : 
    3896                 :     355967 :     p1 = RARRAY_CONST_PTR(ary1);
    3897                 :     355967 :     p2 = RARRAY_CONST_PTR(ary2);
    3898                 :     355967 :     len1 = RARRAY_LEN(ary1);
    3899                 :            : 
    3900         [ +  + ]:     918750 :     for (i = 0; i < len1; i++) {
    3901         [ +  + ]:     654767 :         if (*p1 != *p2) {
    3902         [ +  + ]:     329282 :             if (rb_equal(*p1, *p2)) {
    3903                 :     237299 :                 len1 = RARRAY_LEN(ary1);
    3904         [ +  - ]:     237299 :                 if (len1 != RARRAY_LEN(ary2))
    3905                 :            :                     return Qfalse;
    3906         [ +  + ]:     237299 :                 if (len1 < i)
    3907                 :            :                     return Qtrue;
    3908                 :     237298 :                 p1 = RARRAY_CONST_PTR(ary1) + i;
    3909                 :     237298 :                 p2 = RARRAY_CONST_PTR(ary2) + i;
    3910                 :            :             }
    3911                 :            :             else {
    3912                 :            :                 return Qfalse;
    3913                 :            :             }
    3914                 :            :         }
    3915                 :     562783 :         p1++;
    3916                 :     562783 :         p2++;
    3917                 :            :     }
    3918                 :            :     return Qtrue;
    3919                 :            : }
    3920                 :            : 
    3921                 :            : /*
    3922                 :            :  *  call-seq:
    3923                 :            :  *     ary == other_ary   ->   bool
    3924                 :            :  *
    3925                 :            :  *  Equality --- Two arrays are equal if they contain the same number of
    3926                 :            :  *  elements and if each element is equal to (according to Object#==) the
    3927                 :            :  *  corresponding element in +other_ary+.
    3928                 :            :  *
    3929                 :            :  *     [ "a", "c" ]    == [ "a", "c", 7 ]     #=> false
    3930                 :            :  *     [ "a", "c", 7 ] == [ "a", "c", 7 ]     #=> true
    3931                 :            :  *     [ "a", "c", 7 ] == [ "a", "d", "f" ]   #=> false
    3932                 :            :  *
    3933                 :            :  */
    3934                 :            : 
    3935                 :            : static VALUE
    3936                 :     488426 : rb_ary_equal(VALUE ary1, VALUE ary2)
    3937                 :            : {
    3938         [ +  + ]:     488426 :     if (ary1 == ary2) return Qtrue;
    3939 [ +  + ][ +  + ]:     480851 :     if (!RB_TYPE_P(ary2, T_ARRAY)) {
                 [ +  + ]
    3940         [ +  + ]:      40808 :         if (!rb_respond_to(ary2, idTo_ary)) {
    3941                 :            :             return Qfalse;
    3942                 :            :         }
    3943                 :         28 :         return rb_equal(ary2, ary1);
    3944                 :            :     }
    3945         [ +  + ]:     440043 :     if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
    3946         [ +  + ]:     356029 :     if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
    3947                 :     356008 :     return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
    3948                 :            : }
    3949                 :            : 
    3950                 :            : static VALUE
    3951                 :    7126348 : recursive_eql(VALUE ary1, VALUE ary2, int recur)
    3952                 :            : {
    3953                 :            :     long i;
    3954                 :            : 
    3955         [ +  + ]:    7126348 :     if (recur) return Qtrue; /* Subtle! */
    3956         [ +  + ]:   93115830 :     for (i=0; i<RARRAY_LEN(ary1); i++) {
    3957         [ +  + ]:   43006760 :         if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
    3958                 :            :             return Qfalse;
    3959                 :            :     }
    3960                 :            :     return Qtrue;
    3961                 :            : }
    3962                 :            : 
    3963                 :            : /*
    3964                 :            :  *  call-seq:
    3965                 :            :  *     ary.eql?(other)  -> true or false
    3966                 :            :  *
    3967                 :            :  *  Returns +true+ if +self+ and +other+ are the same object,
    3968                 :            :  *  or are both arrays with the same content (according to Object#eql?).
    3969                 :            :  */
    3970                 :            : 
    3971                 :            : static VALUE
    3972                 :    7126495 : rb_ary_eql(VALUE ary1, VALUE ary2)
    3973                 :            : {
    3974         [ +  + ]:    7126495 :     if (ary1 == ary2) return Qtrue;
    3975 [ +  + ][ +  - ]:    7126490 :     if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse;
                 [ +  + ]
    3976         [ +  + ]:    7126365 :     if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
    3977         [ +  - ]:    7126348 :     if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
    3978                 :    7126348 :     return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
    3979                 :            : }
    3980                 :            : 
    3981                 :            : /*
    3982                 :            :  *  call-seq:
    3983                 :            :  *     ary.hash   -> integer
    3984                 :            :  *
    3985                 :            :  *  Compute a hash-code for this array.
    3986                 :            :  *
    3987                 :            :  *  Two arrays with the same content will have the same hash code (and will
    3988                 :            :  *  compare using #eql?).
    3989                 :            :  *
    3990                 :            :  *  See also Object#hash.
    3991                 :            :  */
    3992                 :            : 
    3993                 :            : static VALUE
    3994                 :   15047220 : rb_ary_hash(VALUE ary)
    3995                 :            : {
    3996                 :            :     long i;
    3997                 :            :     st_index_t h;
    3998                 :            :     VALUE n;
    3999                 :            : 
    4000                 :   15047220 :     h = rb_hash_start(RARRAY_LEN(ary));
    4001                 :   15047220 :     h = rb_hash_uint(h, (st_index_t)rb_ary_hash);
    4002         [ +  + ]:  215394862 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    4003                 :   92650334 :         n = rb_hash(RARRAY_AREF(ary, i));
    4004                 :   92650211 :         h = rb_hash_uint(h, NUM2LONG(n));
    4005                 :            :     }
    4006                 :   15047097 :     h = rb_hash_end(h);
    4007                 :   15047097 :     return ST2FIX(h);
    4008                 :            : }
    4009                 :            : 
    4010                 :            : /*
    4011                 :            :  *  call-seq:
    4012                 :            :  *     ary.include?(object)   -> true or false
    4013                 :            :  *
    4014                 :            :  *  Returns +true+ if the given +object+ is present in +self+ (that is, if any
    4015                 :            :  *  element <code>==</code> +object+), otherwise returns +false+.
    4016                 :            :  *
    4017                 :            :  *     a = [ "a", "b", "c" ]
    4018                 :            :  *     a.include?("b")   #=> true
    4019                 :            :  *     a.include?("z")   #=> false
    4020                 :            :  */
    4021                 :            : 
    4022                 :            : VALUE
    4023                 :    1831172 : rb_ary_includes(VALUE ary, VALUE item)
    4024                 :            : {
    4025                 :            :     long i;
    4026                 :            :     VALUE e;
    4027                 :            : 
    4028         [ +  + ]:   18921766 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    4029                 :    7974252 :         e = RARRAY_AREF(ary, i);
    4030         [ +  + ]:    7974252 :         if (rb_equal(e, item)) {
    4031                 :            :             return Qtrue;
    4032                 :            :         }
    4033                 :            :     }
    4034                 :            :     return Qfalse;
    4035                 :            : }
    4036                 :            : 
    4037                 :            : static VALUE
    4038                 :    1212705 : rb_ary_includes_by_eql(VALUE ary, VALUE item)
    4039                 :            : {
    4040                 :            :     long i;
    4041                 :            :     VALUE e;
    4042                 :            : 
    4043         [ +  + ]:   12530878 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    4044                 :    5847258 :         e = RARRAY_AREF(ary, i);
    4045         [ +  + ]:    5847258 :         if (rb_eql(item, e)) {
    4046                 :            :             return Qtrue;
    4047                 :            :         }
    4048                 :            :     }
    4049                 :            :     return Qfalse;
    4050                 :            : }
    4051                 :            : 
    4052                 :            : static VALUE
    4053                 :    7133693 : recursive_cmp(VALUE ary1, VALUE ary2, int recur)
    4054                 :            : {
    4055                 :            :     long i, len;
    4056                 :            : 
    4057         [ +  - ]:    7133693 :     if (recur) return Qundef;   /* Subtle! */
    4058                 :    7133693 :     len = RARRAY_LEN(ary1);
    4059         [ +  + ]:    7133693 :     if (len > RARRAY_LEN(ary2)) {
    4060                 :        673 :         len = RARRAY_LEN(ary2);
    4061                 :            :     }
    4062         [ +  + ]:    9275641 :     for (i=0; i<len; i++) {
    4063                 :    9275079 :         VALUE e1 = rb_ary_elt(ary1, i), e2 = rb_ary_elt(ary2, i);
    4064                 :    9275079 :         VALUE v = rb_funcallv(e1, id_cmp, 1, &e2);
    4065         [ +  + ]:    9275079 :         if (v != INT2FIX(0)) {
    4066                 :    7133131 :             return v;
    4067                 :            :         }
    4068                 :            :     }
    4069                 :            :     return Qundef;
    4070                 :            : }
    4071                 :            : 
    4072                 :            : /*
    4073                 :            :  *  call-seq:
    4074                 :            :  *     ary <=> other_ary   ->  -1, 0, +1 or nil
    4075                 :            :  *
    4076                 :            :  *  Comparison --- Returns an integer (+-1+, +0+, or <code>+1</code>) if this
    4077                 :            :  *  array is less than, equal to, or greater than +other_ary+.
    4078                 :            :  *
    4079                 :            :  *  Each object in each array is compared (using the <=> operator).
    4080                 :            :  *
    4081                 :            :  *  Arrays are compared in an "element-wise" manner; the first element of +ary+
    4082                 :            :  *  is compared with the first one of +other_ary+ using the <=> operator, then
    4083                 :            :  *  each of the second elements, etc...
    4084                 :            :  *  As soon as the result of any such comparison is non zero (i.e. the two
    4085                 :            :  *  corresponding elements are not equal), that result is returned for the
    4086                 :            :  *  whole array comparison.
    4087                 :            :  *
    4088                 :            :  *  If all the elements are equal, then the result is based on a comparison of
    4089                 :            :  *  the array lengths. Thus, two arrays are "equal" according to Array#<=> if,
    4090                 :            :  *  and only if, they have the same length and the value of each element is
    4091                 :            :  *  equal to the value of the corresponding element in the other array.
    4092                 :            :  *
    4093                 :            :  *  +nil+ is returned if the +other_ary+ is not an array or if the comparison
    4094                 :            :  *  of two elements returned +nil+.
    4095                 :            :  *
    4096                 :            :  *     [ "a", "a", "c" ]    <=> [ "a", "b", "c" ]   #=> -1
    4097                 :            :  *     [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ]            #=> +1
    4098                 :            :  *     [ 1, 2 ]             <=> [ 1, :two ]         #=> nil
    4099                 :            :  *
    4100                 :            :  */
    4101                 :            : 
    4102                 :            : VALUE
    4103                 :    7133696 : rb_ary_cmp(VALUE ary1, VALUE ary2)
    4104                 :            : {
    4105                 :            :     long len;
    4106                 :            :     VALUE v;
    4107                 :            : 
    4108                 :    7133696 :     ary2 = rb_check_array_type(ary2);
    4109         [ +  + ]:    7133696 :     if (NIL_P(ary2)) return Qnil;
    4110         [ +  + ]:    7133695 :     if (ary1 == ary2) return INT2FIX(0);
    4111                 :    7133693 :     v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
    4112         [ +  + ]:    7133693 :     if (v != Qundef) return v;
    4113                 :       1124 :     len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
    4114         [ +  + ]:        562 :     if (len == 0) return INT2FIX(0);
    4115         [ +  + ]:         68 :     if (len > 0) return INT2FIX(1);
    4116                 :         54 :     return INT2FIX(-1);
    4117                 :            : }
    4118                 :            : 
    4119                 :            : static VALUE
    4120                 :     160198 : ary_add_hash(VALUE hash, VALUE ary)
    4121                 :            : {
    4122                 :            :     long i;
    4123                 :            : 
    4124         [ +  + ]:   12748296 :     for (i=0; i<RARRAY_LEN(ary); i++) {
    4125                 :    6213950 :         VALUE elt = RARRAY_AREF(ary, i);
    4126                 :    6213950 :         rb_hash_add_new_element(hash, elt, elt);
    4127                 :            :     }
    4128                 :     160198 :     return hash;
    4129                 :            : }
    4130                 :            : 
    4131                 :            : static inline VALUE
    4132                 :     160661 : ary_tmp_hash_new(VALUE ary)
    4133                 :            : {
    4134                 :     160661 :     long size = RARRAY_LEN(ary);
    4135                 :     160661 :     VALUE hash = rb_hash_new_with_size(size);
    4136                 :            : 
    4137                 :     160661 :     RBASIC_CLEAR_CLASS(hash);
    4138                 :     160661 :     return hash;
    4139                 :            : }
    4140                 :            : 
    4141                 :            : static VALUE
    4142                 :     160198 : ary_make_hash(VALUE ary)
    4143                 :            : {
    4144                 :     160198 :     VALUE hash = ary_tmp_hash_new(ary);
    4145                 :     160198 :     return ary_add_hash(hash, ary);
    4146                 :            : }
    4147                 :            : 
    4148                 :            : static VALUE
    4149                 :        463 : ary_add_hash_by(VALUE hash, VALUE ary)
    4150                 :            : {
    4151                 :            :     long i;
    4152                 :            : 
    4153         [ +  + ]:       4720 :     for (i = 0; i < RARRAY_LEN(ary); ++i) {
    4154                 :       1897 :         VALUE v = rb_ary_elt(ary, i), k = rb_yield(v);
    4155                 :       1897 :         rb_hash_add_new_element(hash, k, v);
    4156                 :            :     }
    4157                 :        463 :     return hash;
    4158                 :            : }
    4159                 :            : 
    4160                 :            : static VALUE
    4161                 :        463 : ary_make_hash_by(VALUE ary)
    4162                 :            : {
    4163                 :        463 :     VALUE hash = ary_tmp_hash_new(ary);
    4164                 :        463 :     return ary_add_hash_by(hash, ary);
    4165                 :            : }
    4166                 :            : 
    4167                 :            : static inline void
    4168                 :     143122 : ary_recycle_hash(VALUE hash)
    4169                 :            : {
    4170                 :            :     assert(RBASIC_CLASS(hash) == 0);
    4171         [ +  - ]:     143122 :     if (RHASH(hash)->ntbl) {
    4172                 :     143122 :         st_table *tbl = RHASH(hash)->ntbl;
    4173                 :     143122 :         st_free_table(tbl);
    4174                 :            :     }
    4175                 :     143122 :     rb_gc_force_recycle(hash);
    4176                 :     143122 : }
    4177                 :            : 
    4178                 :            : /*
    4179                 :            :  *  call-seq:
    4180                 :            :  *     ary - other_ary    -> new_ary
    4181                 :            :  *
    4182                 :            :  *  Array Difference
    4183                 :            :  *
    4184                 :            :  *  Returns a new array that is a copy of the original array, removing any
    4185                 :            :  *  items that also appear in +other_ary+. The order is preserved from the
    4186                 :            :  *  original array.
    4187                 :            :  *
    4188                 :            :  *  It compares elements using their #hash and #eql? methods for efficiency.
    4189                 :            :  *
    4190                 :            :  *     [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]
    4191                 :            :  *
    4192                 :            :  *  If you need set-like behavior, see the library class Set.
    4193                 :            :  */
    4194                 :            : 
    4195                 :            : static VALUE
    4196                 :     131466 : rb_ary_diff(VALUE ary1, VALUE ary2)
    4197                 :            : {
    4198                 :            :     VALUE ary3;
    4199                 :            :     VALUE hash;
    4200                 :            :     long i;
    4201                 :            : 
    4202                 :     131465 :     ary2 = to_ary(ary2);
    4203                 :     131465 :     ary3 = rb_ary_new();
    4204                 :            : 
    4205 [ +  + ][ +  + ]:     135844 :     if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
    4206         [ +  + ]:    2532832 :         for (i=0; i<RARRAY_LEN(ary1); i++) {
    4207                 :    1201842 :             VALUE elt = rb_ary_elt(ary1, i);
    4208         [ +  + ]:    1201842 :             if (rb_ary_includes_by_eql(ary2, elt)) continue;
    4209                 :     411115 :             rb_ary_push(ary3, elt);
    4210                 :            :         }
    4211                 :            :         return ary3;
    4212                 :            :     }
    4213                 :            : 
    4214                 :       2317 :     hash = ary_make_hash(ary2);
    4215         [ +  + ]:    6605542 :     for (i=0; i<RARRAY_LEN(ary1); i++) {
    4216         [ +  + ]:    3300454 :         if (st_lookup(rb_hash_tbl_raw(hash), RARRAY_AREF(ary1, i), 0)) continue;
    4217                 :      12300 :         rb_ary_push(ary3, rb_ary_elt(ary1, i));
    4218                 :            :     }
    4219                 :       2317 :     ary_recycle_hash(hash);
    4220                 :       2317 :     return ary3;
    4221                 :            : }
    4222                 :            : 
    4223                 :            : /*
    4224                 :            :  *  call-seq:
    4225                 :            :  *     ary & other_ary      -> new_ary
    4226                 :            :  *
    4227                 :            :  *  Set Intersection --- Returns a new array containing unique elements common to the
    4228                 :            :  *  two arrays. The order is preserved from the original array.
    4229                 :            :  *
    4230                 :            :  *  It compares elements using their #hash and #eql? methods for efficiency.
    4231                 :            :  *
    4232                 :            :  *     [ 1, 1, 3, 5 ] & [ 3, 2, 1 ]                 #=> [ 1, 3 ]
    4233                 :            :  *     [ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ]   #=> [ 'a', 'b' ]
    4234                 :            :  *
    4235                 :            :  *  See also Array#uniq.
    4236                 :            :  */
    4237                 :            : 
    4238                 :            : 
    4239                 :            : static VALUE
    4240                 :       2608 : rb_ary_and(VALUE ary1, VALUE ary2)
    4241                 :            : {
    4242                 :            :     VALUE hash, ary3, v;
    4243                 :            :     st_table *table;
    4244                 :            :     st_data_t vv;
    4245                 :            :     long i;
    4246                 :            : 
    4247                 :       2608 :     ary2 = to_ary(ary2);
    4248                 :       2608 :     ary3 = rb_ary_new();
    4249 [ +  + ][ +  + ]:       5133 :     if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;
    4250                 :            : 
    4251 [ +  + ][ +  + ]:       2548 :     if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
    4252         [ +  + ]:       2221 :         for (i=0; i<RARRAY_LEN(ary1); i++) {
    4253                 :       1023 :             v = RARRAY_AREF(ary1, i);
    4254         [ +  + ]:       1023 :             if (!rb_ary_includes_by_eql(ary2, v)) continue;
    4255         [ +  + ]:        111 :             if (rb_ary_includes_by_eql(ary3, v)) continue;
    4256                 :         99 :             rb_ary_push(ary3, v);
    4257                 :            :         }
    4258                 :            :         return ary3;
    4259                 :            :     }
    4260                 :            : 
    4261                 :       2195 :     hash = ary_make_hash(ary2);
    4262                 :       2195 :     table = rb_hash_tbl_raw(hash);
    4263                 :            : 
    4264         [ +  + ]:     103032 :     for (i=0; i<RARRAY_LEN(ary1); i++) {
    4265                 :      49321 :         v = RARRAY_AREF(ary1, i);
    4266                 :      49321 :         vv = (st_data_t)v;
    4267         [ +  + ]:      49321 :         if (st_delete(table, &vv, 0)) {
    4268                 :      29261 :             rb_ary_push(ary3, v);
    4269                 :            :         }
    4270                 :            :     }
    4271                 :       2195 :     ary_recycle_hash(hash);
    4272                 :            : 
    4273                 :       2195 :     return ary3;
    4274                 :            : }
    4275                 :            : 
    4276                 :            : static int
    4277                 :      21999 : ary_hash_orset(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
    4278                 :            : {
    4279         [ +  + ]:      21999 :     if (existing) return ST_STOP;
    4280                 :        505 :     *key = *value = (VALUE)arg;
    4281                 :        505 :     return ST_CONTINUE;
    4282                 :            : }
    4283                 :            : 
    4284                 :            : static void
    4285                 :       6498 : rb_ary_union(VALUE ary_union, VALUE ary)
    4286                 :            : {
    4287                 :            :     long i;
    4288         [ +  + ]:      32454 :     for (i = 0; i < RARRAY_LEN(ary); i++) {
    4289                 :       9729 :         VALUE elt = rb_ary_elt(ary, i);
    4290         [ +  + ]:       9729 :         if (rb_ary_includes_by_eql(ary_union, elt)) continue;
    4291                 :       6055 :         rb_ary_push(ary_union, elt);
    4292                 :            :     }
    4293                 :       6498 : }
    4294                 :            : 
    4295                 :            : static void
    4296                 :       2140 : rb_ary_union_hash(VALUE hash, VALUE ary2)
    4297                 :            : {
    4298                 :            :     long i;
    4299         [ +  + ]:      48278 :     for (i = 0; i < RARRAY_LEN(ary2); i++) {
    4300                 :      21999 :         VALUE elt = RARRAY_AREF(ary2, i);
    4301         [ +  + ]:      21999 :         if (!st_update(RHASH_TBL_RAW(hash), (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) {
    4302                 :        505 :             RB_OBJ_WRITTEN(hash, Qundef, elt);
    4303                 :            :         }
    4304                 :            :     }
    4305                 :       2140 : }
    4306                 :            : 
    4307                 :            : /*
    4308                 :            :  *  call-seq:
    4309                 :            :  *     ary | other_ary     -> new_ary
    4310                 :            :  *
    4311                 :            :  *  Set Union --- Returns a new array by joining +ary+ with +other_ary+,
    4312                 :            :  *  excluding any duplicates and preserving the order from the given arrays.
    4313                 :            :  *
    4314                 :            :  *  It compares elements using their #hash and #eql? methods for efficiency.
    4315                 :            :  *
    4316                 :            :  *     [ "a", "b", "c" ] | [ "c", "d", "a" ]    #=> [ "a", "b", "c", "d" ]
    4317                 :            :  *     [ "c", "d", "a" ] | [ "a", "b", "c" ]    #=> [ "c", "d", "a", "b" ]
    4318                 :            :  *
    4319                 :            :  *  See also Array#union.
    4320                 :            :  */
    4321                 :            : 
    4322                 :            : static VALUE
    4323                 :       5372 : rb_ary_or(VALUE ary1, VALUE ary2)
    4324                 :            : {
    4325                 :            :     VALUE hash, ary3;
    4326                 :            : 
    4327                 :       5372 :     ary2 = to_ary(ary2);
    4328         [ +  + ]:       5372 :     if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
    4329                 :       3235 :         ary3 = rb_ary_new();
    4330                 :       3235 :         rb_ary_union(ary3, ary1);
    4331                 :       3235 :         rb_ary_union(ary3, ary2);
    4332                 :       3235 :         return ary3;
    4333                 :            :     }
    4334                 :            : 
    4335                 :       2137 :     hash = ary_make_hash(ary1);
    4336                 :       2137 :     rb_ary_union_hash(hash, ary2);
    4337                 :            : 
    4338                 :       2137 :     ary3 = rb_hash_values(hash);
    4339                 :       2137 :     ary_recycle_hash(hash);
    4340                 :       2137 :     return ary3;
    4341                 :            : }
    4342                 :            : 
    4343                 :            : /*
    4344                 :            :  *  call-seq:
    4345                 :            :  *     ary.union(other_ary1, other_ary2,...)   -> ary
    4346                 :            :  *
    4347                 :            :  *  Set Union --- Returns a new array by joining +other_ary+s with +self+,
    4348                 :            :  *  excluding any duplicates and preserving the order from the given arrays.
    4349                 :            :  *
    4350                 :            :  *  It compares elements using their #hash and #eql? methods for efficiency.
    4351                 :            :  *
    4352                 :            :  *     [ "a", "b", "c" ].union( [ "c", "d", "a" ] )    #=> [ "a", "b", "c", "d" ]
    4353                 :            :  *     [ "a" ].union( ["e", "b"], ["a", "c", "b"] )    #=> [ "a", "e", "b", "c" ]
    4354                 :            :  *     [ "a" ].union #=> [ "a" ]
    4355                 :            :  *
    4356                 :            :  *  See also Array#|.
    4357                 :            :  */
    4358                 :            : 
    4359                 :            : static VALUE
    4360                 :         13 : rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
    4361                 :            : {
    4362                 :            :     int i;
    4363                 :            :     long sum;
    4364                 :            :     VALUE hash, ary_union;
    4365                 :            : 
    4366                 :         13 :     sum = RARRAY_LEN(ary);
    4367         [ +  + ]:         33 :     for (i = 0; i < argc; i++){
    4368                 :         40 :         argv[i] = to_ary(argv[i]);
    4369                 :         40 :         sum += RARRAY_LEN(argv[i]);
    4370                 :            :     }
    4371                 :            : 
    4372         [ +  + ]:         13 :     if (sum <= SMALL_ARRAY_LEN) {
    4373                 :         11 :         ary_union = rb_ary_new();
    4374                 :            : 
    4375                 :         11 :         rb_ary_union(ary_union, ary);
    4376         [ +  + ]:         28 :         for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);
    4377                 :            : 
    4378                 :            :         return ary_union;
    4379                 :            :     }
    4380                 :            : 
    4381                 :          2 :     hash = ary_make_hash(ary);
    4382         [ +  + ]:          5 :     for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);
    4383                 :            : 
    4384                 :          2 :     ary_union = rb_hash_values(hash);
    4385                 :          2 :     ary_recycle_hash(hash);
    4386                 :          2 :     return ary_union;
    4387                 :            : }
    4388                 :            : 
    4389                 :            : /*
    4390                 :            :  *  call-seq:
    4391                 :            :  *     ary.max                     -> obj
    4392                 :            :  *     ary.max {|a, b| block}      -> obj
    4393                 :            :  *     ary.max(n)                  -> array
    4394                 :            :  *     ary.max(n) {|a, b| block}   -> array
    4395                 :            :  *
    4396                 :            :  *  Returns the object in _ary_ with the maximum value. The
    4397                 :            :  *  first form assumes all objects implement <code>Comparable</code>;
    4398                 :            :  *  the second uses the block to return <em>a <=> b</em>.
    4399                 :            :  *
    4400                 :            :  *     ary = %w(albatross dog horse)
    4401                 :            :  *     ary.max                                   #=> "horse"
    4402                 :            :  *     ary.max {|a, b| a.length <=> b.length}    #=> "albatross"
    4403                 :            :  *
    4404                 :            :  *  If the +n+ argument is given, maximum +n+ elements are returned
    4405                 :            :  *  as an array.
    4406                 :            :  *
    4407                 :            :  *     ary = %w[albatross dog horse]
    4408                 :            :  *     ary.max(2)                                  #=> ["horse", "dog"]
    4409                 :            :  *     ary.max(2) {|a, b| a.length <=> b.length }  #=> ["albatross", "horse"]
    4410                 :            :  */
    4411                 :            : static VALUE
    4412                 :     594083 : rb_ary_max(int argc, VALUE *argv, VALUE ary)
    4413                 :            : {
    4414                 :     594083 :     struct cmp_opt_data cmp_opt = { 0, 0 };
    4415                 :     594083 :     VALUE result = Qundef, v;
    4416                 :            :     VALUE num;
    4417                 :            :     long i;
    4418                 :            : 
    4419                 :    4158581 :     rb_scan_args(argc, argv, "01", &num);
    4420                 :            : 
    4421         [ +  + ]:     594083 :     if (!NIL_P(num))
    4422                 :          3 :        return rb_nmin_run(ary, num, 0, 1, 1);
    4423                 :            : 
    4424         [ +  + ]:     594080 :     if (rb_block_given_p()) {
    4425         [ +  + ]:        143 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    4426                 :         65 :            v = RARRAY_AREF(ary, i);
    4427 [ +  + ][ +  + ]:         65 :            if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
    4428                 :         33 :                result = v;
    4429                 :            :            }
    4430                 :            :         }
    4431                 :            :     }
    4432                 :            :     else {
    4433         [ +  + ]:    6105411 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    4434                 :    2755673 :            v = RARRAY_AREF(ary, i);
    4435 [ +  + ][ +  + ]:    2755673 :            if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) > 0) {
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
         [ +  + ][ +  - ]
         [ -  + ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
    4436                 :     991185 :                result = v;
    4437                 :            :            }
    4438                 :            :         }
    4439                 :            :     }
    4440         [ +  + ]:     594079 :     if (result == Qundef) return Qnil;
    4441                 :     594077 :     return result;
    4442                 :            : }
    4443                 :            : 
    4444                 :            : /*
    4445                 :            :  *  call-seq:
    4446                 :            :  *     ary.min                     -> obj
    4447                 :            :  *     ary.min {| a,b | block }    -> obj
    4448                 :            :  *     ary.min(n)                  -> array
    4449                 :            :  *     ary.min(n) {| a,b | block } -> array
    4450                 :            :  *
    4451                 :            :  *  Returns the object in _ary_ with the minimum value. The
    4452                 :            :  *  first form assumes all objects implement <code>Comparable</code>;
    4453                 :            :  *  the second uses the block to return <em>a <=> b</em>.
    4454                 :            :  *
    4455                 :            :  *     ary = %w(albatross dog horse)
    4456                 :            :  *     ary.min                                   #=> "albatross"
    4457                 :            :  *     ary.min {|a, b| a.length <=> b.length}    #=> "dog"
    4458                 :            :  *
    4459                 :            :  *  If the +n+ argument is given, minimum +n+ elements are returned
    4460                 :            :  *  as an array.
    4461                 :            :  *
    4462                 :            :  *     ary = %w[albatross dog horse]
    4463                 :            :  *     ary.min(2)                                  #=> ["albatross", "dog"]
    4464                 :            :  *     ary.min(2) {|a, b| a.length <=> b.length }  #=> ["dog", "horse"]
    4465                 :            :  */
    4466                 :            : static VALUE
    4467                 :     550790 : rb_ary_min(int argc, VALUE *argv, VALUE ary)
    4468                 :            : {
    4469                 :     550790 :     struct cmp_opt_data cmp_opt = { 0, 0 };
    4470                 :     550790 :     VALUE result = Qundef, v;
    4471                 :            :     VALUE num;
    4472                 :            :     long i;
    4473                 :            : 
    4474                 :    3855530 :     rb_scan_args(argc, argv, "01", &num);
    4475                 :            : 
    4476         [ +  + ]:     550790 :     if (!NIL_P(num))
    4477                 :          5 :        return rb_nmin_run(ary, num, 0, 0, 1);
    4478                 :            : 
    4479         [ +  + ]:     550785 :     if (rb_block_given_p()) {
    4480         [ +  + ]:        163 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    4481                 :         74 :            v = RARRAY_AREF(ary, i);
    4482 [ +  + ][ +  + ]:         74 :            if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
    4483                 :         34 :                result = v;
    4484                 :            :            }
    4485                 :            :         }
    4486                 :            :     }
    4487                 :            :     else {
    4488         [ +  + ]:    2426662 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    4489                 :     937947 :            v = RARRAY_AREF(ary, i);
    4490 [ +  + ][ +  + ]:     937947 :            if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) < 0) {
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
         [ +  + ][ +  - ]
         [ -  + ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ +  + ]
    4491                 :     557102 :                result = v;
    4492                 :            :            }
    4493                 :            :         }
    4494                 :            :     }
    4495         [ +  - ]:     550784 :     if (result == Qundef) return Qnil;
    4496                 :     550784 :     return result;
    4497                 :            : }
    4498                 :            : 
    4499                 :            : static int
    4500                 :      19796 : push_value(st_data_t key, st_data_t val, st_data_t ary)
    4501                 :            : {
    4502                 :      19796 :     rb_ary_push((VALUE)ary, (VALUE)val);
    4503                 :      19796 :     return ST_CONTINUE;
    4504                 :            : }
    4505                 :            : 
    4506                 :            : /*
    4507                 :            :  *  call-seq:
    4508                 :            :  *     ary.uniq!                -> ary or nil
    4509                 :            :  *     ary.uniq! {|item| ...}   -> ary or nil
    4510                 :            :  *
    4511                 :            :  *  Removes duplicate elements from +self+.
    4512                 :            :  *
    4513                 :            :  *  If a block is given, it will use the return value of the block for
    4514                 :            :  *  comparison.
    4515                 :            :  *
    4516                 :            :  *  It compares values using their #hash and #eql? methods for efficiency.
    4517                 :            :  *
    4518                 :            :  *  +self+ is traversed in order, and the first occurrence is kept.
    4519                 :            :  *
    4520                 :            :  *  Returns +nil+ if no changes are made (that is, no duplicates are found).
    4521                 :            :  *
    4522                 :            :  *     a = [ "a", "a", "b", "b", "c" ]
    4523                 :            :  *     a.uniq!   # => ["a", "b", "c"]
    4524                 :            :  *
    4525                 :            :  *     b = [ "a", "b", "c" ]
    4526                 :            :  *     b.uniq!   # => nil
    4527                 :            :  *
    4528                 :            :  *     c = [["student","sam"], ["student","george"], ["teacher","matz"]]
    4529                 :            :  *     c.uniq! {|s| s.first}   # => [["student", "sam"], ["teacher", "matz"]]
    4530                 :            :  *
    4531                 :            :  */
    4532                 :            : 
    4533                 :            : static VALUE
    4534                 :     219093 : rb_ary_uniq_bang(VALUE ary)
    4535                 :            : {
    4536                 :            :     VALUE hash;
    4537                 :            :     long hash_size;
    4538                 :            : 
    4539                 :     219093 :     rb_ary_modify_check(ary);
    4540         [ +  + ]:     219088 :     if (RARRAY_LEN(ary) <= 1)
    4541                 :            :         return Qnil;
    4542         [ +  + ]:      23807 :     if (rb_block_given_p())
    4543                 :         13 :         hash = ary_make_hash_by(ary);
    4544                 :            :     else
    4545                 :      23794 :         hash = ary_make_hash(ary);
    4546                 :            : 
    4547         [ +  - ]:      23807 :     hash_size = RHASH_SIZE(hash);
    4548         [ +  + ]:      23807 :     if (RARRAY_LEN(ary) == hash_size) {
    4549                 :            :         return Qnil;
    4550                 :            :     }
    4551                 :       6269 :     rb_ary_modify_check(ary);
    4552 [ +  - ][ +  - ]:       6268 :     ARY_SET_LEN(ary, 0);
         [ +  - ][ +  + ]
                 [ +  + ]
    4553 [ +  - ][ +  - ]:       6268 :     if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4554                 :          3 :         rb_ary_unshare(ary);
    4555 [ +  - ][ +  - ]:          3 :         FL_SET_EMBED(ary);
                 [ +  - ]
    4556                 :            :     }
    4557                 :       6268 :     ary_resize_capa(ary, hash_size);
    4558                 :       6268 :     st_foreach(rb_hash_tbl_raw(hash), push_value, ary);
    4559                 :       6268 :     ary_recycle_hash(hash);
    4560                 :            : 
    4561                 :       6268 :     return ary;
    4562                 :            : }
    4563                 :            : 
    4564                 :            : /*
    4565                 :            :  *  call-seq:
    4566                 :            :  *     ary.uniq                -> new_ary
    4567                 :            :  *     ary.uniq {|item| ...}   -> new_ary
    4568                 :            :  *
    4569                 :            :  *  Returns a new array by removing duplicate values in +self+.
    4570                 :            :  *
    4571                 :            :  *  If a block is given, it will use the return value of the block for comparison.
    4572                 :            :  *
    4573                 :            :  *  It compares values using their #hash and #eql? methods for efficiency.
    4574                 :            :  *
    4575                 :            :  *  +self+ is traversed in order, and the first occurrence is kept.
    4576                 :            :  *
    4577                 :            :  *     a = [ "a", "a", "b", "b", "c" ]
    4578                 :            :  *     a.uniq   # => ["a", "b", "c"]
    4579                 :            :  *
    4580                 :            :  *     b = [["student","sam"], ["student","george"], ["teacher","matz"]]
    4581                 :            :  *     b.uniq {|s| s.first}   # => [["student", "sam"], ["teacher", "matz"]]
    4582                 :            :  *
    4583                 :            :  */
    4584                 :            : 
    4585                 :            : static VALUE
    4586                 :    1580729 : rb_ary_uniq(VALUE ary)
    4587                 :            : {
    4588                 :            :     VALUE hash, uniq;
    4589                 :            : 
    4590         [ +  + ]:    1580729 :     if (RARRAY_LEN(ary) <= 1)
    4591                 :    1450526 :         return rb_ary_dup(ary);
    4592         [ +  + ]:     130203 :     if (rb_block_given_p()) {
    4593                 :        450 :         hash = ary_make_hash_by(ary);
    4594                 :        450 :         uniq = rb_hash_values(hash);
    4595                 :            :     }
    4596                 :            :     else {
    4597                 :     129753 :         hash = ary_make_hash(ary);
    4598                 :     129753 :         uniq = rb_hash_values(hash);
    4599                 :            :     }
    4600                 :     130203 :     RBASIC_SET_CLASS(uniq, rb_obj_class(ary));
    4601                 :     130203 :     ary_recycle_hash(hash);
    4602                 :            : 
    4603                 :     130203 :     return uniq;
    4604                 :            : }
    4605                 :            : 
    4606                 :            : /*
    4607                 :            :  *  call-seq:
    4608                 :            :  *     ary.compact!    -> ary  or  nil
    4609                 :            :  *
    4610                 :            :  *  Removes +nil+ elements from the array.
    4611                 :            :  *
    4612                 :            :  *  Returns +nil+ if no changes were made, otherwise returns the array.
    4613                 :            :  *
    4614                 :            :  *     [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
    4615                 :            :  *     [ "a", "b", "c" ].compact!           #=> nil
    4616                 :            :  */
    4617                 :            : 
    4618                 :            : static VALUE
    4619                 :     411452 : rb_ary_compact_bang(VALUE ary)
    4620                 :            : {
    4621                 :            :     VALUE *p, *t, *end;
    4622                 :            :     long n;
    4623                 :            : 
    4624                 :     411452 :     rb_ary_modify(ary);
    4625                 :     411451 :     p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
    4626                 :     411451 :     end = p + RARRAY_LEN(ary);
    4627                 :            : 
    4628         [ +  + ]:    3926554 :     while (t < end) {
    4629         [ +  + ]:    3515103 :         if (NIL_P(*t)) t++;
    4630                 :    3515103 :         else *p++ = *t++;
    4631                 :            :     }
    4632                 :     822902 :     n = p - RARRAY_CONST_PTR(ary);
    4633         [ +  + ]:     411451 :     if (RARRAY_LEN(ary) == n) {
    4634                 :            :         return Qnil;
    4635                 :            :     }
    4636                 :      44612 :     ary_resize_smaller(ary, n);
    4637                 :            : 
    4638                 :      44612 :     return ary;
    4639                 :            : }
    4640                 :            : 
    4641                 :            : /*
    4642                 :            :  *  call-seq:
    4643                 :            :  *     ary.compact     -> new_ary
    4644                 :            :  *
    4645                 :            :  *  Returns a copy of +self+ with all +nil+ elements removed.
    4646                 :            :  *
    4647                 :            :  *     [ "a", nil, "b", nil, "c", nil ].compact
    4648                 :            :  *                       #=> [ "a", "b", "c" ]
    4649                 :            :  */
    4650                 :            : 
    4651                 :            : static VALUE
    4652                 :     205613 : rb_ary_compact(VALUE ary)
    4653                 :            : {
    4654                 :     205613 :     ary = rb_ary_dup(ary);
    4655                 :     205613 :     rb_ary_compact_bang(ary);
    4656                 :     205613 :     return ary;
    4657                 :            : }
    4658                 :            : 
    4659                 :            : /*
    4660                 :            :  *  call-seq:
    4661                 :            :  *     ary.count                   -> int
    4662                 :            :  *     ary.count(obj)              -> int
    4663                 :            :  *     ary.count {|item| block}    -> int
    4664                 :            :  *
    4665                 :            :  *  Returns the number of elements.
    4666                 :            :  *
    4667                 :            :  *  If an argument is given, counts the number of elements which equal +obj+
    4668                 :            :  *  using <code>==</code>.
    4669                 :            :  *
    4670                 :            :  *  If a block is given, counts the number of elements for which the block
    4671                 :            :  *  returns a true value.
    4672                 :            :  *
    4673                 :            :  *     ary = [1, 2, 4, 2]
    4674                 :            :  *     ary.count                  #=> 4
    4675                 :            :  *     ary.count(2)               #=> 2
    4676                 :            :  *     ary.count {|x| x%2 == 0}   #=> 3
    4677                 :            :  *
    4678                 :            :  */
    4679                 :            : 
    4680                 :            : static VALUE
    4681                 :      26410 : rb_ary_count(int argc, VALUE *argv, VALUE ary)
    4682                 :            : {
    4683                 :      26410 :     long i, n = 0;
    4684                 :            : 
    4685         [ +  + ]:      26410 :     if (argc == 0) {
    4686                 :            :         VALUE v;
    4687                 :            : 
    4688         [ +  + ]:      26401 :         if (!rb_block_given_p())
    4689                 :      26237 :             return LONG2NUM(RARRAY_LEN(ary));
    4690                 :            : 
    4691         [ +  + ]:      30592 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    4692                 :      15214 :             v = RARRAY_AREF(ary, i);
    4693         [ +  + ]:      15214 :             if (RTEST(rb_yield(v))) n++;
    4694                 :            :         }
    4695                 :            :     }
    4696                 :            :     else {
    4697                 :            :         VALUE obj;
    4698                 :            : 
    4699                 :         63 :         rb_scan_args(argc, argv, "1", &obj);
    4700         [ +  + ]:          8 :         if (rb_block_given_p()) {
    4701                 :          8 :             rb_warn("given block not used");
    4702                 :            :         }
    4703         [ +  + ]:         90 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    4704         [ +  + ]:         41 :             if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
    4705                 :            :         }
    4706                 :            :     }
    4707                 :            : 
    4708                 :        172 :     return LONG2NUM(n);
    4709                 :            : }
    4710                 :            : 
    4711                 :            : static VALUE
    4712                 :    2174726 : flatten(VALUE ary, int level, int *modified)
    4713                 :            : {
    4714                 :    2174726 :     long i = 0;
    4715                 :            :     VALUE stack, result, tmp, elt;
    4716                 :            :     st_table *memo;
    4717                 :            :     st_data_t id;
    4718                 :            : 
    4719                 :    2174726 :     stack = ary_new(0, ARY_DEFAULT_SIZE);
    4720                 :    2174726 :     result = ary_new(0, RARRAY_LEN(ary));
    4721                 :    2174726 :     memo = st_init_numtable();
    4722                 :    2174726 :     st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue);
    4723                 :    2174726 :     *modified = 0;
    4724                 :            : 
    4725                 :            :     while (1) {
    4726         [ +  + ]:    9802220 :         while (i < RARRAY_LEN(ary)) {
    4727                 :    6782312 :             elt = RARRAY_AREF(ary, i++);
    4728 [ +  + ][ +  + ]:    6782456 :             if (level >= 0 && RARRAY_LEN(stack) / 2 >= level) {
    4729                 :         57 :                 rb_ary_push(result, elt);
    4730                 :         57 :                 continue;
    4731                 :            :             }
    4732                 :    6782252 :             tmp = rb_check_array_type(elt);
    4733         [ +  + ]:    6782252 :             if (RBASIC(result)->klass) {
    4734                 :          2 :                 rb_raise(rb_eRuntimeError, "flatten reentered");
    4735                 :            :             }
    4736         [ +  + ]:    6782250 :             if (NIL_P(tmp)) {
    4737                 :    5937048 :                 rb_ary_push(result, elt);
    4738                 :            :             }
    4739                 :            :             else {
    4740                 :     845202 :                 *modified = 1;
    4741                 :     845202 :                 id = (st_data_t)tmp;
    4742         [ +  + ]:     845202 :                 if (st_lookup(memo, id, 0)) {
    4743                 :          5 :                     st_free_table(memo);
    4744                 :          5 :                     rb_raise(rb_eArgError, "tried to flatten recursive array");
    4745                 :            :                 }
    4746                 :     845197 :                 st_insert(memo, id, (st_data_t)Qtrue);
    4747                 :     845197 :                 rb_ary_push(stack, ary);
    4748                 :     845197 :                 rb_ary_push(stack, LONG2NUM(i));
    4749                 :     845197 :                 ary = tmp;
    4750                 :    7627494 :                 i = 0;
    4751                 :            :             }
    4752                 :            :         }
    4753         [ +  + ]:    3019908 :         if (RARRAY_LEN(stack) == 0) {
    4754                 :            :             break;
    4755                 :            :         }
    4756                 :     845192 :         id = (st_data_t)ary;
    4757                 :     845192 :         st_delete(memo, &id, 0);
    4758                 :     845192 :         tmp = rb_ary_pop(stack);
    4759                 :     845192 :         i = NUM2LONG(tmp);
    4760                 :     845192 :         ary = rb_ary_pop(stack);
    4761                 :     845192 :     }
    4762                 :            : 
    4763                 :    2174716 :     st_free_table(memo);
    4764                 :            : 
    4765                 :    2174716 :     RBASIC_SET_CLASS(result, rb_obj_class(ary));
    4766                 :    2174716 :     return result;
    4767                 :            : }
    4768                 :            : 
    4769                 :            : /*
    4770                 :            :  *  call-seq:
    4771                 :            :  *     ary.flatten!        -> ary or nil
    4772                 :            :  *     ary.flatten!(level) -> ary or nil
    4773                 :            :  *
    4774                 :            :  *  Flattens +self+ in place.
    4775                 :            :  *
    4776                 :            :  *  Returns +nil+ if no modifications were made (i.e., the array contains no
    4777                 :            :  *  subarrays.)
    4778                 :            :  *
    4779                 :            :  *  The optional +level+ argument determines the level of recursion to flatten.
    4780                 :            :  *
    4781                 :            :  *     a = [ 1, 2, [3, [4, 5] ] ]
    4782                 :            :  *     a.flatten!   #=> [1, 2, 3, 4, 5]
    4783                 :            :  *     a.flatten!   #=> nil
    4784                 :            :  *     a            #=> [1, 2, 3, 4, 5]
    4785                 :            :  *     a = [ 1, 2, [3, [4, 5] ] ]
    4786                 :            :  *     a.flatten!(1) #=> [1, 2, 3, [4, 5]]
    4787                 :            :  */
    4788                 :            : 
    4789                 :            : static VALUE
    4790                 :       4271 : rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
    4791                 :            : {
    4792                 :       4271 :     int mod = 0, level = -1;
    4793                 :            :     VALUE result, lv;
    4794                 :            : 
    4795                 :      29897 :     rb_scan_args(argc, argv, "01", &lv);
    4796                 :       4269 :     rb_ary_modify_check(ary);
    4797         [ +  + ]:       4264 :     if (!NIL_P(lv)) level = NUM2INT(lv);
    4798         [ +  + ]:       4262 :     if (level == 0) return Qnil;
    4799                 :            : 
    4800                 :       4259 :     result = flatten(ary, level, &mod);
    4801         [ +  + ]:       4256 :     if (mod == 0) {
    4802                 :            :         ary_discard(result);
    4803                 :       4082 :         return Qnil;
    4804                 :            :     }
    4805 [ +  - ][ +  - ]:        174 :     if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
         [ +  - ][ +  + ]
                 [ +  + ]
    4806                 :        174 :     rb_ary_replace(ary, result);
    4807         [ +  + ]:        174 :     if (mod) ARY_SET_EMBED_LEN(result, 0);
    4808                 :            : 
    4809                 :        174 :     return ary;
    4810                 :            : }
    4811                 :            : 
    4812                 :            : /*
    4813                 :            :  *  call-seq:
    4814                 :            :  *     ary.flatten -> new_ary
    4815                 :            :  *     ary.flatten(level) -> new_ary
    4816                 :            :  *
    4817                 :            :  *  Returns a new array that is a one-dimensional flattening of +self+
    4818                 :            :  *  (recursively).
    4819                 :            :  *
    4820                 :            :  *  That is, for every element that is an array, extract its elements into
    4821                 :            :  *  the new array.
    4822                 :            :  *
    4823                 :            :  *  The optional +level+ argument determines the level of recursion to
    4824                 :            :  *  flatten.
    4825                 :            :  *
    4826                 :            :  *     s = [ 1, 2, 3 ]           #=> [1, 2, 3]
    4827                 :            :  *     t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
    4828                 :            :  *     a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
    4829                 :            :  *     a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    4830                 :            :  *     a = [ 1, 2, [3, [4, 5] ] ]
    4831                 :            :  *     a.flatten(1)              #=> [1, 2, 3, [4, 5]]
    4832                 :            :  */
    4833                 :            : 
    4834                 :            : static VALUE
    4835                 :    2170472 : rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
    4836                 :            : {
    4837                 :    2170472 :     int mod = 0, level = -1;
    4838                 :            :     VALUE result, lv;
    4839                 :            : 
    4840                 :   15193304 :     rb_scan_args(argc, argv, "01", &lv);
    4841         [ +  + ]:    2170472 :     if (!NIL_P(lv)) level = NUM2INT(lv);
    4842         [ +  + ]:    2170470 :     if (level == 0) return ary_make_shared_copy(ary);
    4843                 :            : 
    4844                 :    2170467 :     result = flatten(ary, level, &mod);
    4845 [ +  - ][ +  - ]:    2170460 :     OBJ_INFECT(result, ary);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4846                 :            : 
    4847                 :    2170460 :     return result;
    4848                 :            : }
    4849                 :            : 
    4850                 :            : #define OPTHASH_GIVEN_P(opts) \
    4851                 :            :     (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
    4852                 :            : static ID id_random;
    4853                 :            : 
    4854                 :            : #define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
    4855                 :            : 
    4856                 :            : /*
    4857                 :            :  *  call-seq:
    4858                 :            :  *     ary.shuffle!              -> ary
    4859                 :            :  *     ary.shuffle!(random: rng) -> ary
    4860                 :            :  *
    4861                 :            :  *  Shuffles elements in +self+ in place.
    4862                 :            :  *
    4863                 :            :  *     a = [ 1, 2, 3 ]           #=> [1, 2, 3]
    4864                 :            :  *     a.shuffle!                #=> [2, 3, 1]
    4865                 :            :  *     a                         #=> [2, 3, 1]
    4866                 :            :  *
    4867                 :            :  *  The optional +rng+ argument will be used as the random number generator.
    4868                 :            :  *
    4869                 :            :  *     a.shuffle!(random: Random.new(1))  #=> [1, 3, 2]
    4870                 :            :  */
    4871                 :            : 
    4872                 :            : static VALUE
    4873                 :        354 : rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
    4874                 :            : {
    4875                 :        354 :     VALUE opts, randgen = rb_cRandom;
    4876                 :            :     long i, len;
    4877                 :            : 
    4878 [ +  + ][ +  - ]:        354 :     if (OPTHASH_GIVEN_P(opts)) {
    4879                 :            :         VALUE rnd;
    4880                 :            :         ID keyword_ids[1];
    4881                 :            : 
    4882                 :        116 :         keyword_ids[0] = id_random;
    4883                 :        116 :         rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
    4884         [ +  + ]:        114 :         if (rnd != Qundef) {
    4885                 :        114 :             randgen = rnd;
    4886                 :            :         }
    4887                 :            :     }
    4888                 :        352 :     rb_check_arity(argc, 0, 0);
    4889                 :        351 :     rb_ary_modify(ary);
    4890                 :        349 :     i = len = RARRAY_LEN(ary);
    4891 [ +  + ][ -  + ]:      22746 :     RARRAY_PTR_USE(ary, ptr, {
                 [ +  + ]
    4892                 :            :         while (i) {
    4893                 :            :             long j = RAND_UPTO(i);
    4894                 :            :             VALUE tmp;
    4895                 :            :             if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
    4896                 :            :                 rb_raise(rb_eRuntimeError, "modified during shuffle");
    4897                 :            :             }
    4898                 :            :             tmp = ptr[--i];
    4899                 :            :             ptr[i] = ptr[j];
    4900                 :            :             ptr[j] = tmp;
    4901                 :            :         }
    4902                 :            :     }); /* WB: no new reference */
    4903                 :        342 :     return ary;
    4904                 :            : }
    4905                 :            : 
    4906                 :            : 
    4907                 :            : /*
    4908                 :            :  *  call-seq:
    4909                 :            :  *     ary.shuffle              -> new_ary
    4910                 :            :  *     ary.shuffle(random: rng) -> new_ary
    4911                 :            :  *
    4912                 :            :  *  Returns a new array with elements of +self+ shuffled.
    4913                 :            :  *
    4914                 :            :  *     a = [ 1, 2, 3 ]           #=> [1, 2, 3]
    4915                 :            :  *     a.shuffle                 #=> [2, 3, 1]
    4916                 :            :  *     a                         #=> [1, 2, 3]
    4917                 :            :  *
    4918                 :            :  *  The optional +rng+ argument will be used as the random number generator.
    4919                 :            :  *
    4920                 :            :  *     a.shuffle(random: Random.new(1))  #=> [1, 3, 2]
    4921                 :            :  */
    4922                 :            : 
    4923                 :            : static VALUE
    4924                 :        339 : rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
    4925                 :            : {
    4926                 :        339 :     ary = rb_ary_dup(ary);
    4927                 :        339 :     rb_ary_shuffle_bang(argc, argv, ary);
    4928                 :        332 :     return ary;
    4929                 :            : }
    4930                 :            : 
    4931                 :            : 
    4932                 :            : /*
    4933                 :            :  *  call-seq:
    4934                 :            :  *     ary.sample                  -> obj
    4935                 :            :  *     ary.sample(random: rng)     -> obj
    4936                 :            :  *     ary.sample(n)               -> new_ary
    4937                 :            :  *     ary.sample(n, random: rng)  -> new_ary
    4938                 :            :  *
    4939                 :            :  *  Choose a random element or +n+ random elements from the array.
    4940                 :            :  *
    4941                 :            :  *  The elements are chosen by using random and unique indices into the array
    4942                 :            :  *  in order to ensure that an element doesn't repeat itself unless the array
    4943                 :            :  *  already contained duplicate elements.
    4944                 :            :  *
    4945                 :            :  *  If the array is empty the first form returns +nil+ and the second form
    4946                 :            :  *  returns an empty array.
    4947                 :            :  *
    4948                 :            :  *     a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
    4949                 :            :  *     a.sample         #=> 7
    4950                 :            :  *     a.sample(4)      #=> [6, 4, 2, 5]
    4951                 :            :  *
    4952                 :            :  *  The optional +rng+ argument will be used as the random number generator.
    4953                 :            :  *
    4954                 :            :  *     a.sample(random: Random.new(1))     #=> 6
    4955                 :            :  *     a.sample(4, random: Random.new(1))  #=> [6, 10, 9, 2]
    4956                 :            :  */
    4957                 :            : 
    4958                 :            : 
    4959                 :            : static VALUE
    4960                 :      39664 : rb_ary_sample(int argc, VALUE *argv, VALUE ary)
    4961                 :            : {
    4962                 :            :     VALUE nv, result;
    4963                 :      39664 :     VALUE opts, randgen = rb_cRandom;
    4964                 :            :     long n, len, i, j, k, idx[10];
    4965                 :            :     long rnds[numberof(idx)];
    4966                 :            :     long memo_threshold;
    4967                 :            : 
    4968 [ +  + ][ +  + ]:      39664 :     if (OPTHASH_GIVEN_P(opts)) {
    4969                 :            :         VALUE rnd;
    4970                 :            :         ID keyword_ids[1];
    4971                 :            : 
    4972                 :       2234 :         keyword_ids[0] = id_random;
    4973                 :       2234 :         rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
    4974         [ +  + ]:       2232 :         if (rnd != Qundef) {
    4975                 :       2232 :             randgen = rnd;
    4976                 :            :         }
    4977                 :            :     }
    4978                 :      79324 :     len = RARRAY_LEN(ary);
    4979         [ +  + ]:      39662 :     if (argc == 0) {
    4980         [ +  + ]:        219 :         if (len < 2)
    4981                 :            :             i = 0;
    4982                 :            :         else
    4983                 :        217 :             i = RAND_UPTO(len);
    4984                 :            : 
    4985                 :        211 :         return rb_ary_elt(ary, i);
    4986                 :            :     }
    4987                 :     276101 :     rb_scan_args(argc, argv, "1", &nv);
    4988                 :      78884 :     n = NUM2LONG(nv);
    4989         [ +  + ]:      39442 :     if (n < 0) rb_raise(rb_eArgError, "negative sample number");
    4990         [ +  + ]:      39440 :     if (n > len) n = len;
    4991         [ +  + ]:      39440 :     if (n <= numberof(idx)) {
    4992         [ +  + ]:     134258 :         for (i = 0; i < n; ++i) {
    4993                 :     107821 :             rnds[i] = RAND_UPTO(len - i);
    4994                 :            :         }
    4995                 :            :     }
    4996                 :      39440 :     k = len;
    4997                 :      78880 :     len = RARRAY_LEN(ary);
    4998         [ +  + ]:      39440 :     if (len < k && n <= numberof(idx)) {
    4999         [ +  - ]:          5 :         for (i = 0; i < n; ++i) {
    5000         [ +  - ]:         10 :             if (rnds[i] >= len) return rb_ary_new_capa(0);
    5001                 :            :         }
    5002                 :            :     }
    5003         [ -  + ]:      39435 :     if (n > len) n = len;
    5004   [ +  +  +  +  :      39435 :     switch (n) {
                      + ]
    5005                 :            :       case 0:
    5006                 :       1301 :         return rb_ary_new_capa(0);
    5007                 :            :       case 1:
    5008                 :       1306 :         i = rnds[0];
    5009                 :       1306 :         return rb_ary_new_from_values(1, &RARRAY_AREF(ary, i));
    5010                 :            :       case 2:
    5011                 :       1411 :         i = rnds[0];
    5012                 :       1411 :         j = rnds[1];
    5013         [ +  + ]:       1411 :         if (j >= i) j++;
    5014                 :       1411 :         return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j));
    5015                 :            :       case 3:
    5016                 :      13304 :         i = rnds[0];
    5017                 :      13304 :         j = rnds[1];
    5018                 :      13304 :         k = rnds[2];
    5019                 :            :         {
    5020                 :      13304 :             long l = j, g = i;
    5021         [ +  + ]:      13304 :             if (j >= i) l = i, g = ++j;
    5022 [ +  + ][ +  + ]:      13304 :             if (k >= l && (++k >= g)) ++k;
    5023                 :            :         }
    5024                 :      13304 :         return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k));
    5025                 :            :     }
    5026                 :      22113 :     memo_threshold =
    5027         [ +  + ]:      22113 :         len < 2560 ? len / 128 :
    5028         [ -  + ]:          4 :         len < 5120 ? len / 64 :
    5029         [ +  - ]:          4 :         len < 10240 ? len / 32 :
    5030                 :            :         len / 16;
    5031         [ +  + ]:      22113 :     if (n <= numberof(idx)) {
    5032                 :            :         long sorted[numberof(idx)];
    5033                 :       9110 :         sorted[0] = idx[0] = rnds[0];
    5034         [ +  + ]:      63761 :         for (i=1; i<n; i++) {
    5035                 :      54651 :             k = rnds[i];
    5036         [ +  + ]:     158844 :             for (j = 0; j < i; ++j) {
    5037         [ +  + ]:     144747 :                 if (k < sorted[j]) break;
    5038                 :     104193 :                 ++k;
    5039                 :            :             }
    5040                 :      54651 :             memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
    5041                 :      54651 :             sorted[j] = idx[i] = k;
    5042                 :            :         }
    5043                 :       9110 :         result = rb_ary_new_capa(n);
    5044         [ +  + ]:      72871 :         RARRAY_PTR_USE(result, ptr_result, {
    5045                 :            :             for (i=0; i<n; i++) {
    5046                 :            :                 ptr_result[i] = RARRAY_AREF(ary, idx[i]);
    5047                 :            :             }
    5048                 :            :         });
    5049                 :            :     }
    5050         [ +  + ]:      13003 :     else if (n <= memo_threshold / 2) {
    5051                 :          2 :         long max_idx = 0;
    5052                 :            : #undef RUBY_UNTYPED_DATA_WARNING
    5053                 :            : #define RUBY_UNTYPED_DATA_WARNING 0
    5054                 :          2 :         VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0);
    5055                 :          2 :         st_table *memo = st_init_numtable_with_size(n);
    5056                 :          2 :         DATA_PTR(vmemo) = memo;
    5057                 :          2 :         result = rb_ary_new_capa(n);
    5058 [ +  + ][ +  + ]:         39 :         RARRAY_PTR_USE(result, ptr_result, {
         [ +  + ][ -  + ]
         [ -  + ][ +  + ]
                 [ +  + ]
    5059                 :            :             for (i=0; i<n; i++) {
    5060                 :            :                 long r = RAND_UPTO(len-i) + i;
    5061                 :            :                 ptr_result[i] = r;
    5062                 :            :                 if (r > max_idx) max_idx = r;
    5063                 :            :             }
    5064                 :            :             len = RARRAY_LEN(ary);
    5065                 :            :             if (len <= max_idx) n = 0;
    5066                 :            :             else if (n > len) n = len;
    5067                 :            :             RARRAY_PTR_USE(ary, ptr_ary, {
    5068                 :            :                 for (i=0; i<n; i++) {
    5069                 :            :                     long j2 = j = ptr_result[i];
    5070                 :            :                     long i2 = i;
    5071                 :            :                     st_data_t value;
    5072                 :            :                     if (st_lookup(memo, (st_data_t)i, &value)) i2 = (long)value;
    5073                 :            :                     if (st_lookup(memo, (st_data_t)j, &value)) j2 = (long)value;
    5074                 :            :                     st_insert(memo, (st_data_t)j, (st_data_t)i2);
    5075                 :            :                     ptr_result[i] = ptr_ary[j2];
    5076                 :            :                 }
    5077                 :            :             });
    5078                 :            :         });
    5079                 :          2 :         DATA_PTR(vmemo) = 0;
    5080                 :          2 :         st_free_table(memo);
    5081                 :            :     }
    5082                 :            :     else {
    5083                 :      13001 :         result = rb_ary_dup(ary);
    5084                 :      13001 :         RBASIC_CLEAR_CLASS(result);
    5085                 :      13001 :         RB_GC_GUARD(ary);
    5086         [ +  + ]:     210612 :         RARRAY_PTR_USE(result, ptr_result, {
    5087                 :            :             for (i=0; i<n; i++) {
    5088                 :            :                 j = RAND_UPTO(len-i) + i;
    5089                 :            :                 nv = ptr_result[j];
    5090                 :            :                 ptr_result[j] = ptr_result[i];
    5091                 :            :                 ptr_result[i] = nv;
    5092                 :            :             }
    5093                 :            :         });
    5094                 :      13001 :         RBASIC_SET_CLASS_RAW(result, rb_cArray);
    5095                 :            :     }
    5096 [ +  - ][ +  - ]:      22113 :     ARY_SET_LEN(result, n);
         [ +  - ][ +  - ]
                 [ -  + ]
    5097                 :            : 
    5098                 :      22113 :     return result;
    5099                 :            : }
    5100                 :            : 
    5101                 :            : static VALUE
    5102                 :         13 : rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
    5103                 :            : {
    5104                 :            :     long mul;
    5105                 :         13 :     VALUE n = Qnil;
    5106 [ +  + ][ +  - ]:         22 :     if (args && (RARRAY_LEN(args) > 0)) {
    5107                 :          9 :         n = RARRAY_AREF(args, 0);
    5108                 :            :     }
    5109         [ +  + ]:         13 :     if (RARRAY_LEN(self) == 0) return INT2FIX(0);
    5110         [ +  + ]:         10 :     if (n == Qnil) return DBL2NUM(HUGE_VAL);
    5111                 :          7 :     mul = NUM2LONG(n);
    5112         [ +  + ]:          7 :     if (mul <= 0) return INT2FIX(0);
    5113                 :          4 :     n = LONG2FIX(mul);
    5114                 :          4 :     return rb_fix_mul_fix(rb_ary_length(self), n);
    5115                 :            : }
    5116                 :            : 
    5117                 :            : /*
    5118                 :            :  *  call-seq:
    5119                 :            :  *     ary.cycle(n=nil) {|obj| block}    -> nil
    5120                 :            :  *     ary.cycle(n=nil)                  -> Enumerator
    5121                 :            :  *
    5122                 :            :  *  Calls the given block for each element +n+ times or forever if +nil+ is
    5123                 :            :  *  given.
    5124                 :            :  *
    5125                 :            :  *  Does nothing if a non-positive number is given or the array is empty.
    5126                 :            :  *
    5127                 :            :  *  Returns +nil+ if the loop has finished without getting interrupted.
    5128                 :            :  *
    5129                 :            :  *  If no block is given, an Enumerator is returned instead.
    5130                 :            :  *
    5131                 :            :  *     a = ["a", "b", "c"]
    5132                 :            :  *     a.cycle {|x| puts x}       # print, a, b, c, a, b, c,.. forever.
    5133                 :            :  *     a.cycle(2) {|x| puts x}    # print, a, b, c, a, b, c.
    5134                 :            :  *
    5135                 :            :  */
    5136                 :            : 
    5137                 :            : static VALUE
    5138                 :         31 : rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
    5139                 :            : {
    5140                 :            :     long n, i;
    5141                 :         31 :     VALUE nv = Qnil;
    5142                 :            : 
    5143                 :        217 :     rb_scan_args(argc, argv, "01", &nv);
    5144                 :            : 
    5145         [ +  + ]:         31 :     RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
    5146         [ +  + ]:         18 :     if (NIL_P(nv)) {
    5147                 :            :         n = -1;
    5148                 :            :     }
    5149                 :            :     else {
    5150                 :         19 :         n = NUM2LONG(nv);
    5151         [ +  + ]:          7 :         if (n <= 0) return Qnil;
    5152                 :            :     }
    5153                 :            : 
    5154 [ +  + ][ +  + ]:         29 :     while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
                 [ +  + ]
    5155         [ +  + ]:        158 :         for (i=0; i<RARRAY_LEN(ary); i++) {
    5156                 :         56 :             rb_yield(RARRAY_AREF(ary, i));
    5157                 :            :         }
    5158                 :            :     }
    5159                 :            :     return Qnil;
    5160                 :            : }
    5161                 :            : 
    5162                 :            : #define tmpary(n) rb_ary_tmp_new(n)
    5163                 :            : #define tmpary_discard(a) (ary_discard(a), RBASIC_SET_CLASS_RAW(a, rb_cArray))
    5164                 :            : 
    5165                 :            : /*
    5166                 :            :  * Build a ruby array of the corresponding values and yield it to the
    5167                 :            :  * associated block.
    5168                 :            :  * Return the class of +values+ for reentry check.
    5169                 :            :  */
    5170                 :            : static int
    5171                 :     263907 : yield_indexed_values(const VALUE values, const long r, const long *const p)
    5172                 :            : {
    5173                 :     263907 :     const VALUE result = rb_ary_new2(r);
    5174                 :     791721 :     VALUE *const result_array = RARRAY_PTR(result);
    5175                 :     263907 :     const VALUE *const values_array = RARRAY_CONST_PTR(values);
    5176                 :            :     long i;
    5177                 :            : 
    5178         [ +  + ]:    2159271 :     for (i = 0; i < r; i++) result_array[i] = values_array[p[i]];
    5179 [ +  - ][ +  - ]:     263907 :     ARY_SET_LEN(result, r);
         [ +  - ][ +  + ]
                 [ +  + ]
    5180                 :     263907 :     rb_yield(result);
    5181                 :     267899 :     return !RBASIC(values)->klass;
    5182                 :            : }
    5183                 :            : 
    5184                 :            : /*
    5185                 :            :  * Compute permutations of +r+ elements of the set <code>[0..n-1]</code>.
    5186                 :            :  *
    5187                 :            :  * When we have a complete permutation of array indices, copy the values
    5188                 :            :  * at those indices into a new array and yield that array.
    5189                 :            :  *
    5190                 :            :  * n: the size of the set
    5191                 :            :  * r: the number of elements in each permutation
    5192                 :            :  * p: the array (of size r) that we're filling in
    5193                 :            :  * used: an array of booleans: whether a given index is already used
    5194                 :            :  * values: the Ruby array that holds the actual values to permute
    5195                 :            :  */
    5196                 :            : static void
    5197                 :         26 : permute0(const long n, const long r, long *const p, char *const used, const VALUE values)
    5198                 :            : {
    5199                 :     105135 :     long i = 0, index = 0;
    5200                 :            : 
    5201                 :            :     for (;;) {
    5202                 :     105135 :         const char *const unused = memchr(&used[i], 0, n-i);
    5203         [ +  + ]:     105135 :         if (!unused) {
    5204         [ +  + ]:       1384 :             if (!index) break;
    5205                 :       1359 :             i = p[--index];                /* pop index */
    5206                 :       1359 :             used[i++] = 0;                 /* index unused */
    5207                 :            :         }
    5208                 :            :         else {
    5209                 :     103751 :             i = unused - used;
    5210                 :     103751 :             p[index] = i;
    5211                 :     103751 :             used[i] = 1;                   /* mark index used */
    5212                 :     103751 :             ++index;
    5213         [ +  + ]:     103751 :             if (index < r-1) {             /* if not done yet */
    5214                 :     101357 :                 p[index] = i = 0;
    5215                 :     101357 :                 continue;
    5216                 :            :             }
    5217         [ +  + ]:     182608 :             for (i = 0; i < n; ++i) {
    5218         [ +  + ]:     180215 :                 if (used[i]) continue;
    5219                 :      70791 :                 p[index] = i;
    5220         [ +  + ]:      70791 :                 if (!yield_indexed_values(values, r, p)) {
    5221                 :        999 :                     rb_raise(rb_eRuntimeError, "permute reentered");
    5222                 :            :                 }
    5223                 :            :             }
    5224                 :       2393 :             i = p[--index];                /* pop index */
    5225                 :       2393 :             used[i] = 0;                   /* index unused */
    5226                 :       2393 :             p[index] = ++i;
    5227                 :            :         }
    5228                 :            :     }
    5229                 :         25 : }
    5230                 :            : 
    5231                 :            : /*
    5232                 :            :  * Returns the product of from, from-1, ..., from - how_many + 1.
    5233                 :            :  * http://en.wikipedia.org/wiki/Pochhammer_symbol
    5234                 :            :  */
    5235                 :            : static VALUE
    5236                 :         30 : descending_factorial(long from, long how_many)
    5237                 :            : {
    5238                 :            :     VALUE cnt;
    5239         [ +  + ]:         30 :     if (how_many > 0) {
    5240                 :         21 :         cnt = LONG2FIX(from);
    5241         [ +  + ]:         92 :         while (--how_many > 0) {
    5242                 :         71 :             long v = --from;
    5243                 :         71 :             cnt = rb_int_mul(cnt, LONG2FIX(v));
    5244                 :            :         }
    5245                 :            :     }
    5246                 :            :     else {
    5247         [ +  + ]:          9 :         cnt = LONG2FIX(how_many == 0);
    5248                 :            :     }
    5249                 :         30 :     return cnt;
    5250                 :            : }
    5251                 :            : 
    5252                 :            : static VALUE
    5253                 :         43 : binomial_coefficient(long comb, long size)
    5254                 :            : {
    5255                 :            :     VALUE r;
    5256                 :            :     long i;
    5257         [ +  + ]:         43 :     if (comb > size-comb) {
    5258                 :         21 :         comb = size-comb;
    5259                 :            :     }
    5260         [ +  + ]:         43 :     if (comb < 0) {
    5261                 :            :         return LONG2FIX(0);
    5262                 :            :     }
    5263         [ +  + ]:         25 :     else if (comb == 0) {
    5264                 :            :         return LONG2FIX(1);
    5265                 :            :     }
    5266                 :         16 :     r = LONG2FIX(size);
    5267         [ +  + ]:        111 :     for (i = 1; i < comb; ++i) {
    5268                 :         95 :         r = rb_int_mul(r, LONG2FIX(size - i));
    5269                 :         95 :         r = rb_int_idiv(r, LONG2FIX(i + 1));
    5270                 :            :     }
    5271                 :         16 :     return r;
    5272                 :            : }
    5273                 :            : 
    5274                 :            : static VALUE
    5275                 :         30 : rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
    5276                 :            : {
    5277                 :         30 :     long n = RARRAY_LEN(ary);
    5278 [ +  + ][ +  - ]:         78 :     long k = (args && (RARRAY_LEN(args) > 0)) ? NUM2LONG(RARRAY_AREF(args, 0)) : n;
    5279                 :            : 
    5280                 :         30 :     return descending_factorial(n, k);
    5281                 :            : }
    5282                 :            : 
    5283                 :            : /*
    5284                 :            :  *  call-seq:
    5285                 :            :  *     ary.permutation {|p| block}            -> ary
    5286                 :            :  *     ary.permutation                        -> Enumerator
    5287                 :            :  *     ary.permutation(n) {|p| block}         -> ary
    5288                 :            :  *     ary.permutation(n)                     -> Enumerator
    5289                 :            :  *
    5290                 :            :  * When invoked with a block, yield all permutations of length +n+ of the
    5291                 :            :  * elements of the array, then return the array itself.
    5292                 :            :  *
    5293                 :            :  * If +n+ is not specified, yield all permutations of all elements.
    5294                 :            :  *
    5295                 :            :  * The implementation makes no guarantees about the order in which the
    5296                 :            :  * permutations are yielded.
    5297                 :            :  *
    5298                 :            :  * If no block is given, an Enumerator is returned instead.
    5299                 :            :  *
    5300                 :            :  * Examples:
    5301                 :            :  *
    5302                 :            :  *   a = [1, 2, 3]
    5303                 :            :  *   a.permutation.to_a    #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
    5304                 :            :  *   a.permutation(1).to_a #=> [[1],[2],[3]]
    5305                 :            :  *   a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
    5306                 :            :  *   a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
    5307                 :            :  *   a.permutation(0).to_a #=> [[]] # one permutation of length 0
    5308                 :            :  *   a.permutation(4).to_a #=> []   # no permutations of length 4
    5309                 :            :  */
    5310                 :            : 
    5311                 :            : static VALUE
    5312                 :        111 : rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
    5313                 :            : {
    5314                 :            :     VALUE num;
    5315                 :            :     long r, n, i;
    5316                 :            : 
    5317                 :        111 :     n = RARRAY_LEN(ary);                  /* Array length */
    5318         [ +  + ]:        111 :     RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size);   /* Return enumerator if no block */
    5319                 :        322 :     rb_scan_args(argc, argv, "01", &num);
    5320         [ +  + ]:         46 :     r = NIL_P(num) ? n : NUM2LONG(num);   /* Permutation size from argument */
    5321                 :            : 
    5322         [ +  + ]:         46 :     if (r < 0 || n < r) {
    5323                 :            :         /* no permutations: yield nothing */
    5324                 :            :     }
    5325         [ +  + ]:         36 :     else if (r == 0) { /* exactly one permutation: the zero-length array */
    5326                 :          8 :         rb_yield(rb_ary_new2(0));
    5327                 :            :     }
    5328         [ +  + ]:         28 :     else if (r == 1) { /* this is a special, easy case */
    5329         [ +  + ]:         14 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    5330                 :          6 :             rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
    5331                 :            :         }
    5332                 :            :     }
    5333                 :            :     else {             /* this is the general case */
    5334                 :            :         volatile VALUE t0;
    5335         [ +  + ]:         26 :         long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
    5336                 :         26 :         char *used = (char*)(p + r);
    5337                 :         26 :         VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
    5338                 :         26 :         RBASIC_CLEAR_CLASS(ary0);
    5339                 :            : 
    5340                 :         26 :         MEMZERO(used, char, n); /* initialize array */
    5341                 :            : 
    5342                 :         26 :         permute0(n, r, p, used, ary0); /* compute and yield permutations */
    5343                 :         25 :         ALLOCV_END(t0);
    5344                 :         25 :         RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
    5345                 :            :     }
    5346                 :         45 :     return ary;
    5347                 :            : }
    5348                 :            : 
    5349                 :            : static void
    5350                 :         14 : combinate0(const long len, const long n, long *const stack, const VALUE values)
    5351                 :            : {
    5352                 :         14 :     long lev = 0;
    5353                 :            : 
    5354                 :         14 :     MEMZERO(stack+1, long, n);
    5355                 :         14 :     stack[0] = -1;
    5356                 :            :     for (;;) {
    5357         [ +  + ]:     171974 :         for (lev++; lev < n; lev++) {
    5358                 :       5154 :             stack[lev+1] = stack[lev]+1;
    5359                 :            :         }
    5360         [ +  + ]:     166820 :         if (!yield_indexed_values(values, n, stack+1)) {
    5361                 :     167818 :             rb_raise(rb_eRuntimeError, "combination reentered");
    5362                 :            :         }
    5363                 :            :         do {
    5364         [ +  + ]:     171937 :             if (lev == 0) return;
    5365                 :     171924 :             stack[lev--]++;
    5366         [ +  + ]:     171924 :         } while (stack[lev+1]+n == len+lev+1);
    5367                 :            :     }
    5368                 :            : }
    5369                 :            : 
    5370                 :            : static VALUE
    5371                 :         29 : rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
    5372                 :            : {
    5373                 :         29 :     long n = RARRAY_LEN(ary);
    5374                 :         58 :     long k = NUM2LONG(RARRAY_AREF(args, 0));
    5375                 :            : 
    5376                 :         29 :     return binomial_coefficient(k, n);
    5377                 :            : }
    5378                 :            : 
    5379                 :            : /*
    5380                 :            :  *  call-seq:
    5381                 :            :  *     ary.combination(n) {|c| block}      -> ary
    5382                 :            :  *     ary.combination(n)                  -> Enumerator
    5383                 :            :  *
    5384                 :            :  * When invoked with a block, yields all combinations of length +n+ of elements
    5385                 :            :  * from the array and then returns the array itself.
    5386                 :            :  *
    5387                 :            :  * The implementation makes no guarantees about the order in which the
    5388                 :            :  * combinations are yielded.
    5389                 :            :  *
    5390                 :            :  * If no block is given, an Enumerator is returned instead.
    5391                 :            :  *
    5392                 :            :  * Examples:
    5393                 :            :  *
    5394                 :            :  *     a = [1, 2, 3, 4]
    5395                 :            :  *     a.combination(1).to_a  #=> [[1],[2],[3],[4]]
    5396                 :            :  *     a.combination(2).to_a  #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
    5397                 :            :  *     a.combination(3).to_a  #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
    5398                 :            :  *     a.combination(4).to_a  #=> [[1,2,3,4]]
    5399                 :            :  *     a.combination(0).to_a  #=> [[]] # one combination of length 0
    5400                 :            :  *     a.combination(5).to_a  #=> []   # no combinations of length 5
    5401                 :            :  *
    5402                 :            :  */
    5403                 :            : 
    5404                 :            : static VALUE
    5405                 :         90 : rb_ary_combination(VALUE ary, VALUE num)
    5406                 :            : {
    5407                 :            :     long i, n, len;
    5408                 :            : 
    5409                 :        180 :     n = NUM2LONG(num);
    5410         [ +  + ]:         90 :     RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size);
    5411                 :         33 :     len = RARRAY_LEN(ary);
    5412         [ +  + ]:         33 :     if (n < 0 || len < n) {
    5413                 :            :         /* yield nothing */
    5414                 :            :     }
    5415         [ +  + ]:         22 :     else if (n == 0) {
    5416                 :          5 :         rb_yield(rb_ary_new2(0));
    5417                 :            :     }
    5418         [ +  + ]:         17 :     else if (n == 1) {
    5419         [ +  + ]:         21 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    5420                 :          9 :             rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
    5421                 :            :         }
    5422                 :            :     }
    5423                 :            :     else {
    5424                 :         14 :         VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
    5425                 :            :         volatile VALUE t0;
    5426         [ +  - ]:         14 :         long *stack = ALLOCV_N(long, t0, n+1);
    5427                 :            : 
    5428                 :         14 :         RBASIC_CLEAR_CLASS(ary0);
    5429                 :         14 :         combinate0(len, n, stack, ary0);
    5430                 :         13 :         ALLOCV_END(t0);
    5431                 :         13 :         RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
    5432                 :            :     }
    5433                 :         32 :     return ary;
    5434                 :            : }
    5435                 :            : 
    5436                 :            : /*
    5437                 :            :  * Compute repeated permutations of +r+ elements of the set
    5438                 :            :  * <code>[0..n-1]</code>.
    5439                 :            :  *
    5440                 :            :  * When we have a complete repeated permutation of array indices, copy the
    5441                 :            :  * values at those indices into a new array and yield that array.
    5442                 :            :  *
    5443                 :            :  * n: the size of the set
    5444                 :            :  * r: the number of elements in each permutation
    5445                 :            :  * p: the array (of size r) that we're filling in
    5446                 :            :  * values: the Ruby array that holds the actual values to permute
    5447                 :            :  */
    5448                 :            : static void
    5449                 :         15 : rpermute0(const long n, const long r, long *const p, const VALUE values)
    5450                 :            : {
    5451                 :         15 :     long i = 0, index = 0;
    5452                 :            : 
    5453                 :     506442 :     p[index] = i;
    5454                 :            :     for (;;) {
    5455         [ +  + ]:     506442 :         if (++index < r-1) {
    5456                 :     501292 :             p[index] = i = 0;
    5457                 :     501292 :             continue;
    5458                 :            :         }
    5459         [ +  + ]:      30724 :         for (i = 0; i < n; ++i) {
    5460                 :      25575 :             p[index] = i;
    5461         [ +  + ]:      25575 :             if (!yield_indexed_values(values, r, p)) {
    5462                 :        999 :                 rb_raise(rb_eRuntimeError, "repeated permute reentered");
    5463                 :            :             }
    5464                 :            :         }
    5465                 :            :         do {
    5466         [ +  + ]:       6457 :             if (index <= 0) return;
    5467         [ +  + ]:       6443 :         } while ((i = ++p[--index]) >= n);
    5468                 :            :     }
    5469                 :            : }
    5470                 :            : 
    5471                 :            : static VALUE
    5472                 :         17 : rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
    5473                 :            : {
    5474                 :         17 :     long n = RARRAY_LEN(ary);
    5475                 :         34 :     long k = NUM2LONG(RARRAY_AREF(args, 0));
    5476                 :            : 
    5477         [ +  + ]:         17 :     if (k < 0) {
    5478                 :            :         return LONG2FIX(0);
    5479                 :            :     }
    5480         [ +  + ]:         15 :     if (n <= 0) {
    5481         [ +  + ]:          6 :         return LONG2FIX(!k);
    5482                 :            :     }
    5483                 :          9 :     return rb_int_positive_pow(n, (unsigned long)k);
    5484                 :            : }
    5485                 :            : 
    5486                 :            : /*
    5487                 :            :  *  call-seq:
    5488                 :            :  *     ary.repeated_permutation(n) {|p| block}   -> ary
    5489                 :            :  *     ary.repeated_permutation(n)               -> Enumerator
    5490                 :            :  *
    5491                 :            :  * When invoked with a block, yield all repeated permutations of length +n+ of
    5492                 :            :  * the elements of the array, then return the array itself.
    5493                 :            :  *
    5494                 :            :  * The implementation makes no guarantees about the order in which the repeated
    5495                 :            :  * permutations are yielded.
    5496                 :            :  *
    5497                 :            :  * If no block is given, an Enumerator is returned instead.
    5498                 :            :  *
    5499                 :            :  * Examples:
    5500                 :            :  *
    5501                 :            :  *     a = [1, 2]
    5502                 :            :  *     a.repeated_permutation(1).to_a  #=> [[1], [2]]
    5503                 :            :  *     a.repeated_permutation(2).to_a  #=> [[1,1],[1,2],[2,1],[2,2]]
    5504                 :            :  *     a.repeated_permutation(3).to_a  #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2],
    5505                 :            :  *                                     #    [2,1,1],[2,1,2],[2,2,1],[2,2,2]]
    5506                 :            :  *     a.repeated_permutation(0).to_a  #=> [[]] # one permutation of length 0
    5507                 :            :  */
    5508                 :            : 
    5509                 :            : static VALUE
    5510                 :         62 : rb_ary_repeated_permutation(VALUE ary, VALUE num)
    5511                 :            : {
    5512                 :            :     long r, n, i;
    5513                 :            : 
    5514                 :         62 :     n = RARRAY_LEN(ary);                  /* Array length */
    5515         [ +  + ]:         62 :     RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size);      /* Return Enumerator if no block */
    5516                 :         48 :     r = NUM2LONG(num);                    /* Permutation size from argument */
    5517                 :            : 
    5518         [ +  + ]:         24 :     if (r < 0) {
    5519                 :            :         /* no permutations: yield nothing */
    5520                 :            :     }
    5521         [ +  + ]:         21 :     else if (r == 0) { /* exactly one permutation: the zero-length array */
    5522                 :          4 :         rb_yield(rb_ary_new2(0));
    5523                 :            :     }
    5524         [ +  + ]:         17 :     else if (r == 1) { /* this is a special, easy case */
    5525         [ +  + ]:          6 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    5526                 :          2 :             rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
    5527                 :            :         }
    5528                 :            :     }
    5529                 :            :     else {             /* this is the general case */
    5530                 :            :         volatile VALUE t0;
    5531         [ +  + ]:         15 :         long *p = ALLOCV_N(long, t0, r);
    5532                 :         15 :         VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
    5533                 :         15 :         RBASIC_CLEAR_CLASS(ary0);
    5534                 :            : 
    5535                 :         15 :         rpermute0(n, r, p, ary0); /* compute and yield repeated permutations */
    5536                 :         14 :         ALLOCV_END(t0);
    5537                 :         14 :         RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
    5538                 :            :     }
    5539                 :         23 :     return ary;
    5540                 :            : }
    5541                 :            : 
    5542                 :            : static void
    5543                 :         26 : rcombinate0(const long n, const long r, long *const p, const long rest, const VALUE values)
    5544                 :            : {
    5545                 :         13 :     long i = 0, index = 0;
    5546                 :            : 
    5547                 :     500736 :     p[index] = i;
    5548                 :            :     for (;;) {
    5549         [ +  + ]:     500736 :         if (++index < r-1) {
    5550                 :     500328 :             p[index] = i;
    5551                 :     500328 :             continue;
    5552                 :            :         }
    5553         [ +  + ]:       1128 :         for (; i < n; ++i) {
    5554                 :        721 :             p[index] = i;
    5555         [ +  + ]:        721 :             if (!yield_indexed_values(values, r, p)) {
    5556                 :        999 :                 rb_raise(rb_eRuntimeError, "repeated combination reentered");
    5557                 :            :             }
    5558                 :            :         }
    5559                 :            :         do {
    5560         [ +  + ]:        749 :             if (index <= 0) return;
    5561         [ +  + ]:        737 :         } while ((i = ++p[--index]) >= n);
    5562                 :            :     }
    5563                 :            : }
    5564                 :            : 
    5565                 :            : static VALUE
    5566                 :         18 : rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
    5567                 :            : {
    5568                 :         18 :     long n = RARRAY_LEN(ary);
    5569                 :         36 :     long k = NUM2LONG(RARRAY_AREF(args, 0));
    5570         [ +  + ]:         18 :     if (k == 0) {
    5571                 :            :         return LONG2FIX(1);
    5572                 :            :     }
    5573                 :         14 :     return binomial_coefficient(k, n + k - 1);
    5574                 :            : }
    5575                 :            : 
    5576                 :            : /*
    5577                 :            :  *  call-seq:
    5578                 :            :  *     ary.repeated_combination(n) {|c| block}   -> ary
    5579                 :            :  *     ary.repeated_combination(n)               -> Enumerator
    5580                 :            :  *
    5581                 :            :  * When invoked with a block, yields all repeated combinations of length +n+ of
    5582                 :            :  * elements from the array and then returns the array itself.
    5583                 :            :  *
    5584                 :            :  * The implementation makes no guarantees about the order in which the repeated
    5585                 :            :  * combinations are yielded.
    5586                 :            :  *
    5587                 :            :  * If no block is given, an Enumerator is returned instead.
    5588                 :            :  *
    5589                 :            :  * Examples:
    5590                 :            :  *
    5591                 :            :  *   a = [1, 2, 3]
    5592                 :            :  *   a.repeated_combination(1).to_a  #=> [[1], [2], [3]]
    5593                 :            :  *   a.repeated_combination(2).to_a  #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
    5594                 :            :  *   a.repeated_combination(3).to_a  #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],
    5595                 :            :  *                                   #    [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]
    5596                 :            :  *   a.repeated_combination(4).to_a  #=> [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3],
    5597                 :            :  *                                   #    [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3],
    5598                 :            :  *                                   #    [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]]
    5599                 :            :  *   a.repeated_combination(0).to_a  #=> [[]] # one combination of length 0
    5600                 :            :  *
    5601                 :            :  */
    5602                 :            : 
    5603                 :            : static VALUE
    5604                 :         66 : rb_ary_repeated_combination(VALUE ary, VALUE num)
    5605                 :            : {
    5606                 :            :     long n, i, len;
    5607                 :            : 
    5608                 :        132 :     n = NUM2LONG(num);                 /* Combination size from argument */
    5609         [ +  + ]:         66 :     RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size);   /* Return enumerator if no block */
    5610                 :         26 :     len = RARRAY_LEN(ary);
    5611         [ +  + ]:         26 :     if (n < 0) {
    5612                 :            :         /* yield nothing */
    5613                 :            :     }
    5614         [ +  + ]:         23 :     else if (n == 0) {
    5615                 :          4 :         rb_yield(rb_ary_new2(0));
    5616                 :            :     }
    5617         [ +  + ]:         19 :     else if (n == 1) {
    5618         [ +  + ]:         11 :         for (i = 0; i < RARRAY_LEN(ary); i++) {
    5619                 :          4 :             rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
    5620                 :            :         }
    5621                 :            :     }
    5622         [ +  + ]:         16 :     else if (len == 0) {
    5623                 :            :         /* yield nothing */
    5624                 :            :     }
    5625                 :            :     else {
    5626                 :            :         volatile VALUE t0;
    5627         [ +  + ]:         13 :         long *p = ALLOCV_N(long, t0, n);
    5628                 :         13 :         VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
    5629                 :         13 :         RBASIC_CLEAR_CLASS(ary0);
    5630                 :            : 
    5631                 :         13 :         rcombinate0(len, n, p, n, ary0); /* compute and yield repeated combinations */
    5632                 :         12 :         ALLOCV_END(t0);
    5633                 :         12 :         RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
    5634                 :            :     }
    5635                 :         25 :     return ary;
    5636                 :            : }
    5637                 :            : 
    5638                 :            : /*
    5639                 :            :  *  call-seq:
    5640                 :            :  *     ary.product(other_ary, ...)                -> new_ary
    5641                 :            :  *     ary.product(other_ary, ...) {|p| block}    -> ary
    5642                 :            :  *
    5643                 :            :  *  Returns an array of all combinations of elements from all arrays.
    5644                 :            :  *
    5645                 :            :  *  The length of the returned array is the product of the length of +self+ and
    5646                 :            :  *  the argument arrays.
    5647                 :            :  *
    5648                 :            :  *  If given a block, #product will yield all combinations and return +self+
    5649                 :            :  *  instead.
    5650                 :            :  *
    5651                 :            :  *     [1,2,3].product([4,5])     #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
    5652                 :            :  *     [1,2].product([1,2])       #=> [[1,1],[1,2],[2,1],[2,2]]
    5653                 :            :  *     [1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
    5654                 :            :  *                                #     [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
    5655                 :            :  *     [1,2].product()            #=> [[1],[2]]
    5656                 :            :  *     [1,2].product([])          #=> []
    5657                 :            :  */
    5658                 :            : 
    5659                 :            : static VALUE
    5660                 :       1246 : rb_ary_product(int argc, VALUE *argv, VALUE ary)
    5661                 :            : {
    5662                 :       1246 :     int n = argc+1;    /* How many arrays we're operating on */
    5663                 :       2492 :     volatile VALUE t0 = tmpary(n);
    5664                 :       1246 :     volatile VALUE t1 = Qundef;
    5665                 :       3738 :     VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
    5666         [ +  - ]:       1246 :     int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
    5667                 :       1246 :     VALUE result = Qnil;      /* The array we'll be returning, when no block given */
    5668                 :            :     long i,j;
    5669                 :       1246 :     long resultlen = 1;
    5670                 :            : 
    5671                 :       1246 :     RBASIC_CLEAR_CLASS(t0);
    5672                 :            : 
    5673                 :            :     /* initialize the arrays of arrays */
    5674 [ +  - ][ +  - ]:       1246 :     ARY_SET_LEN(t0, n);
         [ +  - ][ +  + ]
                 [ +  + ]
    5675                 :       1246 :     arrays[0] = ary;
    5676         [ +  + ]:       3155 :     for (i = 1; i < n; i++) arrays[i] = Qnil;
    5677         [ +  + ]:       3154 :     for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);
    5678                 :            : 
    5679                 :            :     /* initialize the counters for the arrays */
    5680         [ +  + ]:       4398 :     for (i = 0; i < n; i++) counters[i] = 0;
    5681                 :            : 
    5682                 :            :     /* Otherwise, allocate and fill in an array of results */
    5683         [ +  + ]:       1245 :     if (rb_block_given_p()) {
    5684                 :            :         /* Make defensive copies of arrays; exit if any is empty */
    5685         [ +  + ]:         78 :         for (i = 0; i < n; i++) {
    5686         [ +  + ]:         58 :             if (RARRAY_LEN(arrays[i]) == 0) goto done;
    5687                 :         55 :             arrays[i] = ary_make_shared_copy(arrays[i]);
    5688                 :            :         }
    5689                 :            :     }
    5690                 :            :     else {
    5691                 :            :         /* Compute the length of the result array; return [] if any is empty */
    5692         [ +  + ]:       4306 :         for (i = 0; i < n; i++) {
    5693                 :       6178 :             long k = RARRAY_LEN(arrays[i]);
    5694         [ +  + ]:       3089 :             if (k == 0) {
    5695                 :          2 :                 result = rb_ary_new2(0);
    5696                 :          2 :                 goto done;
    5697                 :            :             }
    5698 [ +  - ][ -  + ]:       3087 :             if (MUL_OVERFLOW_LONG_P(resultlen, k))
         [ +  - ][ +  - ]
         [ #  # ][ +  + ]
    5699                 :          3 :                 rb_raise(rb_eRangeError, "too big to product");
    5700                 :       3084 :             resultlen *= k;
    5701                 :            :         }
    5702                 :       1237 :         result = rb_ary_new2(resultlen);
    5703                 :            :     }
    5704                 :            :     for (;;) {
    5705                 :            :         int m;
    5706                 :            :         /* fill in one subarray */
    5707                 :      85468 :         VALUE subarray = rb_ary_new2(n);
    5708         [ +  + ]:     165767 :         for (j = 0; j < n; j++) {
    5709                 :     123033 :             rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
    5710                 :            :         }
    5711                 :            : 
    5712                 :            :         /* put it on the result array */
    5713         [ +  + ]:      42734 :         if (NIL_P(result)) {
    5714 [ +  - ][ +  - ]:        871 :             FL_SET(t0, FL_USER5);
                 [ +  - ]
    5715                 :        871 :             rb_yield(subarray);
    5716 [ +  - ][ +  - ]:       1869 :             if (! FL_TEST(t0, FL_USER5)) {
         [ +  - ][ +  + ]
    5717                 :        999 :                 rb_raise(rb_eRuntimeError, "product reentered");
    5718                 :            :             }
    5719                 :            :             else {
    5720 [ +  - ][ +  - ]:        870 :                 FL_UNSET(t0, FL_USER5);
                 [ +  - ]
    5721                 :            :             }
    5722                 :            :         }
    5723                 :            :         else {
    5724                 :      41863 :             rb_ary_push(result, subarray);
    5725                 :            :         }
    5726                 :            : 
    5727                 :            :         /*
    5728                 :            :          * Increment the last counter.  If it overflows, reset to 0
    5729                 :            :          * and increment the one before it.
    5730                 :            :          */
    5731                 :      42733 :         m = n-1;
    5732                 :      42733 :         counters[m]++;
    5733         [ +  + ]:      97373 :         while (counters[m] == RARRAY_LEN(arrays[m])) {
    5734                 :      13143 :             counters[m] = 0;
    5735                 :            :             /* If the first counter overflows, we are done */
    5736         [ +  + ]:      13143 :             if (--m < 0) goto done;
    5737                 :      11907 :             counters[m]++;
    5738                 :            :         }
    5739                 :            :     }
    5740                 :            : done:
    5741                 :       2482 :     tmpary_discard(t0);
    5742                 :       1241 :     ALLOCV_END(t1);
    5743                 :            : 
    5744         [ +  + ]:       1241 :     return NIL_P(result) ? ary : result;
    5745                 :            : }
    5746                 :            : 
    5747                 :            : /*
    5748                 :            :  *  call-seq:
    5749                 :            :  *     ary.take(n)               -> new_ary
    5750                 :            :  *
    5751                 :            :  *  Returns first +n+ elements from the array.
    5752                 :            :  *
    5753                 :            :  *  If a negative number is given, raises an ArgumentError.
    5754                 :            :  *
    5755                 :            :  *  See also Array#drop
    5756                 :            :  *
    5757                 :            :  *     a = [1, 2, 3, 4, 5, 0]
    5758                 :            :  *     a.take(3)             #=> [1, 2, 3]
    5759                 :            :  *
    5760                 :            :  */
    5761                 :            : 
    5762                 :            : static VALUE
    5763                 :       1251 : rb_ary_take(VALUE obj, VALUE n)
    5764                 :            : {
    5765                 :       1251 :     long len = NUM2LONG(n);
    5766         [ +  + ]:       1251 :     if (len < 0) {
    5767                 :          2 :         rb_raise(rb_eArgError, "attempt to take negative size");
    5768                 :            :     }
    5769                 :       1249 :     return rb_ary_subseq(obj, 0, len);
    5770                 :            : }
    5771                 :            : 
    5772                 :            : /*
    5773                 :            :  *  call-seq:
    5774                 :            :  *     ary.take_while {|obj| block}    -> new_ary
    5775                 :            :  *     ary.take_while                  -> Enumerator
    5776                 :            :  *
    5777                 :            :  *  Passes elements to the block until the block returns +nil+ or +false+, then
    5778                 :            :  *  stops iterating and returns an array of all prior elements.
    5779                 :            :  *
    5780                 :            :  *  If no block is given, an Enumerator is returned instead.
    5781                 :            :  *
    5782                 :            :  *  See also Array#drop_while
    5783                 :            :  *
    5784                 :            :  *     a = [1, 2, 3, 4, 5, 0]
    5785                 :            :  *     a.take_while {|i| i < 3}    #=> [1, 2]
    5786                 :            :  *
    5787                 :            :  */
    5788                 :            : 
    5789                 :            : static VALUE
    5790                 :       1196 : rb_ary_take_while(VALUE ary)
    5791                 :            : {
    5792                 :            :     long i;
    5793                 :            : 
    5794         [ +  - ]:       1196 :     RETURN_ENUMERATOR(ary, 0, 0);
    5795         [ +  + ]:       3484 :     for (i = 0; i < RARRAY_LEN(ary); i++) {
    5796         [ +  + ]:       2316 :         if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
    5797                 :            :     }
    5798                 :       1196 :     return rb_ary_take(ary, LONG2FIX(i));
    5799                 :            : }
    5800                 :            : 
    5801                 :            : /*
    5802                 :            :  *  call-seq:
    5803                 :            :  *     ary.drop(n)               -> new_ary
    5804                 :            :  *
    5805                 :            :  *  Drops first +n+ elements from +ary+ and returns the rest of the elements in
    5806                 :            :  *  an array.
    5807                 :            :  *
    5808                 :            :  *  If a negative number is given, raises an ArgumentError.
    5809                 :            :  *
    5810                 :            :  *  See also Array#take
    5811                 :            :  *
    5812                 :            :  *     a = [1, 2, 3, 4, 5, 0]
    5813                 :            :  *     a.drop(3)             #=> [4, 5, 0]
    5814                 :            :  *
    5815                 :            :  */
    5816                 :            : 
    5817                 :            : static VALUE
    5818                 :         36 : rb_ary_drop(VALUE ary, VALUE n)
    5819                 :            : {
    5820                 :            :     VALUE result;
    5821                 :         36 :     long pos = NUM2LONG(n);
    5822         [ +  + ]:         36 :     if (pos < 0) {
    5823                 :          2 :         rb_raise(rb_eArgError, "attempt to drop negative size");
    5824                 :            :     }
    5825                 :            : 
    5826                 :         34 :     result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
    5827         [ +  + ]:         34 :     if (result == Qnil) result = rb_ary_new();
    5828                 :         34 :     return result;
    5829                 :            : }
    5830                 :            : 
    5831                 :            : /*
    5832                 :            :  *  call-seq:
    5833                 :            :  *     ary.drop_while {|obj| block}     -> new_ary
    5834                 :            :  *     ary.drop_while                  -> Enumerator
    5835                 :            :  *
    5836                 :            :  *  Drops elements up to, but not including, the first element for which the
    5837                 :            :  *  block returns +nil+ or +false+ and returns an array containing the
    5838                 :            :  *  remaining elements.
    5839                 :            :  *
    5840                 :            :  *  If no block is given, an Enumerator is returned instead.
    5841                 :            :  *
    5842                 :            :  *  See also Array#take_while
    5843                 :            :  *
    5844                 :            :  *     a = [1, 2, 3, 4, 5, 0]
    5845                 :            :  *     a.drop_while {|i| i < 3 }   #=> [3, 4, 5, 0]
    5846                 :            :  *
    5847                 :            :  */
    5848                 :            : 
    5849                 :            : static VALUE
    5850                 :          5 : rb_ary_drop_while(VALUE ary)
    5851                 :            : {
    5852                 :            :     long i;
    5853                 :            : 
    5854         [ +  - ]:          5 :     RETURN_ENUMERATOR(ary, 0, 0);
    5855         [ +  - ]:         27 :     for (i = 0; i < RARRAY_LEN(ary); i++) {
    5856         [ +  + ]:         16 :         if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break;
    5857                 :            :     }
    5858                 :          5 :     return rb_ary_drop(ary, LONG2FIX(i));
    5859                 :            : }
    5860                 :            : 
    5861                 :            : /*
    5862                 :            :  *  call-seq:
    5863                 :            :  *     ary.any? [{|obj| block}  ]   -> true or false
    5864                 :            :  *     ary.any?(pattern)            -> true or false
    5865                 :            :  *
    5866                 :            :  *  See also Enumerable#any?
    5867                 :            :  */
    5868                 :            : 
    5869                 :            : static VALUE
    5870                 :     237847 : rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
    5871                 :            : {
    5872                 :     237847 :     long i, len = RARRAY_LEN(ary);
    5873                 :     237847 :     const VALUE *ptr = RARRAY_CONST_PTR(ary);
    5874                 :            : 
    5875                 :     237847 :     rb_check_arity(argc, 0, 1);
    5876         [ +  + ]:     237846 :     if (!len) return Qfalse;
    5877         [ +  + ]:     230167 :     if (argc) {
    5878         [ +  + ]:          5 :         if (rb_block_given_p()) {
    5879                 :          5 :             rb_warn("given block not used");
    5880                 :            :         }
    5881         [ +  + ]:         17 :         for (i = 0; i < RARRAY_LEN(ary); ++i) {
    5882         [ +  + ]:          9 :             if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
    5883                 :            :         }
    5884                 :            :     }
    5885         [ +  + ]:     230162 :     else if (!rb_block_given_p()) {
    5886 [ +  + ][ +  + ]:     221341 :         for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue;
    5887                 :            :     }
    5888                 :            :     else {
    5889         [ +  + ]:    2163118 :         for (i = 0; i < RARRAY_LEN(ary); ++i) {
    5890         [ +  + ]:    1108152 :             if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
    5891                 :            :         }
    5892                 :            :     }
    5893                 :            :     return Qfalse;
    5894                 :            : }
    5895                 :            : 
    5896                 :            : /*
    5897                 :            :  * call-seq:
    5898                 :            :  *   ary.dig(idx, ...)                 -> object
    5899                 :            :  *
    5900                 :            :  * Extracts the nested value specified by the sequence of <i>idx</i>
    5901                 :            :  * objects by calling +dig+ at each step, returning +nil+ if any
    5902                 :            :  * intermediate step is +nil+.
    5903                 :            :  *
    5904                 :            :  *   a = [[1, [2, 3]]]
    5905                 :            :  *
    5906                 :            :  *   a.dig(0, 1, 1)                    #=> 3
    5907                 :            :  *   a.dig(1, 2, 3)                    #=> nil
    5908                 :            :  *   a.dig(0, 0, 0)                    #=> TypeError: Integer does not have #dig method
    5909                 :            :  *   [42, {foo: :bar}].dig(1, :foo)    #=> :bar
    5910                 :            :  */
    5911                 :            : 
    5912                 :            : static VALUE
    5913                 :        588 : rb_ary_dig(int argc, VALUE *argv, VALUE self)
    5914                 :            : {
    5915                 :        588 :     rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    5916                 :        587 :     self = rb_ary_at(self, *argv);
    5917         [ +  + ]:        586 :     if (!--argc) return self;
    5918                 :        570 :     ++argv;
    5919                 :        570 :     return rb_obj_dig(argc, argv, self, Qnil);
    5920                 :            : }
    5921                 :            : 
    5922                 :            : static inline VALUE
    5923                 :         51 : finish_exact_sum(long n, VALUE r, VALUE v, int z)
    5924                 :            : {
    5925         [ +  + ]:         51 :     if (n != 0)
    5926                 :         26 :         v = rb_fix_plus(LONG2FIX(n), v);
    5927         [ +  + ]:         49 :     if (r != Qundef) {
    5928                 :            :         /* r can be an Integer when mathn is loaded */
    5929         [ -  + ]:          7 :         if (FIXNUM_P(r))
    5930                 :          0 :             v = rb_fix_plus(r, v);
    5931 [ +  - ][ +  - ]:          7 :         else if (RB_TYPE_P(r, T_BIGNUM))
                 [ -  + ]
    5932                 :          0 :             v = rb_big_plus(r, v);
    5933                 :            :         else
    5934                 :          7 :             v = rb_rational_plus(r, v);
    5935                 :            :     }
    5936         [ +  + ]:         42 :     else if (!n && z) {
    5937                 :          2 :         v = rb_fix_plus(LONG2FIX(0), v);
    5938                 :            :     }
    5939                 :         48 :     return v;
    5940                 :            : }
    5941                 :            : 
    5942                 :            : /*
    5943                 :            :  * call-seq:
    5944                 :            :  *   ary.sum(init=0)                    -> number
    5945                 :            :  *   ary.sum(init=0) {|e| expr }        -> number
    5946                 :            :  *
    5947                 :            :  * Returns the sum of elements.
    5948                 :            :  * For example, [e1, e2, e3].sum returns init + e1 + e2 + e3.
    5949                 :            :  *
    5950                 :            :  * If a block is given, the block is applied to each element
    5951                 :            :  * before addition.
    5952                 :            :  *
    5953                 :            :  * If <i>ary</i> is empty, it returns <i>init</i>.
    5954                 :            :  *
    5955                 :            :  *   [].sum                             #=> 0
    5956                 :            :  *   [].sum(0.0)                        #=> 0.0
    5957                 :            :  *   [1, 2, 3].sum                      #=> 6
    5958                 :            :  *   [3, 5.5].sum                       #=> 8.5
    5959                 :            :  *   [2.5, 3.0].sum(0.0) {|e| e * e }   #=> 15.25
    5960                 :            :  *   [Object.new].sum                   #=> TypeError
    5961                 :            :  *
    5962                 :            :  * The (arithmetic) mean value of an array can be obtained as follows.
    5963                 :            :  *
    5964                 :            :  *   mean = ary.sum(0.0) / ary.length
    5965                 :            :  *
    5966                 :            :  * This method can be used for non-numeric objects by
    5967                 :            :  * explicit <i>init</i> argument.
    5968                 :            :  *
    5969                 :            :  *   ["a", "b", "c"].sum("")            #=> "abc"
    5970                 :            :  *   [[1], [[2]], [3]].sum([])          #=> [1, [2], 3]
    5971                 :            :  *
    5972                 :            :  * However, Array#join and Array#flatten is faster than Array#sum for
    5973                 :            :  * array of strings and array of arrays.
    5974                 :            :  *
    5975                 :            :  *   ["a", "b", "c"].join               #=> "abc"
    5976                 :            :  *   [[1], [[2]], [3]].flatten(1)       #=> [1, [2], 3]
    5977                 :            :  *
    5978                 :            :  *
    5979                 :            :  * Array#sum method may not respect method redefinition of "+" methods
    5980                 :            :  * such as Integer#+.
    5981                 :            :  *
    5982                 :            :  */
    5983                 :            : 
    5984                 :            : static VALUE
    5985                 :         55 : rb_ary_sum(int argc, VALUE *argv, VALUE ary)
    5986                 :            : {
    5987                 :            :     VALUE e, v, r;
    5988                 :            :     long i, n;
    5989                 :            :     int block_given;
    5990                 :            : 
    5991         [ +  + ]:         55 :     if (rb_scan_args(argc, argv, "01", &v) == 0)
    5992                 :         41 :         v = LONG2FIX(0);
    5993                 :            : 
    5994                 :         55 :     block_given = rb_block_given_p();
    5995                 :            : 
    5996         [ +  + ]:         55 :     if (RARRAY_LEN(ary) == 0)
    5997                 :          4 :         return v;
    5998                 :            : 
    5999                 :            :     n = 0;
    6000                 :            :     r = Qundef;
    6001         [ +  + ]:        305 :     for (i = 0; i < RARRAY_LEN(ary); i++) {
    6002                 :        154 :         e = RARRAY_AREF(ary, i);
    6003         [ +  + ]:        154 :         if (block_given)
    6004                 :          7 :             e = rb_yield(e);
    6005         [ +  + ]:        154 :         if (FIXNUM_P(e)) {
    6006                 :        107 :             n += FIX2LONG(e); /* should not overflow long type */
    6007         [ +  + ]:        107 :             if (!FIXABLE(n)) {
    6008                 :          9 :                 v = rb_big_plus(LONG2NUM(n), v);
    6009                 :          9 :                 n = 0;
    6010                 :            :             }
    6011                 :            :         }
    6012 [ +  + ][ +  - ]:         47 :         else if (RB_TYPE_P(e, T_BIGNUM))
                 [ +  + ]
    6013                 :         12 :             v = rb_big_plus(e, v);
    6014 [ +  + ][ +  - ]:         35 :         else if (RB_TYPE_P(e, T_RATIONAL)) {
                 [ +  + ]
    6015         [ +  + ]:          8 :             if (r == Qundef)
    6016                 :            :                 r = e;
    6017                 :            :             else
    6018                 :          1 :                 r = rb_rational_plus(r, e);
    6019                 :            :         }
    6020                 :            :         else
    6021                 :            :             goto not_exact;
    6022                 :            :     }
    6023                 :         24 :     v = finish_exact_sum(n, r, v, argc!=0);
    6024                 :         21 :     return v;
    6025                 :            : 
    6026                 :            :   not_exact:
    6027                 :         27 :     v = finish_exact_sum(n, r, v, i!=0);
    6028                 :            : 
    6029 [ +  + ][ +  - ]:         27 :     if (RB_FLOAT_TYPE_P(e)) {
         [ +  - ][ +  + ]
    6030                 :            :         /*
    6031                 :            :          * Kahan-Babuska balancing compensated summation algorithm
    6032                 :            :          * See http://link.springer.com/article/10.1007/s00607-005-0139-x
    6033                 :            :          */
    6034                 :            :         double f, c;
    6035                 :            : 
    6036                 :         20 :         f = NUM2DBL(v);
    6037                 :         20 :         c = 0.0;
    6038                 :         20 :         goto has_float_value;
    6039         [ +  + ]:         58 :         for (; i < RARRAY_LEN(ary); i++) {
    6040                 :            :             double x, t;
    6041                 :         40 :             e = RARRAY_AREF(ary, i);
    6042         [ +  + ]:         40 :             if (block_given)
    6043                 :          1 :                 e = rb_yield(e);
    6044 [ +  + ][ +  + ]:         40 :             if (RB_FLOAT_TYPE_P(e))
         [ +  - ][ +  + ]
    6045                 :            :               has_float_value:
    6046                 :         53 :                 x = RFLOAT_VALUE(e);
    6047         [ +  + ]:          7 :             else if (FIXNUM_P(e))
    6048                 :          3 :                 x = FIX2LONG(e);
    6049 [ +  - ][ +  - ]:          4 :             else if (RB_TYPE_P(e, T_BIGNUM))
                 [ +  + ]
    6050                 :          1 :                 x = rb_big2dbl(e);
    6051 [ +  - ][ +  - ]:          3 :             else if (RB_TYPE_P(e, T_RATIONAL))
                 [ +  + ]
    6052                 :          5 :                 x = rb_num2dbl(e);
    6053                 :            :             else
    6054                 :            :                 goto not_float;
    6055                 :            : 
    6056         [ -  + ]:         58 :             if (isnan(f)) continue;
    6057         [ -  + ]:         58 :             if (isnan(x)) {
    6058                 :          0 :                 f = x;
    6059                 :          0 :                 continue;
    6060                 :            :             }
    6061         [ +  + ]:         58 :             if (isinf(x)) {
    6062 [ +  + ][ -  + ]:          8 :                 if (isinf(f) && signbit(x) != signbit(f))
    6063                 :            :                     f = NAN;
    6064                 :            :                 else
    6065                 :          7 :                     f = x;
    6066                 :          8 :                 continue;
    6067                 :            :             }
    6068         [ +  + ]:         50 :             if (isinf(f)) continue;
    6069                 :            : 
    6070                 :         48 :             t = f + x;
    6071         [ +  + ]:         48 :             if (fabs(f) >= fabs(x))
    6072                 :         40 :                 c += ((f - t) + x);
    6073                 :            :             else
    6074                 :          8 :                 c += ((x - t) + f);
    6075                 :         48 :             f = t;
    6076                 :            :         }
    6077                 :         18 :         f += c;
    6078                 :         18 :         return DBL2NUM(f);
    6079                 :            : 
    6080                 :            :       not_float:
    6081                 :          9 :         v = DBL2NUM(f);
    6082                 :            :     }
    6083                 :            : 
    6084                 :            :     goto has_some_value;
    6085         [ +  + ]:         13 :     for (; i < RARRAY_LEN(ary); i++) {
    6086                 :          6 :         e = RARRAY_AREF(ary, i);
    6087         [ -  + ]:          6 :         if (block_given)
    6088                 :          6 :             e = rb_yield(e);
    6089                 :            :       has_some_value:
    6090                 :         15 :         v = rb_funcall(v, idPLUS, 1, e);
    6091                 :            :     }
    6092                 :          7 :     return v;
    6093                 :            : }
    6094                 :            : 
    6095                 :            : /*
    6096                 :            :  *  Arrays are ordered, integer-indexed collections of any object.
    6097                 :            :  *
    6098                 :            :  *  Array indexing starts at 0, as in C or Java.  A negative index is assumed
    6099                 :            :  *  to be relative to the end of the array---that is, an index of -1 indicates
    6100                 :            :  *  the last element of the array, -2 is the next to last element in the
    6101                 :            :  *  array, and so on.
    6102                 :            :  *
    6103                 :            :  *  == Creating Arrays
    6104                 :            :  *
    6105                 :            :  *  A new array can be created by using the literal constructor
    6106                 :            :  *  <code>[]</code>.  Arrays can contain different types of objects.  For
    6107                 :            :  *  example, the array below contains an Integer, a String and a Float:
    6108                 :            :  *
    6109                 :            :  *     ary = [1, "two", 3.0] #=> [1, "two", 3.0]
    6110                 :            :  *
    6111                 :            :  *  An array can also be created by explicitly calling Array.new with zero, one
    6112                 :            :  *  (the initial size of the Array) or two arguments (the initial size and a
    6113                 :            :  *  default object).
    6114                 :            :  *
    6115                 :            :  *     ary = Array.new    #=> []
    6116                 :            :  *     Array.new(3)       #=> [nil, nil, nil]
    6117                 :            :  *     Array.new(3, true) #=> [true, true, true]
    6118                 :            :  *
    6119                 :            :  *  Note that the second argument populates the array with references to the
    6120                 :            :  *  same object.  Therefore, it is only recommended in cases when you need to
    6121                 :            :  *  instantiate arrays with natively immutable objects such as Symbols,
    6122                 :            :  *  numbers, true or false.
    6123                 :            :  *
    6124                 :            :  *  To create an array with separate objects a block can be passed instead.
    6125                 :            :  *  This method is safe to use with mutable objects such as hashes, strings or
    6126                 :            :  *  other arrays:
    6127                 :            :  *
    6128                 :            :  *     Array.new(4) {Hash.new}    #=> [{}, {}, {}, {}]
    6129                 :            :  *     Array.new(4) {|i| i.to_s } #=> ["0", "1", "2", "3"]
    6130                 :            :  *
    6131                 :            :  *  This is also a quick way to build up multi-dimensional arrays:
    6132                 :            :  *
    6133                 :            :  *     empty_table = Array.new(3) {Array.new(3)}
    6134                 :            :  *     #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
    6135                 :            :  *
    6136                 :            :  *  An array can also be created by using the Array() method, provided by
    6137                 :            :  *  Kernel, which tries to call #to_ary, then #to_a on its argument.
    6138                 :            :  *
    6139                 :            :  *      Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
    6140                 :            :  *
    6141                 :            :  *  == Example Usage
    6142                 :            :  *
    6143                 :            :  *  In addition to the methods it mixes in through the Enumerable module, the
    6144                 :            :  *  Array class has proprietary methods for accessing, searching and otherwise
    6145                 :            :  *  manipulating arrays.
    6146                 :            :  *
    6147                 :            :  *  Some of the more common ones are illustrated below.
    6148                 :            :  *
    6149                 :            :  *  == Accessing Elements
    6150                 :            :  *
    6151                 :            :  *  Elements in an array can be retrieved using the Array#[] method.  It can
    6152                 :            :  *  take a single integer argument (a numeric index), a pair of arguments
    6153                 :            :  *  (start and length) or a range. Negative indices start counting from the end,
    6154                 :            :  *  with -1 being the last element.
    6155                 :            :  *
    6156                 :            :  *     arr = [1, 2, 3, 4, 5, 6]
    6157                 :            :  *     arr[2]    #=> 3
    6158                 :            :  *     arr[100]  #=> nil
    6159                 :            :  *     arr[-3]   #=> 4
    6160                 :            :  *     arr[2, 3] #=> [3, 4, 5]
    6161                 :            :  *     arr[1..4] #=> [2, 3, 4, 5]
    6162                 :            :  *     arr[1..-3] #=> [2, 3, 4]
    6163                 :            :  *
    6164                 :            :  *  Another way to access a particular array element is by using the #at method
    6165                 :            :  *
    6166                 :            :  *     arr.at(0) #=> 1
    6167                 :            :  *
    6168                 :            :  *  The #slice method works in an identical manner to Array#[].
    6169                 :            :  *
    6170                 :            :  *  To raise an error for indices outside of the array bounds or else to
    6171                 :            :  *  provide a default value when that happens, you can use #fetch.
    6172                 :            :  *
    6173                 :            :  *     arr = ['a', 'b', 'c', 'd', 'e', 'f']
    6174                 :            :  *     arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
    6175                 :            :  *     arr.fetch(100, "oops") #=> "oops"
    6176                 :            :  *
    6177                 :            :  *  The special methods #first and #last will return the first and last
    6178                 :            :  *  elements of an array, respectively.
    6179                 :            :  *
    6180                 :            :  *     arr.first #=> 1
    6181                 :            :  *     arr.last  #=> 6
    6182                 :            :  *
    6183                 :            :  *  To return the first +n+ elements of an array, use #take
    6184                 :            :  *
    6185                 :            :  *     arr.take(3) #=> [1, 2, 3]
    6186                 :            :  *
    6187                 :            :  *  #drop does the opposite of #take, by returning the elements after +n+
    6188                 :            :  *  elements have been dropped:
    6189                 :            :  *
    6190                 :            :  *     arr.drop(3) #=> [4, 5, 6]
    6191                 :            :  *
    6192                 :            :  *  == Obtaining Information about an Array
    6193                 :            :  *
    6194                 :            :  *  Arrays keep track of their own length at all times.  To query an array
    6195                 :            :  *  about the number of elements it contains, use #length, #count or #size.
    6196                 :            :  *
    6197                 :            :  *    browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
    6198                 :            :  *    browsers.length #=> 5
    6199                 :            :  *    browsers.count #=> 5
    6200                 :            :  *
    6201                 :            :  *  To check whether an array contains any elements at all
    6202                 :            :  *
    6203                 :            :  *    browsers.empty? #=> false
    6204                 :            :  *
    6205                 :            :  *  To check whether a particular item is included in the array
    6206                 :            :  *
    6207                 :            :  *    browsers.include?('Konqueror') #=> false
    6208                 :            :  *
    6209                 :            :  *  == Adding Items to Arrays
    6210                 :            :  *
    6211                 :            :  *  Items can be added to the end of an array by using either #push or #<<
    6212                 :            :  *
    6213                 :            :  *    arr = [1, 2, 3, 4]
    6214                 :            :  *    arr.push(5) #=> [1, 2, 3, 4, 5]
    6215                 :            :  *    arr << 6    #=> [1, 2, 3, 4, 5, 6]
    6216                 :            :  *
    6217                 :            :  *  #unshift will add a new item to the beginning of an array.
    6218                 :            :  *
    6219                 :            :  *     arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]
    6220                 :            :  *
    6221                 :            :  *  With #insert you can add a new element to an array at any position.
    6222                 :            :  *
    6223                 :            :  *     arr.insert(3, 'apple')  #=> [0, 1, 2, 'apple', 3, 4, 5, 6]
    6224                 :            :  *
    6225                 :            :  *  Using the #insert method, you can also insert multiple values at once:
    6226                 :            :  *
    6227                 :            :  *     arr.insert(3, 'orange', 'pear', 'grapefruit')
    6228                 :            :  *     #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
    6229                 :            :  *
    6230                 :            :  *  == Removing Items from an Array
    6231                 :            :  *
    6232                 :            :  *  The method #pop removes the last element in an array and returns it:
    6233                 :            :  *
    6234                 :            :  *     arr =  [1, 2, 3, 4, 5, 6]
    6235                 :            :  *     arr.pop #=> 6
    6236                 :            :  *     arr #=> [1, 2, 3, 4, 5]
    6237                 :            :  *
    6238                 :            :  *  To retrieve and at the same time remove the first item, use #shift:
    6239                 :            :  *
    6240                 :            :  *     arr.shift #=> 1
    6241                 :            :  *     arr #=> [2, 3, 4, 5]
    6242                 :            :  *
    6243                 :            :  *  To delete an element at a particular index:
    6244                 :            :  *
    6245                 :            :  *     arr.delete_at(2) #=> 4
    6246                 :            :  *     arr #=> [2, 3, 5]
    6247                 :            :  *
    6248                 :            :  *  To delete a particular element anywhere in an array, use #delete:
    6249                 :            :  *
    6250                 :            :  *     arr = [1, 2, 2, 3]
    6251                 :            :  *     arr.delete(2) #=> 2
    6252                 :            :  *     arr #=> [1,3]
    6253                 :            :  *
    6254                 :            :  *  A useful method if you need to remove +nil+ values from an array is
    6255                 :            :  *  #compact:
    6256                 :            :  *
    6257                 :            :  *     arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
    6258                 :            :  *     arr.compact  #=> ['foo', 0, 'bar', 7, 'baz']
    6259                 :            :  *     arr          #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
    6260                 :            :  *     arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
    6261                 :            :  *     arr          #=> ['foo', 0, 'bar', 7, 'baz']
    6262                 :            :  *
    6263                 :            :  *  Another common need is to remove duplicate elements from an array.
    6264                 :            :  *
    6265                 :            :  *  It has the non-destructive #uniq, and destructive method #uniq!
    6266                 :            :  *
    6267                 :            :  *     arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
    6268                 :            :  *     arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
    6269                 :            :  *
    6270                 :            :  *  == Iterating over Arrays
    6271                 :            :  *
    6272                 :            :  *  Like all classes that include the Enumerable module, Array has an each
    6273                 :            :  *  method, which defines what elements should be iterated over and how.  In
    6274                 :            :  *  case of Array's #each, all elements in the Array instance are yielded to
    6275                 :            :  *  the supplied block in sequence.
    6276                 :            :  *
    6277                 :            :  *  Note that this operation leaves the array unchanged.
    6278                 :            :  *
    6279                 :            :  *     arr = [1, 2, 3, 4, 5]
    6280                 :            :  *     arr.each {|a| print a -= 10, " "}
    6281                 :            :  *     # prints: -9 -8 -7 -6 -5
    6282                 :            :  *     #=> [1, 2, 3, 4, 5]
    6283                 :            :  *
    6284                 :            :  *  Another sometimes useful iterator is #reverse_each which will iterate over
    6285                 :            :  *  the elements in the array in reverse order.
    6286                 :            :  *
    6287                 :            :  *     words = %w[first second third fourth fifth sixth]
    6288                 :            :  *     str = ""
    6289                 :            :  *     words.reverse_each {|word| str += "#{word} "}
    6290                 :            :  *     p str #=> "sixth fifth fourth third second first "
    6291                 :            :  *
    6292                 :            :  *  The #map method can be used to create a new array based on the original
    6293                 :            :  *  array, but with the values modified by the supplied block:
    6294                 :            :  *
    6295                 :            :  *     arr.map {|a| 2*a}     #=> [2, 4, 6, 8, 10]
    6296                 :            :  *     arr                   #=> [1, 2, 3, 4, 5]
    6297                 :            :  *     arr.map! {|a| a**2}   #=> [1, 4, 9, 16, 25]
    6298                 :            :  *     arr                   #=> [1, 4, 9, 16, 25]
    6299                 :            :  *
    6300                 :            :  *  == Selecting Items from an Array
    6301                 :            :  *
    6302                 :            :  *  Elements can be selected from an array according to criteria defined in a
    6303                 :            :  *  block.  The selection can happen in a destructive or a non-destructive
    6304                 :            :  *  manner.  While the destructive operations will modify the array they were
    6305                 :            :  *  called on, the non-destructive methods usually return a new array with the
    6306                 :            :  *  selected elements, but leave the original array unchanged.
    6307                 :            :  *
    6308                 :            :  *  === Non-destructive Selection
    6309                 :            :  *
    6310                 :            :  *     arr = [1, 2, 3, 4, 5, 6]
    6311                 :            :  *     arr.select {|a| a > 3}       #=> [4, 5, 6]
    6312                 :            :  *     arr.reject {|a| a < 3}       #=> [3, 4, 5, 6]
    6313                 :            :  *     arr.drop_while {|a| a < 4}   #=> [4, 5, 6]
    6314                 :            :  *     arr                          #=> [1, 2, 3, 4, 5, 6]
    6315                 :            :  *
    6316                 :            :  *  === Destructive Selection
    6317                 :            :  *
    6318                 :            :  *  #select! and #reject! are the corresponding destructive methods to #select
    6319                 :            :  *  and #reject
    6320                 :            :  *
    6321                 :            :  *  Similar to #select vs. #reject, #delete_if and #keep_if have the exact
    6322                 :            :  *  opposite result when supplied with the same block:
    6323                 :            :  *
    6324                 :            :  *     arr.delete_if {|a| a < 4}   #=> [4, 5, 6]
    6325                 :            :  *     arr                         #=> [4, 5, 6]
    6326                 :            :  *
    6327                 :            :  *     arr = [1, 2, 3, 4, 5, 6]
    6328                 :            :  *     arr.keep_if {|a| a < 4}   #=> [1, 2, 3]
    6329                 :            :  *     arr                       #=> [1, 2, 3]
    6330                 :            :  *
    6331                 :            :  */
    6332                 :            : 
    6333                 :            : void
    6334                 :       4591 : Init_Array(void)
    6335                 :            : {
    6336                 :            : #undef rb_intern
    6337                 :            : #define rb_intern(str) rb_intern_const(str)
    6338                 :            : 
    6339                 :       4591 :     rb_cArray  = rb_define_class("Array", rb_cObject);
    6340                 :       4591 :     rb_include_module(rb_cArray, rb_mEnumerable);
    6341                 :            : 
    6342                 :       4591 :     rb_define_alloc_func(rb_cArray, empty_ary_alloc);
    6343                 :       4591 :     rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
    6344                 :       4591 :     rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
    6345                 :       4591 :     rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
    6346                 :       4591 :     rb_define_method(rb_cArray, "initialize_copy", rb_ary_replace, 1);
    6347                 :            : 
    6348                 :       4591 :     rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
    6349                 :       4591 :     rb_define_alias(rb_cArray,  "to_s", "inspect");
    6350                 :       4591 :     rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
    6351                 :       4591 :     rb_define_method(rb_cArray, "to_h", rb_ary_to_h, 0);
    6352                 :       4591 :     rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
    6353                 :            : 
    6354                 :       4591 :     rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
    6355                 :       4591 :     rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
    6356                 :       4591 :     rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
    6357                 :            : 
    6358                 :       4591 :     rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
    6359                 :       4591 :     rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
    6360                 :       4591 :     rb_define_method(rb_cArray, "at", rb_ary_at, 1);
    6361                 :       4591 :     rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
    6362                 :       4591 :     rb_define_method(rb_cArray, "first", rb_ary_first, -1);
    6363                 :       4591 :     rb_define_method(rb_cArray, "last", rb_ary_last, -1);
    6364                 :       4591 :     rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
    6365                 :       4591 :     rb_define_method(rb_cArray, "union", rb_ary_union_multi, -1);
    6366                 :       4591 :     rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
    6367                 :       4591 :     rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
    6368                 :       4591 :     rb_define_alias(rb_cArray,  "append", "push");
    6369                 :       4591 :     rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);
    6370                 :       4591 :     rb_define_method(rb_cArray, "shift", rb_ary_shift_m, -1);
    6371                 :       4591 :     rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
    6372                 :       4591 :     rb_define_alias(rb_cArray,  "prepend", "unshift");
    6373                 :       4591 :     rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
    6374                 :       4591 :     rb_define_method(rb_cArray, "each", rb_ary_each, 0);
    6375                 :       4591 :     rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
    6376                 :       4591 :     rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
    6377                 :       4591 :     rb_define_method(rb_cArray, "length", rb_ary_length, 0);
    6378                 :       4591 :     rb_define_alias(rb_cArray,  "size", "length");
    6379                 :       4591 :     rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
    6380                 :       4591 :     rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
    6381                 :       4591 :     rb_define_method(rb_cArray, "index", rb_ary_index, -1);
    6382                 :       4591 :     rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
    6383                 :       4591 :     rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
    6384                 :       4591 :     rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
    6385                 :       4591 :     rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
    6386                 :       4591 :     rb_define_method(rb_cArray, "rotate", rb_ary_rotate_m, -1);
    6387                 :       4591 :     rb_define_method(rb_cArray, "rotate!", rb_ary_rotate_bang, -1);
    6388                 :       4591 :     rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
    6389                 :       4591 :     rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
    6390                 :       4591 :     rb_define_method(rb_cArray, "sort_by!", rb_ary_sort_by_bang, 0);
    6391                 :       4591 :     rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
    6392                 :       4591 :     rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
    6393                 :       4591 :     rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
    6394                 :       4591 :     rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
    6395                 :       4591 :     rb_define_method(rb_cArray, "select", rb_ary_select, 0);
    6396                 :       4591 :     rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
    6397                 :       4591 :     rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
    6398                 :       4591 :     rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
    6399                 :       4591 :     rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
    6400                 :       4591 :     rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);
    6401                 :       4591 :     rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
    6402                 :       4591 :     rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
    6403                 :       4591 :     rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
    6404                 :       4591 :     rb_define_method(rb_cArray, "reject", rb_ary_reject, 0);
    6405                 :       4591 :     rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
    6406                 :       4591 :     rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);
    6407                 :       4591 :     rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);
    6408                 :       4591 :     rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);
    6409                 :       4591 :     rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
    6410                 :       4591 :     rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
    6411                 :       4591 :     rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
    6412                 :       4591 :     rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
    6413                 :            : 
    6414                 :       4591 :     rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
    6415                 :       4591 :     rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
    6416                 :            : 
    6417                 :       4591 :     rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
    6418                 :       4591 :     rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
    6419                 :            : 
    6420                 :       4591 :     rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
    6421                 :       4591 :     rb_define_method(rb_cArray, "*", rb_ary_times, 1);
    6422                 :            : 
    6423                 :       4591 :     rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
    6424                 :       4591 :     rb_define_method(rb_cArray, "&", rb_ary_and, 1);
    6425                 :       4591 :     rb_define_method(rb_cArray, "|", rb_ary_or, 1);
    6426                 :            : 
    6427                 :       4591 :     rb_define_method(rb_cArray, "max", rb_ary_max, -1);
    6428                 :       4591 :     rb_define_method(rb_cArray, "min", rb_ary_min, -1);
    6429                 :            : 
    6430                 :       4591 :     rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
    6431                 :       4591 :     rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
    6432                 :       4591 :     rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
    6433                 :       4591 :     rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
    6434                 :       4591 :     rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
    6435                 :       4591 :     rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
    6436                 :       4591 :     rb_define_method(rb_cArray, "count", rb_ary_count, -1);
    6437                 :       4591 :     rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1);
    6438                 :       4591 :     rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1);
    6439                 :       4591 :     rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
    6440                 :       4591 :     rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
    6441                 :       4591 :     rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
    6442                 :       4591 :     rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
    6443                 :       4591 :     rb_define_method(rb_cArray, "repeated_permutation", rb_ary_repeated_permutation, 1);
    6444                 :       4591 :     rb_define_method(rb_cArray, "repeated_combination", rb_ary_repeated_combination, 1);
    6445                 :       4591 :     rb_define_method(rb_cArray, "product", rb_ary_product, -1);
    6446                 :            : 
    6447                 :       4591 :     rb_define_method(rb_cArray, "take", rb_ary_take, 1);
    6448                 :       4591 :     rb_define_method(rb_cArray, "take_while", rb_ary_take_while, 0);
    6449                 :       4591 :     rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
    6450                 :       4591 :     rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
    6451                 :       4591 :     rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
    6452                 :       4591 :     rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
    6453                 :       4591 :     rb_define_method(rb_cArray, "any?", rb_ary_any_p, -1);
    6454                 :       4591 :     rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
    6455                 :       4591 :     rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
    6456                 :            : 
    6457                 :       4591 :     id_random = rb_intern("random");
    6458                 :       4591 : }

Generated by: LCOV version 1.13