diff --git a/NEWS b/NEWS index 39d7047bd..d12c0bb91 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,9 @@ New in spot 2.3.3.dev (not yet released) synonym for spot::twa::prop_universal() to help backward compatibility. + - spot::acc_cond::mark_t::sets() now returns an internal iterable + object instead of an std::vector. + Deprecation notice: - spot::dtwa_complement() used to work only on deterministic diff --git a/python/spot/impl.i b/python/spot/impl.i index be594f45f..a5efcd064 100644 --- a/python/spot/impl.i +++ b/python/spot/impl.i @@ -787,6 +787,14 @@ def state_is_accepting(self, src) -> "bool": } } +%extend spot::internal::mark_container { + swig::SwigPyIterator* __iter__(PyObject **PYTHON_SELF) + { + return swig::make_forward_iterator_np(self->begin(), self->begin(), + self->end(), *PYTHON_SELF); + } +} + %extend spot::twa_graph { unsigned new_univ_edge(unsigned src, const std::vector& v, bdd cond, acc_cond::mark_t acc = 0U) diff --git a/spot/parseaut/parseaut.yy b/spot/parseaut/parseaut.yy index 986183b73..e7169972c 100644 --- a/spot/parseaut/parseaut.yy +++ b/spot/parseaut/parseaut.yy @@ -2173,14 +2173,18 @@ static void fix_acceptance(result_& r) unsigned base = 0; if (both) { - auto v = both.sets(); - auto vs = v.size(); - base = acc.add_sets(vs); + base = acc.add_sets(both.count()); for (auto& t: r.h->aut->edge_vector()) - if ((t.acc & both) != both) - for (unsigned i = 0; i < vs; ++i) - if (!t.acc.has(v[i])) - t.acc |= acc.mark(base + i); + { + unsigned i = 0; + if ((t.acc & both) != both) + for (unsigned v : both.sets()) + { + if (!t.acc.has(v)) + t.acc |= acc.mark(base + i); + i++; + } + } } if (onlyneg || both) diff --git a/spot/twa/acc.hh b/spot/twa/acc.hh index 197804d3d..465e90064 100644 --- a/spot/twa/acc.hh +++ b/spot/twa/acc.hh @@ -28,6 +28,10 @@ namespace spot { + namespace internal + { + class mark_container; + } class SPOT_API acc_cond { public: @@ -297,13 +301,8 @@ namespace spot } } - // FIXME: Return some iterable object without building a vector. - std::vector sets() const - { - std::vector res; - fill(std::back_inserter(res)); - return res; - } + // Returns some iterable object that contains the used sets. + spot::internal::mark_container sets() const; SPOT_API friend std::ostream& operator<<(std::ostream& os, mark_t m); @@ -1243,6 +1242,85 @@ namespace spot SPOT_API std::ostream& operator<<(std::ostream& os, const acc_cond& acc); + + namespace internal + { + class SPOT_API mark_iterator + { + public: + typedef unsigned value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + mark_iterator() noexcept + : m_(0U) + { + } + + mark_iterator(acc_cond::mark_t m) noexcept + : m_(m) + { + } + + bool operator==(mark_iterator m) const + { + return m_ == m.m_; + } + + bool operator!=(mark_iterator m) const + { + return m_ != m.m_; + } + + value_type operator*() const + { + SPOT_ASSERT(m_); + return m_.min_set() - 1; + } + + mark_iterator operator++() + { + m_.id &= m_.id - 1; + return *this; + } + + mark_iterator operator++(int) + { + mark_iterator it = *this; + ++(*this); + return it; + } + private: + acc_cond::mark_t m_; + }; + + class SPOT_API mark_container + { + public: + mark_container(spot::acc_cond::mark_t m) noexcept + : m_(m) + { + } + + mark_iterator begin() const + { + return {m_}; + } + mark_iterator end() const + { + return {}; + } + private: + spot::acc_cond::mark_t m_; + }; + } + + inline spot::internal::mark_container acc_cond::mark_t::sets() const + { + return {*this}; + } } namespace std diff --git a/tests/python/acc_cond.ipynb b/tests/python/acc_cond.ipynb index b18513672..c371ba95b 100644 --- a/tests/python/acc_cond.ipynb +++ b/tests/python/acc_cond.ipynb @@ -15,10 +15,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.3+" + "version": "3.5.3" }, - "name": "", - "signature": "sha256:9abaa081794db5d5479c8c9c179c8518aa52b60abdb4b7a106045646e277d43a" + "name": "" }, "nbformat": 3, "nbformat_minor": 0, @@ -338,7 +337,7 @@ "collapsed": false, "input": [ "print(x)\n", - "print(x.sets())\n", + "print(list(x.sets()))\n", "for s in x.sets():\n", " print(s)" ], @@ -350,7 +349,7 @@ "stream": "stdout", "text": [ "{0,2,5}\n", - "(0, 2, 5)\n", + "[0, 2, 5]\n", "0\n", "2\n", "5\n" @@ -1435,10 +1434,10 @@ "language": "python", "metadata": {}, "outputs": [], - "prompt_number": 52 + "prompt_number": null } ], "metadata": {} } ] -} \ No newline at end of file +}