#ifndef _KNOTKIT_LIB_VECTOR_H #define _KNOTKIT_LIB_VECTOR_H #include template class vector { protected: class data { public: unsigned refcount; unsigned n; unsigned c; T p[1]; }; data *d; static data *alloc (unsigned n_, unsigned c_, unsigned initn, T *init); void unref (); void ref (data *newd) { assert (d == 0); d = newd; if (d) d->refcount ++; } T &at (unsigned i) { return operator [] (i); } const T &at (unsigned i) const { return operator [] (i); } public: vector () : d(0) { } explicit vector (unsigned n_); vector (const vector &v) : d(0) { ref (v.d); } vector (const vector &v, const vector &u); vector (copy, const vector &v); vector (copy2, const vector &v); vector (unsigned n_, T *p_); vector (unsigned n_, const vector &v_); explicit vector (reader &r); ~vector () { unref (); } vector &operator = (const vector &v) { unref (); ref (v.d); return *this; } bool operator == (const vector &v) const; bool operator != (const vector &v) const { return !operator == (v); } bool operator < (const vector &v) const; bool operator % (unsigned i) { return d && i < d->n; } T &operator [] (unsigned i) { assert (d); assert (i < d->n); return d->p[i]; } const T &operator [] (unsigned i) const { assert (d); assert (i < d->n); return d->p[i]; } const T &operator () (unsigned i) const { return operator [] (i); } /* ??? break resize into grow_capacity/resize, and specialize this to in-place ctor from v */ void append (const T &v) { if (!d) reserve (4); else if (d->n == d->c) reserve (d->c * 2); assert (d && d->n < d->c); new (&d->p[d->n ++]) T (v); } const T &top () const { unsigned n = size (); assert (n > 0); return at (n - 1); } T pop (); unsigned capacity () const { return d ? d->c : 0; } unsigned size () const { return d ? d->n : 0; } void resize (unsigned new_size); void reserve (unsigned c); void sort () { assert (d); sort (0, d->n); } void sort (unsigned from, unsigned len); template void sort (unsigned from, unsigned len, C comp); unsigned lower_bound (const T &v) const; unsigned upper_bound (const T &v) const; void write_self (writer &w) const; hash_t hash_self () const; }; template typename vector::data * vector::alloc (unsigned n_, unsigned c_, unsigned initn, T *init) { if (c_ > 0) { data *d = (data *)new char[sizeof (data) + sizeof (T) * (c_ - 1)]; d->refcount = 1; d->c = c_; d->n = n_; if (initn > n_) initn = n_; for (unsigned i = 0; i < initn; i ++) new (&d->p[i]) T (init[i]); for (unsigned i = initn; i < n_; i ++) new (&d->p[i]) T (); return d; } else return 0; } template void vector::unref () { if (d && -- d->refcount == 0) { for (unsigned i = 0; i < d->n; i ++) d->p[i].~T (); delete [] (char *)d; } d = 0; } template vector::vector (const vector &v, const vector &u) : d(0) { if (v.d) { unsigned vn = v.d->n, un = u.size (); d = alloc (vn, vn + un, v.d->n, v.d->p); d->n = vn + un; for (unsigned i = 0; i < un; i ++) new (&d->p[vn + i]) T (u[i]); } else { if (u.d) d = alloc (u.d->n, u.d->n, u.d->n, u.d->p); } } template vector::vector (copy, const vector &v) : d(0) { if (v.d) d = alloc (v.d->n, v.d->n, v.d->n, v.d->p); } template vector::vector (copy2, const vector &v) : d(0) { if (v.d && v.d->n > 0) { unsigned n = v.d->n; d = (data *)new char[sizeof (data) + sizeof (T) * (n - 1)]; d->refcount = 1; d->c = n; d->n = n; for (unsigned i = 0; i < n; i ++) new (&d->p[i]) T (COPY1, v.d->p[i]); } } template vector::vector (unsigned n_) : d(0) { d = alloc (n_, n_, 0, 0); } template vector::vector (reader &r) : d(0) { unsigned n_; read (r, n_); if (n_ > 0) { d = (data *)new char[sizeof (data) + sizeof (T) * (n_ - 1)]; d->refcount = 1; d->c = n_; d->n = n_; for (unsigned i = 0; i < n_; i ++) ctor_read (r, &d->p[i]); } } template vector::vector (unsigned n_, T *p_) : d(0) { d = alloc (n_, n_, n_, p_); } template vector::vector (unsigned n_, const vector &v) : d(0) { if (v.d) d = alloc (n_, n_, v.d->n, v.d->p); else d = alloc (n_, n_, 0, 0); } template bool vector::operator < (const vector &v) const { unsigned n = size (), vn = v.size (); if (n < vn) return 1; else if (n > vn) return 0; for (unsigned i = 0; i < n; i ++) { if (at (i) < v[i]) return 1; else if (at (i) > v[i]) return 0; } return 0; } template bool vector::operator == (const vector &v) const { unsigned n = size (); if (n != v.size ()) return 0; for (unsigned i = 0; i < n; i ++) { if (at (i) != v[i]) return 0; } return 1; } template T vector::pop () { unsigned n = size (); assert (n > 0); T tmp = at (n - 1); resize (n - 1); return tmp; } template void vector::reserve (unsigned newc) { if (newc <= capacity ()) return; data *newd; if (d) newd = alloc (d->n, newc, d->n, d->p); else newd = alloc (0, newc, 0, 0); unref (); d = newd; } template void vector::resize (unsigned new_size) { unsigned n = size (); if (new_size == n) return; reserve (new_size); assert (d); assert (new_size <= capacity ()); if (new_size < n) { for (unsigned i = new_size; i < n; i ++) d->p[i].~T (); } else { for (unsigned i = n; i < new_size; i ++) new (&d->p[i]) T (); } d->n = new_size; } template void vector::sort (unsigned from, unsigned len) { assert (d); assert (from < d->n); assert (from + len <= d->n); std::sort (&d->p[from], &d->p[from + len]); } template template void vector::sort (unsigned from, unsigned len, C comp) { assert (d); assert (from < d->n); assert (from + len <= d->n); std::sort (&d->p[from], &d->p[from + len], comp); } template void vector::write_self (writer &w) const { if (d) { write (w, d->n); for (unsigned i = 0; i < d->n; i ++) write (w, d->p[i]); } else { unsigned n = 0; write (w, n); } } template hash_t vector::hash_self () const { unsigned n = size (); hash_t h = hash (n); for (unsigned i = 0; i < n; i ++) h = hash_combine (h, hash (d->p[i])); return h; } template unsigned vector::lower_bound (const T &v) const { T *r = std::lower_bound (&d->p[0], &d->p[d->n], v); return r - &d->p[0]; } template unsigned vector::upper_bound (const T &v) const { T *r = std::upper_bound (&d->p[0], &d->p[d->n], v); return r - &d->p[0]; } template class basedvector : public vector { public: basedvector () { } explicit basedvector (unsigned n_) : vector(n_) { } explicit basedvector (vector &v_) : vector(v_) { } basedvector (unsigned n_, T *p_) : vector(n_, p_) { } basedvector (unsigned n_, const vector &v_) : vector(n_, v_) { } basedvector (copy, const vector &v_) : vector(COPY, v_) { } basedvector (copy2, const vector &v_) : vector(COPY2, v_) { } basedvector (const vector &v_, const vector &u_) : vector(v_, u_) { } explicit basedvector (reader &r) : vector(r) { } ~basedvector () { } vector &operator = (const vector &v) { vector::operator = (v); } bool operator % (unsigned i) { return vector::operator % (i - B); } T &operator [] (unsigned i) { return vector::operator [] (i - B); } const T &operator [] (unsigned i) const { return vector::operator [] (i - B); } const T &operator () (unsigned i) const { return vector::operator () (i - B); } void sort () { vector::sort (); } void sort (unsigned from, unsigned len) { vector::sort (from - B, len); } template void sort (unsigned from, unsigned len, C comp) { vector::sort (from - B, len, comp); } unsigned lower_bound (const T &v) const { return vector::lower_bound (v) + B; } unsigned upper_bound (const T &v) const { return vector::upper_bound (v) + B; } }; #endif // _KNOTKIT_LIB_VECTOR_H