LCOV - code coverage report
Current view: top level - ruby - array.c (source / functions) Hit Total Coverage
Test: lcov-all-filtered.info Lines: 2091 2116 98.8 %
Date: 2017-12-14 20:32:32 Functions: 194 195 99.5 %
Branches: 2151 2819 76.3 %

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

Generated by: LCOV version 1.13