diff --git a/Makefile b/Makefile index 0558a56..402a664 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,8 @@ KNOTKIT_OBJS = planar_diagram.o dt_code.o knot_diagram.o cube.o spanning_tree_co COMMON_OBJS = $(KNOTKIT_OBJS) $(ALGEBRA_OBJS) $(LIB_OBJS) LIB_HEADERS = lib/lib.h lib/show.h lib/refcount.h lib/pair.h lib/maybe.h lib/vector.h \ - lib/set.h lib/ullmanset.h lib/bitset.h lib/smallbitset.h lib/setcommon.h \ + lib/set_wrapper.h lib/set.h lib/hashset.h \ + lib/ullmanset.h lib/bitset.h lib/smallbitset.h lib/setcommon.h \ lib/map_wrapper.h lib/map.h lib/hashmap.h lib/ullmanmap.h lib/mapcommon.h \ lib/unionfind.h lib/priority_queue.h lib/io.h \ lib/directed_multigraph.h diff --git a/algebra/polynomial.h b/algebra/polynomial.h index 3952544..5c3abcd 100644 --- a/algebra/polynomial.h +++ b/algebra/polynomial.h @@ -106,6 +106,7 @@ public: polynomial &operator *= (polynomial p) { return operator = (*this * p); } polynomial &operator *= (T s); + // ??? rename polynomial &add_term (T c, unsigned e) { T &c2 = coeffs[e]; diff --git a/lib/hashmap.h b/lib/hashmap.h index 845da86..75ddae2 100644 --- a/lib/hashmap.h +++ b/lib/hashmap.h @@ -10,10 +10,16 @@ class hashmap : public map_wrapper >, K, V> hashmap () { } hashmap (const hashmap &m) : base(m) { } hashmap (copy, const hashmap &m) : base(COPY, m) { } + hashmap (initializer_list > il) : base(il) { } hashmap (reader &r) : base(r) { } ~hashmap () { } hashmap &operator = (const hashmap &m) { base::operator = (m); return *this; } + hashmap &operator = (initializer_list > il) + { + base::operator = (il); + return *this; + } }; template diff --git a/lib/hashset.h b/lib/hashset.h index 2c0bc97..971eb2a 100644 --- a/lib/hashset.h +++ b/lib/hashset.h @@ -10,10 +10,12 @@ class hashset : public set_wrapper >, T> hashset () { } hashset (const hashset &m) : base(m) { } hashset (copy, const hashset &m) : base(COPY, m) { } + hashset (initializer_list il) : base(il) { } hashset (reader &r) : base(r) { } ~hashset () { } hashset &operator = (const hashset &m) { base::operator = (m); return *this; } + hashset &operator = (initializer_list il) { base::operator = (il); return *this; } }; template diff --git a/lib/lib.h b/lib/lib.h index 070b5e5..b507b58 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -167,6 +168,7 @@ using std::get; using std::make_tuple; using std::tie; using std::ignore; +using std::initializer_list; #include diff --git a/lib/map.h b/lib/map.h index 2521af3..859829a 100644 --- a/lib/map.h +++ b/lib/map.h @@ -11,11 +11,16 @@ class map : public map_wrapper, K, V> map (unsigned dummy_size) : base(dummy_size) { } map (const map &m) : base(m) { } map (copy, const map &m) : base(COPY, m) { } - map (copy2, const map &m) : base(COPY2, m) { } + map (initializer_list > il) : base(il) { } map (reader &r) : base(r) { } ~map () { } map &operator = (const map &m) { base::operator = (m); return *this; } + map &operator = (initializer_list > il) + { + base::operator = (il); + return *this; + } }; template diff --git a/lib/map_wrapper.h b/lib/map_wrapper.h index 48cfacf..e263412 100644 --- a/lib/map_wrapper.h +++ b/lib/map_wrapper.h @@ -15,6 +15,15 @@ class map_wrapper { public: M t; + + public: + map_impl () = default; + map_impl (const map_impl &) = delete; + map_impl (const M &t_) : t(t_) { } + map_impl (initializer_list > il) : t(il) { } + ~map_impl () = default; + + map_impl &operator = (const map_impl &) = delete; }; ptr impl; @@ -25,14 +34,24 @@ class map_wrapper public: map_wrapper () : impl(new map_impl) { } - map_wrapper (unsigned dummy_size) : impl(new map_impl) { } map_wrapper (const map_wrapper &m) : impl(m.impl) { } - map_wrapper (copy, const map_wrapper &m) : impl(new map_impl) { impl->t = M (m.impl->t); } - map_wrapper (copy2, const map_wrapper &m); + map_wrapper (copy, const map_wrapper &m) : impl(new map_impl (m.impl->t)) { } + map_wrapper (initializer_list > il) + : impl(new map_impl (il)) + { } map_wrapper (reader &r); ~map_wrapper () { } map_wrapper &operator = (const map_wrapper &m) { impl = m.impl; return *this; } + map_wrapper &operator = (initializer_list > il) + { + impl->t = il; + return *this; + } + + // range-based for + typename M::const_iterator begin () const { return impl->t.begin (); } + typename M::const_iterator end () const { return impl->t.end (); } /* returns the pair associated to the smallest key */ pair head () const @@ -136,15 +155,6 @@ class map_wrapper void write_self (writer &w) const; }; -template -map_wrapper::map_wrapper (copy2, const map_wrapper &m) - : impl(new map_impl) -{ - /* Keys are immutable. Just copy the values. */ - for (const_iter i = m; i; i ++) - push (i.key (), V (COPY, i.val ())); -} - template map_wrapper::map_wrapper (reader &r) : impl(new map_impl) diff --git a/lib/set.h b/lib/set.h index a2aa03f..0f3e08f 100644 --- a/lib/set.h +++ b/lib/set.h @@ -8,13 +8,14 @@ class set : public set_wrapper, T> public: set () { } - set (unsigned dummy_size) : base(dummy_size) { } set (const set &m) : base(m) { } set (copy, const set &m) : base(COPY, m) { } + set (initializer_list il) : base(il) { } set (reader &r) : base(r) { } ~set () { } set &operator = (const set &m) { base::operator = (m); return *this; } + set &operator = (initializer_list il) { base::operator = (il); } bool operator == (const set &s) const; bool operator != (const set &s) const { return !operator == (s); } diff --git a/lib/set_wrapper.h b/lib/set_wrapper.h index 105c6bc..a31e654 100644 --- a/lib/set_wrapper.h +++ b/lib/set_wrapper.h @@ -15,6 +15,15 @@ class set_wrapper { public: S t; + + public: + set_wrapper_impl () = default; + set_wrapper_impl (const set_wrapper_impl &) = delete; + set_wrapper_impl (const S &t_) : t(t_) { } + set_wrapper_impl (initializer_list il) : t(il) { } + ~set_wrapper_impl () = default; + + set_wrapper_impl &operator = (const set_wrapper_impl &) = delete; }; ptr impl; @@ -25,13 +34,25 @@ class set_wrapper public: set_wrapper () : impl(new set_wrapper_impl) { } - set_wrapper (unsigned dummy_size) : impl(new set_wrapper_impl) { } set_wrapper (const set_wrapper &s) : impl(s.impl) { } - set_wrapper (copy, const set_wrapper &s) : impl(new set_wrapper_impl) { impl->t = S (s.impl->t); } + set_wrapper (copy, const set_wrapper &s) + : impl(new set_wrapper_impl (s.impl->t)) + { } + set_wrapper (initializer_list il) + : impl(new set_wrapper_impl (il)) + { } set_wrapper (reader &r); ~set_wrapper () { } set_wrapper &operator = (const set_wrapper &s) { impl = s.impl; return *this; } + set_wrapper &operator = (initializer_list li) + { + impl->t = li; + } + + // range-based for + typename S::const_iterator begin () const { return impl->t.begin (); } + typename S::const_iterator end () const { return impl->t.end (); } T pop () { diff --git a/lib/ullmanset.h b/lib/ullmanset.h index 658fc33..d6599ad 100644 --- a/lib/ullmanset.h +++ b/lib/ullmanset.h @@ -2,12 +2,15 @@ template class ullmanset_iter; template class ullmanset_const_iter; +template class ullmanset_const_stl_iter; + template class ullmanset { private: friend class ullmanset_iter; friend class ullmanset_const_iter; + friend class ullmanset_const_stl_iter; class keypos { @@ -16,57 +19,56 @@ class ullmanset unsigned pos; }; - class data + class data : public refcounted { public: - unsigned refcount; unsigned size; unsigned n; keypos kp[1]; + + public: + inline void delete_at_pos (unsigned p); }; - data *d; - - void ref (data *newd) { assert (!d); d = newd; if (d) d->refcount ++; } - void unref (); - - inline void delete_at_pos (unsigned p); + ptr d; public: typedef ullmanset_iter iter; typedef ullmanset_const_iter const_iter; public: - ullmanset () : d(0) { } ullmanset (unsigned size); - ullmanset (const ullmanset &s) : d(0) { ref (s.d); } + ullmanset () : ullmanset(0) { } + ullmanset (const ullmanset &s) : d(s.d) { } ullmanset (copy, const ullmanset &s); - // ullmanset (const unsignedset &t); ullmanset (const bitset &t); + ullmanset (unsigned size, initializer_list il); ullmanset (reader &r); - ~ullmanset () { unref (); } + ~ullmanset () { } - ullmanset &operator = (const ullmanset &s) { unref (); ref (s.d); return *this; } - // ullmanset &operator = (const unsignedset &t); + ullmanset &operator = (const ullmanset &s) { d = s.d; return *this; } ullmanset &operator = (const bitset &t); - unsigned size () const { return d ? d->size : 0; } + // range-based for + inline ullmanset_const_stl_iter begin () const; + inline ullmanset_const_stl_iter end () const; - bool is_empty () const { assert (d); return d->n == 0; } - unsigned card () const { assert (d); return d->n; } - unsigned head () const { assert (d); assert (d->n > 0); return d->kp[0].key; } + unsigned size () const { return d->size; } + + bool is_empty () const { return d->n == 0; } + unsigned card () const { return d->n; } + unsigned head () const { assert (d->n > 0); return d->kp[0].key; } bool operator == (const ullmanset &s); bool operator != (const ullmanset &s) { return !operator == (s); } void restore (unsigned old_card) { - assert (d); assert (d->n >= old_card); d->n = old_card; } - void clear () { if (d) { d->n = 0; } } + void clear () { d->n = 0; } inline void push (unsigned k); inline void operator += (unsigned k); // ??? should these be inline? @@ -88,89 +90,75 @@ class ullmanset bool operator % (unsigned k) const { - assert (d); assert ((k - B) >= 0); assert ((k - B) < d->size); unsigned p = d->kp[k - B].pos; return p < d->n && d->kp[p].key == k; } + bool operator () (unsigned k) const { return operator % (k); } // always 0-based - unsigned nth (unsigned p) const { assert (d); assert (p < d->n); return d->kp[p].key; } + unsigned nth (unsigned p) const + { + assert (p < d->n); + return d->kp[p].key; + } - unsigned position (unsigned k) const { assert (operator % (k)); return d->kp[k - B].pos; } + unsigned position (unsigned k) const + { + assert (operator % (k)); + return d->kp[k - B].pos; + } void write_self (writer &w) const; }; template void -ullmanset::unref () +ullmanset::data::delete_at_pos (unsigned p) { - if (d && --d->refcount == 0) - { - delete [] (char *)d; - d = 0; - } -} - -template void -ullmanset::delete_at_pos (unsigned p) -{ - assert (d); - assert (p < d->n); - unsigned n = --d->n; + assert (p < n); + --n; if (p != n) { - unsigned ell = d->kp[n].key; - d->kp[ell - B].pos = p; - d->kp[p].key = ell; + unsigned ell = kp[n].key; + kp[ell - B].pos = p; + kp[p].key = ell; } } template ullmanset::ullmanset (unsigned size) - : d(0) { data *newd = (data *)new char[sizeof (data) + sizeof (keypos) * size - sizeof (keypos)]; - newd->refcount = 0; + new (newd) data; newd->size = size; newd->n = 0; - ref (newd); + d = newd; +} + +template +ullmanset::ullmanset (unsigned size, initializer_list il) + : ullmanset(size) +{ + for (unsigned i : il) + operator += (i); } template ullmanset::ullmanset (copy, const ullmanset &s) - : d(0) + : ullmanset(s.size ()) { - if (s.d) - { - unsigned bytes = (sizeof (data) - + sizeof (keypos) * s.d->size - - sizeof (keypos)); - data *newd = (data *)new char[bytes]; - memcpy (newd, s.d, bytes); - newd->refcount = 0; - ref (newd); - } + d->n = s.d->n; + memcpy (&d->kp[0], &s.d->kp[0], sizeof (keypos) * d->n); } template ullmanset::ullmanset (reader &r) - : d(0) + : ullmanset(r.read_unsigned ()) { - unsigned size_ = r.read_unsigned (); - if (size_ > 0) - { - data *newd = (data *)new char[sizeof (data) + sizeof (keypos) * (size_ - 1)]; - newd->refcount = 0; - newd->size = size_; - newd->n = 0; - ref (newd); - } - unsigned card_ = r.read_unsigned (); for (unsigned i = 0; i < card_; i ++) push (r.read_unsigned ()); @@ -179,8 +167,6 @@ ullmanset::ullmanset (reader &r) template bool ullmanset::operator == (const ullmanset &s) { - assert (d); - assert (s.d); if (d->n != s.d->n) return 0; for (iter i = *this; i; i ++) @@ -194,7 +180,6 @@ ullmanset::operator == (const ullmanset &s) template void ullmanset::push (unsigned k) { - assert (d); assert (!operator % (k)); unsigned p = d->n ++; d->kp[p].key = k; @@ -204,7 +189,6 @@ ullmanset::push (unsigned k) template void ullmanset::operator += (unsigned k) { - assert (d); assert ((k - B) >= 0); assert ((k - B) < d->size); if (!operator % (k)) @@ -218,13 +202,12 @@ ullmanset::operator += (unsigned k) template void ullmanset::operator -= (unsigned k) { - assert (d); assert ((k - B) >= 0); assert ((k - B) < d->size); if (operator % (k)) { unsigned p = d->kp[k - B].pos; - delete_at_pos (p); + d->delete_at_pos (p); } } @@ -270,22 +253,49 @@ ullmanset::write_self (writer &w) const write (w, i.val ()); } +template +class ullmanset_const_stl_iter +{ + private: + ptr::data> d; + unsigned p; + + public: + ullmanset_const_stl_iter (const ullmanset &s, unsigned p_) : d(s.d), p(p_) { } + + bool operator != (const ullmanset_const_stl_iter &end) const { return p != end.p; } + unsigned operator * () const { assert (p < d->n); return d->kp[p].key; } + ullmanset_const_stl_iter &operator ++ () { p ++; return *this; } +}; + +template ullmanset_const_stl_iter +ullmanset::begin () const +{ + return ullmanset_const_stl_iter (*this, 0); +} + +template ullmanset_const_stl_iter +ullmanset::end () const +{ + return ullmanset_const_stl_iter (*this, d->n); +} + template class ullmanset_iter { private: - ullmanset &s; + ptr::data> d; unsigned i; bool deleted; public: - ullmanset_iter (ullmanset &s_) : s(s_), i(0), deleted(0) { assert (s_.d); } + ullmanset_iter (ullmanset &s) : d(s.d), i(0), deleted(0) { } ~ullmanset_iter () { } - void del () { assert (!deleted); assert (i < s.d->n); s.delete_at_pos (i); } - unsigned val () const { assert (!deleted); assert (i < s.d->n); return s.d->kp[i].key; } - unsigned pos () const { assert (!deleted); assert (i < s.d->n); return i; } - operator bool () const { assert (!deleted); return i < s.d->n; } + void del () { assert (!deleted); assert (i < d->n); d->delete_at_pos (i); } + unsigned val () const { assert (!deleted); assert (i < d->n); return d->kp[i].key; } + unsigned pos () const { assert (!deleted); assert (i < d->n); return i; } + operator bool () const { assert (!deleted); return i < d->n; } void operator ++ () { if (deleted) deleted = 0; else i ++; } void operator ++ (int) { operator ++ (); } }; @@ -294,16 +304,16 @@ template class ullmanset_const_iter { private: - const ullmanset &s; + ptr::data> d; unsigned i; public: - ullmanset_const_iter (const ullmanset &s_) : s(s_), i(0) { assert (s_.d); } + ullmanset_const_iter (const ullmanset &s) : d(s.d), i(0) { } ~ullmanset_const_iter () { } - unsigned val () const { assert (i < s.d->n); return s.d->kp[i].key; } - unsigned pos () const { assert (i < s.d->n); return i; } - operator bool () const { return i < s.d->n; } + unsigned val () const { assert (i < d->n); return d->kp[i].key; } + unsigned pos () const { assert (i < d->n); return i; } + operator bool () const { return i < d->n; } void operator ++ () { i ++; } void operator ++ (int) { i ++; } }; diff --git a/main.cpp b/main.cpp index 2ae5f6e..9ba848a 100644 --- a/main.cpp +++ b/main.cpp @@ -127,6 +127,47 @@ rank_lte (multivariate_laurentpoly p, int main () { +#if 0 + ullmanset<1> empty; + assert (empty.size () == 0); + assert (empty.card () == 0); + assert (empty.is_empty ()); + + ullmanset<1> empty2; + assert (empty == empty2); + + ullmanset<1> emptycopy (COPY, empty); + assert (emptycopy == empty); + + ullmanset<1> s (50, {1,2,5,5,2,1,3,4}); + assert (s.card () == 5); + + ullmanset<1> scopy (COPY, s); + assert (scopy == s); + + printf ("s:"); + for (int x : s) + printf (" %d", x); + newline (); +#endif + + map m = { { 5, "foo" }, { 11, "bar" } }; + + hashmap m2 = { { 5, "foo" }, { 11, "bar" }, { 37, "baz" } }; + for (std::pair i : m2) + { + printf ("%d -> %s\n", i.first, i.second); + } + +#if 0 + set s {1,2,5,5,2,1,3,4}; + printf ("s:"); + for (int x : s) + printf (" %d", x); + newline (); +#endif + +#if 0 basedvector v (4); v[1] = 2; v[2] = -1; @@ -205,6 +246,7 @@ main () assert (sleb == sleb2); assert (uleb == uleb2); } +#endif #if 0