LCOV - code coverage report
Current view: top level - ruby - array.c (source / functions) Hit Total Coverage
Test: lcov-all-filtered.info Lines: 2084 2109 98.8 %
Date: 2017-10-20 17:30:17 Functions: 191 192 99.5 %
Branches: 2147 2815 76.3 %

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

Generated by: LCOV version 1.13