mirror of
https://github.com/Z3Prover/z3
synced 2025-08-23 03:27:52 +00:00
Shared features from polysat branch (#6567)
* Allow setting default debug action * Fix dlist and add iterator * Add var_queue iterator * Add some helpers * rational: machine_div2k and pseudo_inverse * Basic support for non-copyable types in map * tbv helpers * pdd updates * Remove duplicate functions gcc doesn't like having both versions
This commit is contained in:
parent
be44ace995
commit
d69155b9e9
13 changed files with 456 additions and 62 deletions
147
src/util/dlist.h
147
src/util/dlist.h
|
@ -17,20 +17,38 @@ Revision History:
|
|||
|
||||
--*/
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
#include "util/debug.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#define DLIST_EXTRA_ASSERTIONS 0
|
||||
|
||||
template<typename T>
|
||||
template <typename T> class dll_iterator;
|
||||
|
||||
template <typename T>
|
||||
class dll_base {
|
||||
T* m_next { nullptr };
|
||||
T* m_prev { nullptr };
|
||||
T* m_next = nullptr;
|
||||
T* m_prev = nullptr;
|
||||
|
||||
protected:
|
||||
dll_base() = default;
|
||||
~dll_base() = default;
|
||||
|
||||
public:
|
||||
dll_base(dll_base const&) = delete;
|
||||
dll_base(dll_base&&) = delete;
|
||||
dll_base& operator=(dll_base const&) = delete;
|
||||
dll_base& operator=(dll_base&&) = delete;
|
||||
|
||||
T* prev() { return m_prev; }
|
||||
T* next() { return m_next; }
|
||||
T const* prev() const { return m_prev; }
|
||||
T const* next() const { return m_next; }
|
||||
|
||||
void init(T* t) {
|
||||
m_next = t;
|
||||
m_prev = t;
|
||||
SASSERT(invariant());
|
||||
}
|
||||
|
||||
static T* pop(T*& list) {
|
||||
|
@ -41,23 +59,63 @@ public:
|
|||
return head;
|
||||
}
|
||||
|
||||
void insert_after(T* elem) {
|
||||
void insert_after(T* other) {
|
||||
#if DLIST_EXTRA_ASSERTIONS
|
||||
SASSERT(other);
|
||||
SASSERT(invariant());
|
||||
SASSERT(other->invariant());
|
||||
size_t const old_sz1 = count_if(*static_cast<T*>(this), [](T const&) { return true; });
|
||||
size_t const old_sz2 = count_if(*other, [](T const&) { return true; });
|
||||
#endif
|
||||
// have: this -> next -> ...
|
||||
// insert: other -> ... -> other_end
|
||||
// result: this -> other -> ... -> other_end -> next -> ...
|
||||
T* next = this->m_next;
|
||||
elem->m_prev = next->m_prev;
|
||||
elem->m_next = next;
|
||||
this->m_next = elem;
|
||||
next->m_prev = elem;
|
||||
T* other_end = other->m_prev;
|
||||
this->m_next = other;
|
||||
other->m_prev = static_cast<T*>(this);
|
||||
other_end->m_next = next;
|
||||
next->m_prev = other_end;
|
||||
#if DLIST_EXTRA_ASSERTIONS
|
||||
SASSERT(invariant());
|
||||
SASSERT(other->invariant());
|
||||
size_t const new_sz = count_if(*static_cast<T*>(this), [](T const&) { return true; });
|
||||
SASSERT_EQ(new_sz, old_sz1 + old_sz2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void insert_before(T* elem) {
|
||||
void insert_before(T* other) {
|
||||
#if DLIST_EXTRA_ASSERTIONS
|
||||
SASSERT(other);
|
||||
SASSERT(invariant());
|
||||
SASSERT(other->invariant());
|
||||
size_t const old_sz1 = count_if(*static_cast<T*>(this), [](T const&) { return true; });
|
||||
size_t const old_sz2 = count_if(*other, [](T const&) { return true; });
|
||||
#endif
|
||||
// have: prev -> this -> ...
|
||||
// insert: other -> ... -> other_end
|
||||
// result: prev -> other -> ... -> other_end -> this -> ...
|
||||
T* prev = this->m_prev;
|
||||
elem->m_next = prev->m_next;
|
||||
elem->m_prev = prev;
|
||||
prev->m_next = elem;
|
||||
this->m_prev = elem;
|
||||
T* other_end = other->m_prev;
|
||||
prev->m_next = other;
|
||||
other->m_prev = prev;
|
||||
other_end->m_next = static_cast<T*>(this);
|
||||
this->m_prev = other_end;
|
||||
#if DLIST_EXTRA_ASSERTIONS
|
||||
SASSERT(invariant());
|
||||
SASSERT(other->invariant());
|
||||
size_t const new_sz = count_if(*static_cast<T*>(this), [](T const&) { return true; });
|
||||
SASSERT_EQ(new_sz, old_sz1 + old_sz2);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void remove_from(T*& list, T* elem) {
|
||||
#if DLIST_EXTRA_ASSERTIONS
|
||||
SASSERT(list);
|
||||
SASSERT(elem);
|
||||
SASSERT(list->invariant());
|
||||
SASSERT(elem->invariant());
|
||||
#endif
|
||||
if (list->m_next == list) {
|
||||
SASSERT(elem == list);
|
||||
list = nullptr;
|
||||
|
@ -69,6 +127,9 @@ public:
|
|||
auto* prev = elem->m_prev;
|
||||
prev->m_next = next;
|
||||
next->m_prev = prev;
|
||||
#if DLIST_EXTRA_ASSERTIONS
|
||||
SASSERT(list->invariant());
|
||||
#endif
|
||||
}
|
||||
|
||||
static void push_to_front(T*& list, T* elem) {
|
||||
|
@ -105,11 +166,10 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool contains(T* list, T* elem) {
|
||||
static bool contains(T const* list, T const* elem) {
|
||||
if (!list)
|
||||
return false;
|
||||
T* first = list;
|
||||
T const* first = list;
|
||||
do {
|
||||
if (list == elem)
|
||||
return true;
|
||||
|
@ -120,5 +180,60 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class dll_iterator {
|
||||
T const* m_elem;
|
||||
bool m_first;
|
||||
|
||||
dll_iterator(T const* elem, bool first): m_elem(elem), m_first(first) { }
|
||||
|
||||
public:
|
||||
static dll_iterator mk_begin(T const* elem) {
|
||||
// Setting first==(bool)elem makes this also work for elem==nullptr;
|
||||
// but we can't implement top-level begin/end for pointers because it clashes with the definition for arrays.
|
||||
return {elem, (bool)elem};
|
||||
}
|
||||
|
||||
static dll_iterator mk_end(T const* elem) {
|
||||
return {elem, false};
|
||||
}
|
||||
|
||||
using value_type = T;
|
||||
using pointer = T const*;
|
||||
using reference = T const&;
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
dll_iterator& operator++() {
|
||||
m_elem = m_elem->next();
|
||||
m_first = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T const& operator*() const {
|
||||
return *m_elem;
|
||||
}
|
||||
|
||||
bool operator==(dll_iterator const& other) const {
|
||||
return m_elem == other.m_elem && m_first == other.m_first;
|
||||
}
|
||||
|
||||
bool operator!=(dll_iterator const& other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
|
||||
template < typename T
|
||||
, typename U = std::enable_if_t<std::is_base_of_v<dll_base<T>, T>> // should only match if T actually inherits from dll_base<T>
|
||||
>
|
||||
dll_iterator<T> begin(T const& elem) {
|
||||
return dll_iterator<T>::mk_begin(&elem);
|
||||
}
|
||||
|
||||
template < typename T
|
||||
, typename U = std::enable_if_t<std::is_base_of_v<dll_base<T>, T>> // should only match if T actually inherits from dll_base<T>
|
||||
>
|
||||
dll_iterator<T> end(T const& elem)
|
||||
{
|
||||
return dll_iterator<T>::mk_end(&elem);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue