template void Flex::Destroy(int from, int count) { DestroyArray(data, data + count); } template void Flex::Free() { if(data) { DestroyArray(data, data + count); delete[] (byte *)data; delete offset; data = NULL; } } template void Flex::Init() { SHIFT = sizeof(T) < 16 ? 8 : sizeof(T) < 64 ? 7 : sizeof(T) < 256 ? 6 : 5; NBLK = 1 << SHIFT; MASK = NBLK - 1; blk_items = blk_count = 0; data = NULL; static int zero = 0; offset = &zero; alloc = count = 0; } template void Flex::Clear() { Free(); Init(); } template void Flex::Expand(int n) { unsigned ns = count + n; ns = ns + (ns >> 1); alloc = max(max(1, int(16 / sizeof(T))), (int)ns); T *newdata = (T *) new byte[sizeof(T) * alloc]; int rawsz = count * sizeof(T); int *newoffset; const unsigned growk = 18; if(growk * blk_count > NBLK * sizeof(T)) { T *t = newdata; for(int i = 0; i < blk_count; i++) { int off = offset[i] & MASK; T *bpos = data + (i << SHIFT); int sz = NBLK - off; memcpy(t, bpos + off, sz * sizeof(T)); t += sz; memcpy(t, bpos, off * sizeof(T)); t += off; } memcpy(t, data + blk_items, (count - blk_items) * sizeof(T)); do { SHIFT++; blk_count = (unsigned)count >> SHIFT; } while(growk * blk_count > NBLK * sizeof(T)); NBLK = 1 << SHIFT; MASK = NBLK - 1; blk_items = blk_count << SHIFT; newoffset = new int[(alloc >> SHIFT) + 1]; int bpos = 0; for(int i = 0; i <= blk_count; i++) { newoffset[i] = bpos; bpos += NBLK; } } else { memcpy(newdata, data, rawsz); newoffset = new int[(alloc >> SHIFT) + 1]; memcpy(newoffset, offset, ((count >> SHIFT) + 1) * sizeof(int)); } if(data) { delete[] offset; delete[] (byte *) data; } data = newdata; offset = newoffset; } template T *Flex::RawInsert(int i) { Move(i + 1, i, count - i); count++; return &data[i]; } template void Flex::Insert(int i, const T& x) { ASSERT(i >= 0 && i <= count); if(count >= alloc) Expand(count + 1); if(i >= blk_items) DeepCopyConstruct(RawInsert(i), x); else { T *p = RawInsert(blk_items); int tn = i >> SHIFT; int bpos = blk_items - NBLK; int ii = blk_count - 1; while(ii > tn) { offset[ii] = ((offset[ii] - 1) & MASK) + bpos; T *q = &data[bpos + (offset[ii] & MASK)]; *((Data_S_*)p) = *((Data_S_*)q); p = q; --ii; bpos -= NBLK; } int boff = offset[ii] & MASK; int ex = (boff - 1) & MASK; *((Data_S_*)p) = *((Data_S_*)&data[bpos + ex]); i = (i + boff) & MASK; if(i > ex) { Move(bpos + 1, bpos, ex); Move(bpos, bpos + NBLK - 1, 1); ex = NBLK - 1; } Move(bpos + i + 1, bpos + i, ex - i); DeepCopyConstruct(&data[bpos + i], x); } if(count > blk_items + NBLK) { blk_items += NBLK; blk_count++; offset[blk_count] = blk_items; } } template void Flex::Remove(int i, const T& x) { ASSERT(i >= 0 && i <= count); if(i >= blk_items) RawRemove(i); else { int tn = i >> SHIFT; } if(count < blk_items) { } } #define DDUMP(i) //DUMP(i) #define DDUMPC(i) //DUMPC(i) #define DLOG(i) //LOG(i) template template inline int Flex::LBound(const T& x, int l, int h, const Less& less) const { while(l < h) { int mid = unsigned(l + h) >> 1; if(less(data[mid], x)) l = mid + 1; else h = mid; } return l; } template template int Flex::FindLowerBound0(const T& x, const Less& less) const { int l = 0; int h = blk_count + 1; while(l < h) { int mid = unsigned(l + h) >> 1; if(less(data[offset[mid]], x)) l = mid + 1; else h = mid; } if(l == blk_count + 1) return LBound(x, blk_items, GetCount(), less); if(l == 0) return 0; int bpos = (l - 1) << SHIFT; int off = offset[l - 1]; if(less(data[bpos + NBLK - 1], x)) return LBound(x, bpos, off, less) + bpos + NBLK - off; else return LBound(x, off, bpos + NBLK, less) - off + bpos; } template template int Flex::UBound(const T& x, int l, int h, const Less& less) const { while(l < h) { int mid = unsigned(l + h) >> 1; if(less(x, data[mid])) h = mid; else l = mid + 1; } return h; } template template int Flex::FindUpperBound(const T& x, const Less& less) const { if(GetCount() == 0) return 0; int l = 0; int h = blk_count + 1; while(l < h) { int mid = unsigned(l + h) >> 1; if(less(x, data[offset[mid]])) h = mid; else l = mid + 1; } if(l == blk_count + 1) return UBound(x, blk_items, GetCount(), less); if(l == 0) return 0; int bpos = (l - 1) << SHIFT; int off = offset[l]; if(less(data[bpos], x)) return bpos + NBLK - off + UBound(x, bpos, off, less); else return bpos + UBound(x, off, bpos + NBLK, less); }