JL_DLLEXPORT void jl_array_del_end(jl_array_t *a, size_t dec) { size_t n = jl_array_nrows(a); if (__unlikely(n < dec)) jl_bounds_error_int((jl_value_t*)a, 0); if (__unlikely(a->flags.isshared)) array_try_unshare(a); jl_array_del_at_end(a, n - dec, dec, n); }
STATIC_INLINE void jl_array_grow_at_end(jl_array_t *a, size_t idx, size_t inc, size_t n) { // optimized for the case of only growing and shrinking at the end if (__unlikely(a->flags.isshared)) { if (a->flags.how != 3) jl_error("cannot resize array with shared data"); if (inc == 0) { // If inc > 0, it will always trigger the slow path and unshare the // buffer array_try_unshare(a); return; } } size_t elsz = a->elsize; char *data = (char*)a->data; int has_gap = n > idx; if (__unlikely((n + inc) > a->maxsize - a->offset)) { size_t nb1 = idx * elsz; size_t nbinc = inc * elsz; size_t newlen = a->maxsize == 0 ? (inc < 4 ? 4 : inc) : a->maxsize * 2; while ((n + inc) > newlen - a->offset) newlen *= 2; newlen = limit_overallocation(a, n, newlen, inc); int newbuf = array_resize_buffer(a, newlen); char *newdata = (char*)a->data + a->offset * elsz; if (newbuf) { memcpy(newdata, data, nb1); if (has_gap) { memcpy(newdata + nb1 + nbinc, data + nb1, n * elsz - nb1); } } else if (has_gap) { memmove(newdata + nb1 + nbinc, newdata + nb1, n * elsz - nb1); } a->data = data = newdata; } else if (has_gap) { size_t nb1 = idx * elsz; memmove(data + nb1 + inc * elsz, data + nb1, n * elsz - nb1); } size_t newnrows = n + inc; #ifdef STORE_ARRAY_LEN a->length = newnrows; #endif a->nrows = newnrows; if (a->flags.ptrarray) { memset(data + idx * elsz, 0, inc * elsz); } }
void jl_array_del_end(jl_array_t *a, size_t dec) { if (dec == 0) return; if (dec > a->nrows) jl_throw(jl_bounds_exception); if (a->isshared) array_try_unshare(a); char *ptail = (char*)a->data + (a->nrows-dec)*a->elsize; if (a->ptrarray) memset(ptail, 0, dec*a->elsize); else ptail[0] = 0; #ifdef STORE_ARRAY_LEN a->length -= dec; #endif a->nrows -= dec; }
JL_DLLEXPORT void jl_array_del_at(jl_array_t *a, ssize_t idx, size_t dec) { size_t n = jl_array_nrows(a); size_t last = idx + dec; if (__unlikely(idx < 0)) jl_bounds_error_int((jl_value_t*)a, idx + 1); if (__unlikely(last > n)) jl_bounds_error_int((jl_value_t*)a, last); // The unsharing needs to happen before we modify the buffer if (__unlikely(a->flags.isshared)) array_try_unshare(a); if (idx < n - last) { jl_array_del_at_beg(a, idx, dec, n); } else { jl_array_del_at_end(a, idx, dec, n); } }
void jl_array_del_end(jl_array_t *a, size_t dec) { if (dec == 0) return; if (dec > a->nrows) jl_bounds_error_int((jl_value_t*)a, a->nrows - dec); if (a->isshared) array_try_unshare(a); if (a->elsize > 0) { char *ptail = (char*)a->data + (a->nrows-dec)*a->elsize; assert(ptail < (char*)a->data + (a->length*a->elsize)); if (a->ptrarray) memset(ptail, 0, dec*a->elsize); else ptail[0] = 0; } #ifdef STORE_ARRAY_LEN a->length -= dec; #endif a->nrows -= dec; }
void jl_array_grow_beg(jl_array_t *a, size_t inc) { if (inc == 0) return; // designed to handle the case of growing and shrinking at both ends if (a->isshared) array_try_unshare(a); size_t es = a->elsize; size_t incnb = inc*es; if (a->offset >= inc) { a->data = (char*)a->data - incnb; a->offset -= inc; } else { size_t alen = a->nrows; size_t anb = alen*es; if (inc > (a->maxsize-alen)/2 - (a->maxsize-alen)/20) { size_t newlen = a->maxsize==0 ? inc*2 : a->maxsize*2; while (alen+2*inc > newlen-a->offset) newlen *= 2; newlen = limit_overallocation(a, alen, newlen, 2*inc); size_t center = (newlen - (alen + inc))/2; array_resize_buffer(a, newlen, alen, center+inc); char *newdata = (char*)a->data - (center+inc)*es; if (a->ptrarray) { memset(newdata, 0, (center+inc)*es); } a->offset = center; a->data = newdata + center*es; } else { size_t center = (a->maxsize - (alen + inc))/2; char *newdata = (char*)a->data - es*a->offset + es*center; memmove(&newdata[incnb], a->data, anb); a->data = newdata; a->offset = center; } } #ifdef STORE_ARRAY_LEN a->length += inc; #endif a->nrows += inc; }
void jl_array_del_beg(jl_array_t *a, size_t dec) { if (dec == 0) return; if (dec > a->nrows) jl_throw(jl_bounds_exception); if (a->isshared) array_try_unshare(a); size_t es = a->elsize; size_t nb = dec*es; memset(a->data, 0, nb); size_t offset = a->offset; offset += dec; a->data = (char*)a->data + nb; #ifdef STORE_ARRAY_LEN a->length -= dec; #endif a->nrows -= dec; // make sure offset doesn't grow forever due to deleting at beginning // and growing at end size_t newoffs = offset; if (offset >= 13*a->maxsize/20) { newoffs = 17*(a->maxsize - a->nrows)/100; } #ifdef _P64 while (newoffs > (size_t)((uint32_t)-1)) { newoffs = newoffs/2; } #endif if (newoffs != offset) { size_t anb = a->nrows*es; size_t delta = (offset - newoffs)*es; a->data = (char*)a->data - delta; memmove(a->data, (char*)a->data + delta, anb); } a->offset = newoffs; }
STATIC_INLINE void jl_array_grow_at_beg(jl_array_t *a, size_t idx, size_t inc, size_t n) { // designed to handle the case of growing and shrinking at both ends if (__unlikely(a->flags.isshared)) { if (a->flags.how != 3) jl_error("cannot resize array with shared data"); if (inc == 0) { // If inc > 0, it will always trigger the slow path and unshare the // buffer array_try_unshare(a); return; } } size_t newnrows = n + inc; size_t elsz = a->elsize; size_t nbinc = inc * elsz; char *data = (char*)a->data; char *newdata; if (a->offset >= inc) { assert(!a->flags.isshared); newdata = data - nbinc; a->offset -= inc; if (idx > 0) { memmove(newdata, data, idx * elsz); } } else { size_t oldoffsnb = a->offset * elsz; size_t nb1 = idx * elsz; if (inc > (a->maxsize - n) / 2 - (a->maxsize - n) / 20) { size_t newlen = a->maxsize == 0 ? inc * 2 : a->maxsize * 2; while (n + 2 * inc > newlen - a->offset) newlen *= 2; newlen = limit_overallocation(a, n, newlen, 2 * inc); size_t newoffset = (newlen - newnrows) / 2; if (!array_resize_buffer(a, newlen)) data = (char*)a->data + oldoffsnb; newdata = (char*)a->data + newoffset * elsz; // We could use memcpy if resizing allocates a new buffer, // hopefully it's not a particularly important optimization. if (idx > 0 && newdata < data) memmove(newdata, data, nb1); memmove(newdata + nbinc + nb1, data + nb1, n * elsz - nb1); if (idx > 0 && newdata > data) memmove(newdata, data, nb1); a->offset = newoffset; } else { assert(!a->flags.isshared); a->offset = (a->maxsize - newnrows) / 2; newdata = data - oldoffsnb + a->offset * elsz; // We could use memcpy if resizing allocates a new buffer, // hopefully it's not a particularly important optimization. if (idx > 0 && newdata < data) memmove(newdata, data, nb1); memmove(newdata + nbinc + nb1, data + nb1, n * elsz - nb1); if (idx > 0 && newdata > data) memmove(newdata, data, nb1); } } #ifdef STORE_ARRAY_LEN a->length = newnrows; #endif a->nrows = newnrows; a->data = newdata; if (a->flags.ptrarray) { memset(newdata + idx * elsz, 0, nbinc); } }