From 2ff2e77739c0948ffc083ee7f88b6b1f8f1eac86 Mon Sep 17 00:00:00 2001 From: Daniel Schemmel Date: Mon, 21 May 2018 03:19:19 +0200 Subject: [PATCH 1/2] Move buffer.h to old_buffer.h and add a shim buffer.h --- src/util/buffer.h | 265 ++--------------------------------------- src/util/old_buffer.h | 268 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 275 insertions(+), 258 deletions(-) create mode 100644 src/util/old_buffer.h diff --git a/src/util/buffer.h b/src/util/buffer.h index c64e23d8b..7a89ffef3 100644 --- a/src/util/buffer.h +++ b/src/util/buffer.h @@ -1,268 +1,17 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - buffer.h - -Abstract: - - - -Author: - - Leonardo de Moura (leonardo) 2006-10-16. - -Revision History: - ---*/ #ifndef BUFFER_H_ #define BUFFER_H_ -#include -#include "util/memory_manager.h" +#include "old_buffer.h" template -class buffer { -protected: - T * m_buffer; - unsigned m_pos; - unsigned m_capacity; - char m_initial_buffer[INITIAL_SIZE * sizeof(T)]; - - void free_memory() { - if (m_buffer != reinterpret_cast(m_initial_buffer)) { - dealloc_svect(m_buffer); - } - } +using buffer = old_buffer; - void expand() { - unsigned new_capacity = m_capacity << 1; - T * new_buffer = reinterpret_cast(memory::allocate(sizeof(T) * new_capacity)); - memcpy(new_buffer, m_buffer, m_pos * sizeof(T)); - free_memory(); - m_buffer = new_buffer; - m_capacity = new_capacity; - } - - void destroy_elements() { - iterator it = begin(); - iterator e = end(); - for (; it != e; ++it) { - it->~T(); - } - } - - void destroy() { - if (CallDestructors) { - destroy_elements(); - } - free_memory(); - } - -public: - typedef T data; - typedef T * iterator; - typedef const T * const_iterator; - - buffer(): - m_buffer(reinterpret_cast(m_initial_buffer)), - m_pos(0), - m_capacity(INITIAL_SIZE) { - } - - buffer(const buffer & source): - m_buffer(reinterpret_cast(m_initial_buffer)), - m_pos(0), - m_capacity(INITIAL_SIZE) { - unsigned sz = source.size(); - for(unsigned i = 0; i < sz; i++) { - push_back(source.m_buffer[i]); - } - } - - buffer(unsigned sz, const T & elem): - m_buffer(reinterpret_cast(m_initial_buffer)), - m_pos(0), - m_capacity(INITIAL_SIZE) { - for (unsigned i = 0; i < sz; i++) { - push_back(elem); - } - SASSERT(size() == sz); - } - - ~buffer() { - destroy(); - } - - void reset() { - if (CallDestructors) { - destroy_elements(); - } - m_pos = 0; - } - - void finalize() { - destroy(); - m_buffer = reinterpret_cast(m_initial_buffer); - m_pos = 0; - m_capacity = INITIAL_SIZE; - } - - unsigned size() const { - return m_pos; - } - - bool empty() const { - return m_pos == 0; - } - - iterator begin() { - return m_buffer; - } - - iterator end() { - return m_buffer + size(); - } - - void set_end(iterator it) { - m_pos = static_cast(it - m_buffer); - if (CallDestructors) { - iterator e = end(); - for (; it != e; ++it) { - it->~T(); - } - } - } - - const_iterator begin() const { - return m_buffer; - } - - const_iterator end() const { - return m_buffer + size(); - } - - void push_back(const T & elem) { - if (m_pos >= m_capacity) - expand(); - new (m_buffer + m_pos) T(elem); - m_pos++; - } - - void push_back(T && elem) { - if (m_pos >= m_capacity) - expand(); - new (m_buffer + m_pos) T(std::move(elem)); - m_pos++; - } - - void pop_back() { - if (CallDestructors) { - back().~T(); - } - m_pos--; - } - - const T & back() const { - SASSERT(!empty()); - SASSERT(m_pos > 0); - return m_buffer[m_pos - 1]; - } - - T & back() { - SASSERT(!empty()); - SASSERT(m_pos > 0); - return m_buffer[m_pos - 1]; - } - - T * c_ptr() const { - return m_buffer; - } - - void append(unsigned n, T const * elems) { - for (unsigned i = 0; i < n; i++) { - push_back(elems[i]); - } - } - - void append(const buffer& source) { - append(source.size(), source.c_ptr()); - } - - T & operator[](unsigned idx) { - SASSERT(idx < size()); - return m_buffer[idx]; - } - - const T & operator[](unsigned idx) const { - SASSERT(idx < size()); - return m_buffer[idx]; - } - - T & get(unsigned idx) { - SASSERT(idx < size()); - return m_buffer[idx]; - } - - const T & get(unsigned idx) const { - SASSERT(idx < size()); - return m_buffer[idx]; - } - - void set(unsigned idx, T const & val) { - SASSERT(idx < size()); - m_buffer[idx] = val; - } - - void resize(unsigned nsz, const T & elem=T()) { - unsigned sz = size(); - if (nsz > sz) { - for (unsigned i = sz; i < nsz; i++) { - push_back(elem); - } - } - else if (nsz < sz) { - for (unsigned i = nsz; i < sz; i++) { - pop_back(); - } - } - SASSERT(size() == nsz); - } - - void shrink(unsigned nsz) { - unsigned sz = size(); - SASSERT(nsz <= sz); - for (unsigned i = nsz; i < sz; i++) - pop_back(); - SASSERT(size() == nsz); - } - - buffer & operator=(buffer const & other) { - if (this == &other) - return *this; - reset(); - append(other); - return *this; - } -}; +// note that the append added in the old_ptr_buffer is actually not an addition over its base class old_buffer, +// which already has an append function with the same signature and implementation +template +using ptr_buffer = old_ptr_buffer; template -class ptr_buffer : public buffer { -public: - void append(unsigned n, T * const * elems) { - for (unsigned i = 0; i < n; i++) { - this->push_back(elems[i]); - } - } -}; - -template -class sbuffer : public buffer { -public: - sbuffer(): buffer() {} - sbuffer(unsigned sz, const T& elem) : buffer(sz,elem) {} -}; +using sbuffer = old_sbuffer; #endif /* BUFFER_H_ */ - diff --git a/src/util/old_buffer.h b/src/util/old_buffer.h new file mode 100644 index 000000000..5ed1df583 --- /dev/null +++ b/src/util/old_buffer.h @@ -0,0 +1,268 @@ +/*++ +Copyright (c) 2006 Microsoft Corporation + +Module Name: + + old_buffer.h + +Abstract: + + + +Author: + + Leonardo de Moura (leonardo) 2006-10-16. + +Revision History: + +--*/ +#ifndef OLD_BUFFER_H_ +#define OLD_BUFFER_H_ + +#include +#include "util/memory_manager.h" + +template +class old_buffer { +protected: + T * m_buffer; + unsigned m_pos; + unsigned m_capacity; + char m_initial_buffer[INITIAL_SIZE * sizeof(T)]; + + void free_memory() { + if (m_buffer != reinterpret_cast(m_initial_buffer)) { + dealloc_svect(m_buffer); + } + } + + void expand() { + unsigned new_capacity = m_capacity << 1; + T * new_buffer = reinterpret_cast(memory::allocate(sizeof(T) * new_capacity)); + memcpy(new_buffer, m_buffer, m_pos * sizeof(T)); + free_memory(); + m_buffer = new_buffer; + m_capacity = new_capacity; + } + + void destroy_elements() { + iterator it = begin(); + iterator e = end(); + for (; it != e; ++it) { + it->~T(); + } + } + + void destroy() { + if (CallDestructors) { + destroy_elements(); + } + free_memory(); + } + +public: + typedef T data; + typedef T * iterator; + typedef const T * const_iterator; + + old_buffer(): + m_buffer(reinterpret_cast(m_initial_buffer)), + m_pos(0), + m_capacity(INITIAL_SIZE) { + } + + old_buffer(const old_buffer & source): + m_buffer(reinterpret_cast(m_initial_buffer)), + m_pos(0), + m_capacity(INITIAL_SIZE) { + unsigned sz = source.size(); + for(unsigned i = 0; i < sz; i++) { + push_back(source.m_buffer[i]); + } + } + + old_buffer(unsigned sz, const T & elem): + m_buffer(reinterpret_cast(m_initial_buffer)), + m_pos(0), + m_capacity(INITIAL_SIZE) { + for (unsigned i = 0; i < sz; i++) { + push_back(elem); + } + SASSERT(size() == sz); + } + + ~old_buffer() { + destroy(); + } + + void reset() { + if (CallDestructors) { + destroy_elements(); + } + m_pos = 0; + } + + void finalize() { + destroy(); + m_buffer = reinterpret_cast(m_initial_buffer); + m_pos = 0; + m_capacity = INITIAL_SIZE; + } + + unsigned size() const { + return m_pos; + } + + bool empty() const { + return m_pos == 0; + } + + iterator begin() { + return m_buffer; + } + + iterator end() { + return m_buffer + size(); + } + + void set_end(iterator it) { + m_pos = static_cast(it - m_buffer); + if (CallDestructors) { + iterator e = end(); + for (; it != e; ++it) { + it->~T(); + } + } + } + + const_iterator begin() const { + return m_buffer; + } + + const_iterator end() const { + return m_buffer + size(); + } + + void push_back(const T & elem) { + if (m_pos >= m_capacity) + expand(); + new (m_buffer + m_pos) T(elem); + m_pos++; + } + + void push_back(T && elem) { + if (m_pos >= m_capacity) + expand(); + new (m_buffer + m_pos) T(std::move(elem)); + m_pos++; + } + + void pop_back() { + if (CallDestructors) { + back().~T(); + } + m_pos--; + } + + const T & back() const { + SASSERT(!empty()); + SASSERT(m_pos > 0); + return m_buffer[m_pos - 1]; + } + + T & back() { + SASSERT(!empty()); + SASSERT(m_pos > 0); + return m_buffer[m_pos - 1]; + } + + T * c_ptr() const { + return m_buffer; + } + + void append(unsigned n, T const * elems) { + for (unsigned i = 0; i < n; i++) { + push_back(elems[i]); + } + } + + void append(const old_buffer& source) { + append(source.size(), source.c_ptr()); + } + + T & operator[](unsigned idx) { + SASSERT(idx < size()); + return m_buffer[idx]; + } + + const T & operator[](unsigned idx) const { + SASSERT(idx < size()); + return m_buffer[idx]; + } + + T & get(unsigned idx) { + SASSERT(idx < size()); + return m_buffer[idx]; + } + + const T & get(unsigned idx) const { + SASSERT(idx < size()); + return m_buffer[idx]; + } + + void set(unsigned idx, T const & val) { + SASSERT(idx < size()); + m_buffer[idx] = val; + } + + void resize(unsigned nsz, const T & elem=T()) { + unsigned sz = size(); + if (nsz > sz) { + for (unsigned i = sz; i < nsz; i++) { + push_back(elem); + } + } + else if (nsz < sz) { + for (unsigned i = nsz; i < sz; i++) { + pop_back(); + } + } + SASSERT(size() == nsz); + } + + void shrink(unsigned nsz) { + unsigned sz = size(); + SASSERT(nsz <= sz); + for (unsigned i = nsz; i < sz; i++) + pop_back(); + SASSERT(size() == nsz); + } + + old_buffer & operator=(old_buffer const & other) { + if (this == &other) + return *this; + reset(); + append(other); + return *this; + } +}; + +template +class old_ptr_buffer : public old_buffer { +public: + void append(unsigned n, T * const * elems) { + for (unsigned i = 0; i < n; i++) { + this->push_back(elems[i]); + } + } +}; + +template +class old_sbuffer : public old_buffer { +public: + old_sbuffer(): old_buffer() {} + old_sbuffer(unsigned sz, const T& elem) : old_buffer(sz,elem) {} +}; + +#endif /* OLD_BUFFER_H_ */ + From 721ea2a8d3eec8819e3f3b2c4b55ed5212c67dcb Mon Sep 17 00:00:00 2001 From: Daniel Schemmel Date: Sat, 26 May 2018 05:22:39 +0200 Subject: [PATCH 2/2] Move vector.h to old_vector.h and add a shim vector.h To do so, one instance of the class keyword needs to be removed. --- src/util/lp/dense_matrix.cpp | 2 +- src/util/old_vector.h | 609 ++++++++++++++++++++++++++++++++++ src/util/vector.h | 617 +---------------------------------- 3 files changed, 622 insertions(+), 606 deletions(-) create mode 100644 src/util/old_vector.h diff --git a/src/util/lp/dense_matrix.cpp b/src/util/lp/dense_matrix.cpp index 50f2598c8..4ababc47a 100644 --- a/src/util/lp/dense_matrix.cpp +++ b/src/util/lp/dense_matrix.cpp @@ -35,6 +35,6 @@ template lp::dense_matrix >::dense_matrix(uns template lp::dense_matrix >& lp::dense_matrix >::operator=(lp::dense_matrix > const&); template lp::dense_matrix > lp::operator* >(lp::matrix >&, lp::matrix >&); template void lp::dense_matrix >::apply_from_right( vector< lp::mpq> &); -template void lp::dense_matrix::apply_from_right(class vector &); +template void lp::dense_matrix::apply_from_right(vector &); template void lp::dense_matrix::apply_from_left(vector&); #endif diff --git a/src/util/old_vector.h b/src/util/old_vector.h new file mode 100644 index 000000000..53450e6cf --- /dev/null +++ b/src/util/old_vector.h @@ -0,0 +1,609 @@ +/*++ +Copyright (c) 2006 Microsoft Corporation + +Module Name: + + old_vector.h + +Abstract: + Dynamic array implementation. + Remarks: + + - Empty arrays consume only sizeof(T *) bytes. + + - There is the option of disabling the destructor invocation for elements stored in the vector. + This is useful for vectors of int. + +Author: + + Leonardo de Moura (leonardo) 2006-09-11. + +Revision History: + +--*/ +#ifndef OLD_VECTOR_H_ +#define OLD_VECTOR_H_ + +#include "util/debug.h" +#include +#include +#include +#include +#include "util/memory_manager.h" +#include "util/hash.h" +#include "util/z3_exception.h" + +// disable warning for constant 'if' expressions. +// these are used heavily in templates. +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + +template +class old_vector { +#define SIZE_IDX -1 +#define CAPACITY_IDX -2 + T * m_data; + + void destroy_elements() { + iterator it = begin(); + iterator e = end(); + for (; it != e; ++it) { + it->~T(); + } + } + + void free_memory() { + memory::deallocate(reinterpret_cast(reinterpret_cast(m_data) - 2)); + } + + void expand_vector() { + if (m_data == nullptr) { + SZ capacity = 2; + SZ * mem = reinterpret_cast(memory::allocate(sizeof(T) * capacity + sizeof(SZ) * 2)); + *mem = capacity; + mem++; + *mem = 0; + mem++; + m_data = reinterpret_cast(mem); + } + else { + SASSERT(capacity() > 0); + SZ old_capacity = reinterpret_cast(m_data)[CAPACITY_IDX]; + SZ old_capacity_T = sizeof(T) * old_capacity + sizeof(SZ) * 2; + SZ new_capacity = (3 * old_capacity + 1) >> 1; + SZ new_capacity_T = sizeof(T) * new_capacity + sizeof(SZ) * 2; + if (new_capacity <= old_capacity || new_capacity_T <= old_capacity_T) { + throw default_exception("Overflow encountered when expanding old_vector"); + } + SZ *mem, *old_mem = reinterpret_cast(m_data) - 2; +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 + if (__has_trivial_copy(T)) { +#else + if (std::is_trivially_copyable::value) { +#endif + mem = (SZ*)memory::reallocate(old_mem, new_capacity_T); + m_data = reinterpret_cast(mem + 2); + } else { + mem = (SZ*)memory::allocate(new_capacity_T); + auto old_data = m_data; + auto old_size = size(); + mem[1] = old_size; + m_data = reinterpret_cast(mem + 2); + for (unsigned i = 0; i < old_size; ++i) { + new (&m_data[i]) T(std::move(old_data[i])); + old_data[i].~T(); + } + memory::deallocate(old_mem); + } + *mem = new_capacity; + } + } + + void copy_core(old_vector const & source) { + SZ size = source.size(); + SZ capacity = source.capacity(); + SZ * mem = reinterpret_cast(memory::allocate(sizeof(T) * capacity + sizeof(SZ) * 2)); + *mem = capacity; + mem++; + *mem = size; + mem++; + m_data = reinterpret_cast(mem); + const_iterator it = source.begin(); + iterator it2 = begin(); + SASSERT(it2 == m_data); + const_iterator e = source.end(); + for (; it != e; ++it, ++it2) { + new (it2) T(*it); + } + } + + void destroy() { + if (m_data) { + if (CallDestructors) { + destroy_elements(); + } + free_memory(); + } + } + +public: + typedef T data; + typedef T * iterator; + typedef const T * const_iterator; + + old_vector(): + m_data(nullptr) { + } + + old_vector(SZ s) { + if (s == 0) { + m_data = nullptr; + return; + } + SZ * mem = reinterpret_cast(memory::allocate(sizeof(T) * s + sizeof(SZ) * 2)); + *mem = s; + mem++; + *mem = s; + mem++; + m_data = reinterpret_cast(mem); + // initialize elements + iterator it = begin(); + iterator e = end(); + for (; it != e; ++it) { + new (it) T(); + } + } + + old_vector(SZ s, T const & elem): + m_data(nullptr) { + resize(s, elem); + } + + old_vector(old_vector const & source): + m_data(nullptr) { + if (source.m_data) { + copy_core(source); + } + SASSERT(size() == source.size()); + } + + old_vector(old_vector&& other) : m_data(nullptr) { + std::swap(m_data, other.m_data); + } + + old_vector(SZ s, T const * data): + m_data(nullptr) { + for (SZ i = 0; i < s; i++) { + push_back(data[i]); + } + } + + + ~old_vector() { + destroy(); + } + + void finalize() { + destroy(); + m_data = nullptr; + } + + bool operator==(old_vector const & other) const { + if (this == &other) { + return true; + } + if (size() != other.size()) + return false; + for (unsigned i = 0; i < size(); i++) { + if ((*this)[i] != other[i]) + return false; + } + return true; + } + + bool operator!=(old_vector const & other) const { + return !(*this == other); + } + + + old_vector & operator=(old_vector const & source) { + if (this == &source) { + return *this; + } + destroy(); + if (source.m_data) { + copy_core(source); + } + else { + m_data = nullptr; + } + return *this; + } + + old_vector & operator=(old_vector && source) { + if (this == &source) { + return *this; + } + destroy(); + m_data = nullptr; + std::swap(m_data, source.m_data); + return *this; + } + + bool containsp(std::function& predicate) const { + for (auto const& t : *this) + if (predicate(t)) + return true; + return false; + } + + /** + * retain elements that satisfy predicate. aka 'where'. + */ + old_vector filter_pure(std::function& predicate) const { + old_vector result; + for (auto& t : *this) + if (predicate(t)) + result.push_back(t); + return result; + } + + old_vector& filter_update(std::function& predicate) { + unsigned j = 0; + for (auto& t : *this) + if (predicate(t)) + set(j++, t); + shrink(j); + return *this; + } + + /** + * update elements using f, aka 'select' + */ + template + old_vector map_pure(std::function& f) const { + old_vector result; + for (auto& t : *this) + result.push_back(f(t)); + return result; + } + + old_vector& map_update(std::function& f) { + unsigned j = 0; + for (auto& t : *this) + set(j++, f(t)); + return *this; + } + + void reset() { + if (m_data) { + if (CallDestructors) { + destroy_elements(); + } + reinterpret_cast(m_data)[SIZE_IDX] = 0; + } + } + + void clear() { reset(); } + + bool empty() const { + return m_data == nullptr || reinterpret_cast(m_data)[SIZE_IDX] == 0; + } + + SZ size() const { + if (m_data == nullptr) { + return 0; + } + return reinterpret_cast(m_data)[SIZE_IDX]; + } + + SZ capacity() const { + if (m_data == nullptr) { + return 0; + } + return reinterpret_cast(m_data)[CAPACITY_IDX]; + } + + iterator begin() { + return m_data; + } + + iterator end() { + return m_data + size(); + } + + const_iterator begin() const { + return m_data; + } + + const_iterator end() const { + return m_data + size(); + } + + class reverse_iterator { + T* v; + public: + reverse_iterator(T* v):v(v) {} + + T operator*() { return *v; } + reverse_iterator operator++(int) { + reverse_iterator tmp = *this; + --v; + return tmp; + } + reverse_iterator& operator++() { + --v; + return *this; + } + + bool operator==(reverse_iterator const& other) const { + return other.v == v; + } + bool operator!=(reverse_iterator const& other) const { + return other.v != v; + } + }; + + reverse_iterator rbegin() { return reverse_iterator(end() - 1); } + reverse_iterator rend() { return reverse_iterator(begin() - 1); } + + void set_end(iterator it) { + if (m_data) { + SZ new_sz = static_cast(it - m_data); + if (CallDestructors) { + iterator e = end(); + for(; it != e; ++it) { + it->~T(); + } + } + reinterpret_cast(m_data)[SIZE_IDX] = new_sz; + } + else { + SASSERT(it == 0); + } + } + + T & operator[](SZ idx) { + SASSERT(idx < size()); + return m_data[idx]; + } + + T const & operator[](SZ idx) const { + SASSERT(idx < size()); + return m_data[idx]; + } + + T & get(SZ idx) { + SASSERT(idx < size()); + return m_data[idx]; + } + + T const & get(SZ idx) const { + SASSERT(idx < size()); + return m_data[idx]; + } + + void set(SZ idx, T const & val) { + SASSERT(idx < size()); + m_data[idx] = val; + } + + void set(SZ idx, T && val) { + SASSERT(idx < size()); + m_data[idx] = std::move(val); + } + + T & back() { + SASSERT(!empty()); + return operator[](size() - 1); + } + + T const & back() const { + SASSERT(!empty()); + return operator[](size() - 1); + } + + void pop_back() { + SASSERT(!empty()); + if (CallDestructors) { + back().~T(); + } + reinterpret_cast(m_data)[SIZE_IDX]--; + } + + void push_back(T const & elem) { + if (m_data == nullptr || reinterpret_cast(m_data)[SIZE_IDX] == reinterpret_cast(m_data)[CAPACITY_IDX]) { + expand_vector(); + } + new (m_data + reinterpret_cast(m_data)[SIZE_IDX]) T(elem); + reinterpret_cast(m_data)[SIZE_IDX]++; + } + + void push_back(T && elem) { + if (m_data == nullptr || reinterpret_cast(m_data)[SIZE_IDX] == reinterpret_cast(m_data)[CAPACITY_IDX]) { + expand_vector(); + } + new (m_data + reinterpret_cast(m_data)[SIZE_IDX]) T(std::move(elem)); + reinterpret_cast(m_data)[SIZE_IDX]++; + } + + void insert(T const & elem) { + push_back(elem); + } + + void erase(iterator pos) { + SASSERT(pos >= begin() && pos < end()); + iterator prev = pos; + ++pos; + iterator e = end(); + for(; pos != e; ++pos, ++prev) { + *prev = *pos; + } + reinterpret_cast(m_data)[SIZE_IDX]--; + } + + void erase(T const & elem) { + iterator it = std::find(begin(), end(), elem); + if (it != end()) { + erase(it); + } + } + + void shrink(SZ s) { + if (m_data) { + SASSERT(s <= reinterpret_cast(m_data)[SIZE_IDX]); + if (CallDestructors) { + iterator it = m_data + s; + iterator e = end(); + for(; it != e; ++it) { + it->~T(); + } + } + reinterpret_cast(m_data)[SIZE_IDX] = s; + } + else { + SASSERT(s == 0); + } + } + + template + void resize(SZ s, Args args...) { + SZ sz = size(); + if (s <= sz) { shrink(s); return; } + while (s > capacity()) { + expand_vector(); + } + SASSERT(m_data != 0); + reinterpret_cast(m_data)[SIZE_IDX] = s; + iterator it = m_data + sz; + iterator end = m_data + s; + for (; it != end; ++it) { + new (it) T(std::forward(args)); + } + } + + void resize(SZ s) { + SZ sz = size(); + if (s <= sz) { shrink(s); return; } + while (s > capacity()) { + expand_vector(); + } + SASSERT(m_data != 0); + reinterpret_cast(m_data)[SIZE_IDX] = s; + iterator it = m_data + sz; + iterator end = m_data + s; + for (; it != end; ++it) { + new (it) T(); + } + } + + void append(old_vector const & other) { + for(SZ i = 0; i < other.size(); ++i) { + push_back(other[i]); + } + } + + void append(SZ sz, T const * data) { + for(SZ i = 0; i < sz; ++i) { + push_back(data[i]); + } + } + + T * c_ptr() const { + return m_data; + } + + void swap(old_vector & other) { + std::swap(m_data, other.m_data); + } + + void reverse() { + SZ sz = size(); + for (SZ i = 0; i < sz/2; ++i) { + std::swap(m_data[i], m_data[sz-i-1]); + } + } + + void fill(T const & elem) { + iterator i = begin(); + iterator e = end(); + for (; i != e; ++i) { + *i = elem; + } + } + + void fill(unsigned sz, T const & elem) { + resize(sz); + fill(elem); + } + + bool contains(T const & elem) const { + const_iterator it = begin(); + const_iterator e = end(); + for (; it != e; ++it) { + if (*it == elem) { + return true; + } + } + return false; + } + + // set pos idx with elem. If idx >= size, then expand using default. + void setx(SZ idx, T const & elem, T const & d) { + if (idx >= size()) { + resize(idx+1, d); + } + m_data[idx] = elem; + } + + // return element at position idx, if idx >= size, then return default + T const & get(SZ idx, T const & d) const { + if (idx >= size()) { + return d; + } + return m_data[idx]; + } + + void reserve(SZ s, T const & d) { + if (s > size()) + resize(s, d); + } + + void reserve(SZ s) { + if (s > size()) + resize(s); + } +}; + +template +class old_ptr_vector : public old_vector { +public: + old_ptr_vector():old_vector() {} + old_ptr_vector(unsigned s):old_vector(s) {} + old_ptr_vector(unsigned s, T * elem):old_vector(s, elem) {} + old_ptr_vector(old_ptr_vector const & source):old_vector(source) {} + old_ptr_vector(old_ptr_vector && other) : old_vector(std::move(other)) {} + old_ptr_vector(unsigned s, T * const * data):old_vector(s, const_cast(data)) {} + old_ptr_vector & operator=(old_ptr_vector const & source) { + old_vector::operator=(source); + return *this; + } +}; + +template +class old_svector : public old_vector { +public: + old_svector():old_vector() {} + old_svector(SZ s):old_vector(s) {} + old_svector(SZ s, T const & elem):old_vector(s, elem) {} + old_svector(old_svector const & source):old_vector(source) {} + old_svector(old_svector && other) : old_vector(std::move(other)) {} + old_svector(SZ s, T const * data):old_vector(s, data) {} + old_svector & operator=(old_svector const & source) { + old_vector::operator=(source); + return *this; + } +}; + +#endif /* OLD_VECTOR_H_ */ diff --git a/src/util/vector.h b/src/util/vector.h index acbcd1357..b3625bdfc 100644 --- a/src/util/vector.h +++ b/src/util/vector.h @@ -1,616 +1,23 @@ -/*++ -Copyright (c) 2006 Microsoft Corporation - -Module Name: - - vector.h - -Abstract: - Dynamic array implementation. - Remarks: - - - Empty arrays consume only sizeof(T *) bytes. - - - There is the option of disabling the destructor invocation for elements stored in the vector. - This is useful for vectors of int. - -Author: - - Leonardo de Moura (leonardo) 2006-09-11. - -Revision History: - ---*/ #ifndef VECTOR_H_ #define VECTOR_H_ -#include "util/debug.h" -#include -#include -#include -#include -#include "util/memory_manager.h" -#include "util/hash.h" -#include "util/z3_exception.h" - -// disable warning for constant 'if' expressions. -// these are used heavily in templates. -#ifdef _MSC_VER -#pragma warning(disable:4127) -#endif +#include "old_vector.h" +#include "hash.h" template -class vector { -#define SIZE_IDX -1 -#define CAPACITY_IDX -2 - T * m_data; - - void destroy_elements() { - iterator it = begin(); - iterator e = end(); - for (; it != e; ++it) { - it->~T(); - } - } - - void free_memory() { - memory::deallocate(reinterpret_cast(reinterpret_cast(m_data) - 2)); - } - - void expand_vector() { - if (m_data == nullptr) { - SZ capacity = 2; - SZ * mem = reinterpret_cast(memory::allocate(sizeof(T) * capacity + sizeof(SZ) * 2)); - *mem = capacity; - mem++; - *mem = 0; - mem++; - m_data = reinterpret_cast(mem); - } - else { - SASSERT(capacity() > 0); - SZ old_capacity = reinterpret_cast(m_data)[CAPACITY_IDX]; - SZ old_capacity_T = sizeof(T) * old_capacity + sizeof(SZ) * 2; - SZ new_capacity = (3 * old_capacity + 1) >> 1; - SZ new_capacity_T = sizeof(T) * new_capacity + sizeof(SZ) * 2; - if (new_capacity <= old_capacity || new_capacity_T <= old_capacity_T) { - throw default_exception("Overflow encountered when expanding vector"); - } - SZ *mem, *old_mem = reinterpret_cast(m_data) - 2; -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5 - if (__has_trivial_copy(T)) { -#else - if (std::is_trivially_copyable::value) { -#endif - mem = (SZ*)memory::reallocate(old_mem, new_capacity_T); - m_data = reinterpret_cast(mem + 2); - } else { - mem = (SZ*)memory::allocate(new_capacity_T); - auto old_data = m_data; - auto old_size = size(); - mem[1] = old_size; - m_data = reinterpret_cast(mem + 2); - for (unsigned i = 0; i < old_size; ++i) { - new (&m_data[i]) T(std::move(old_data[i])); - old_data[i].~T(); - } - memory::deallocate(old_mem); - } - *mem = new_capacity; - } - } - - void copy_core(vector const & source) { - SZ size = source.size(); - SZ capacity = source.capacity(); - SZ * mem = reinterpret_cast(memory::allocate(sizeof(T) * capacity + sizeof(SZ) * 2)); - *mem = capacity; - mem++; - *mem = size; - mem++; - m_data = reinterpret_cast(mem); - const_iterator it = source.begin(); - iterator it2 = begin(); - SASSERT(it2 == m_data); - const_iterator e = source.end(); - for (; it != e; ++it, ++it2) { - new (it2) T(*it); - } - } - - void destroy() { - if (m_data) { - if (CallDestructors) { - destroy_elements(); - } - free_memory(); - } - } - -public: - typedef T data; - typedef T * iterator; - typedef const T * const_iterator; - - vector(): - m_data(nullptr) { - } - - vector(SZ s) { - if (s == 0) { - m_data = nullptr; - return; - } - SZ * mem = reinterpret_cast(memory::allocate(sizeof(T) * s + sizeof(SZ) * 2)); - *mem = s; - mem++; - *mem = s; - mem++; - m_data = reinterpret_cast(mem); - // initialize elements - iterator it = begin(); - iterator e = end(); - for (; it != e; ++it) { - new (it) T(); - } - } - - vector(SZ s, T const & elem): - m_data(nullptr) { - resize(s, elem); - } - - vector(vector const & source): - m_data(nullptr) { - if (source.m_data) { - copy_core(source); - } - SASSERT(size() == source.size()); - } - - vector(vector&& other) : m_data(nullptr) { - std::swap(m_data, other.m_data); - } - - vector(SZ s, T const * data): - m_data(nullptr) { - for (SZ i = 0; i < s; i++) { - push_back(data[i]); - } - } - - - ~vector() { - destroy(); - } - - void finalize() { - destroy(); - m_data = nullptr; - } - - bool operator==(vector const & other) const { - if (this == &other) { - return true; - } - if (size() != other.size()) - return false; - for (unsigned i = 0; i < size(); i++) { - if ((*this)[i] != other[i]) - return false; - } - return true; - } - - bool operator!=(vector const & other) const { - return !(*this == other); - } - - - vector & operator=(vector const & source) { - if (this == &source) { - return *this; - } - destroy(); - if (source.m_data) { - copy_core(source); - } - else { - m_data = nullptr; - } - return *this; - } - - vector & operator=(vector && source) { - if (this == &source) { - return *this; - } - destroy(); - m_data = nullptr; - std::swap(m_data, source.m_data); - return *this; - } - - bool containsp(std::function& predicate) const { - for (auto const& t : *this) - if (predicate(t)) - return true; - return false; - } - - /** - * retain elements that satisfy predicate. aka 'where'. - */ - vector filter_pure(std::function& predicate) const { - vector result; - for (auto& t : *this) - if (predicate(t)) - result.push_back(t); - return result; - } - - vector& filter_update(std::function& predicate) { - unsigned j = 0; - for (auto& t : *this) - if (predicate(t)) - set(j++, t); - shrink(j); - return *this; - } - - /** - * update elements using f, aka 'select' - */ - template - vector map_pure(std::function& f) const { - vector result; - for (auto& t : *this) - result.push_back(f(t)); - return result; - } - - vector& map_update(std::function& f) { - unsigned j = 0; - for (auto& t : *this) - set(j++, f(t)); - return *this; - } - - void reset() { - if (m_data) { - if (CallDestructors) { - destroy_elements(); - } - reinterpret_cast(m_data)[SIZE_IDX] = 0; - } - } - - void clear() { reset(); } - - bool empty() const { - return m_data == nullptr || reinterpret_cast(m_data)[SIZE_IDX] == 0; - } - - SZ size() const { - if (m_data == nullptr) { - return 0; - } - return reinterpret_cast(m_data)[SIZE_IDX]; - } - - SZ capacity() const { - if (m_data == nullptr) { - return 0; - } - return reinterpret_cast(m_data)[CAPACITY_IDX]; - } - - iterator begin() { - return m_data; - } - - iterator end() { - return m_data + size(); - } - - const_iterator begin() const { - return m_data; - } - - const_iterator end() const { - return m_data + size(); - } - - class reverse_iterator { - T* v; - public: - reverse_iterator(T* v):v(v) {} - - T operator*() { return *v; } - reverse_iterator operator++(int) { - reverse_iterator tmp = *this; - --v; - return tmp; - } - reverse_iterator& operator++() { - --v; - return *this; - } - - bool operator==(reverse_iterator const& other) const { - return other.v == v; - } - bool operator!=(reverse_iterator const& other) const { - return other.v != v; - } - }; - - reverse_iterator rbegin() { return reverse_iterator(end() - 1); } - reverse_iterator rend() { return reverse_iterator(begin() - 1); } - - void set_end(iterator it) { - if (m_data) { - SZ new_sz = static_cast(it - m_data); - if (CallDestructors) { - iterator e = end(); - for(; it != e; ++it) { - it->~T(); - } - } - reinterpret_cast(m_data)[SIZE_IDX] = new_sz; - } - else { - SASSERT(it == 0); - } - } - - T & operator[](SZ idx) { - SASSERT(idx < size()); - return m_data[idx]; - } - - T const & operator[](SZ idx) const { - SASSERT(idx < size()); - return m_data[idx]; - } - - T & get(SZ idx) { - SASSERT(idx < size()); - return m_data[idx]; - } - - T const & get(SZ idx) const { - SASSERT(idx < size()); - return m_data[idx]; - } - - void set(SZ idx, T const & val) { - SASSERT(idx < size()); - m_data[idx] = val; - } - - void set(SZ idx, T && val) { - SASSERT(idx < size()); - m_data[idx] = std::move(val); - } - - T & back() { - SASSERT(!empty()); - return operator[](size() - 1); - } - - T const & back() const { - SASSERT(!empty()); - return operator[](size() - 1); - } - - void pop_back() { - SASSERT(!empty()); - if (CallDestructors) { - back().~T(); - } - reinterpret_cast(m_data)[SIZE_IDX]--; - } - - void push_back(T const & elem) { - if (m_data == nullptr || reinterpret_cast(m_data)[SIZE_IDX] == reinterpret_cast(m_data)[CAPACITY_IDX]) { - expand_vector(); - } - new (m_data + reinterpret_cast(m_data)[SIZE_IDX]) T(elem); - reinterpret_cast(m_data)[SIZE_IDX]++; - } - - void push_back(T && elem) { - if (m_data == nullptr || reinterpret_cast(m_data)[SIZE_IDX] == reinterpret_cast(m_data)[CAPACITY_IDX]) { - expand_vector(); - } - new (m_data + reinterpret_cast(m_data)[SIZE_IDX]) T(std::move(elem)); - reinterpret_cast(m_data)[SIZE_IDX]++; - } - - void insert(T const & elem) { - push_back(elem); - } - - void erase(iterator pos) { - SASSERT(pos >= begin() && pos < end()); - iterator prev = pos; - ++pos; - iterator e = end(); - for(; pos != e; ++pos, ++prev) { - *prev = *pos; - } - reinterpret_cast(m_data)[SIZE_IDX]--; - } - - void erase(T const & elem) { - iterator it = std::find(begin(), end(), elem); - if (it != end()) { - erase(it); - } - } - - void shrink(SZ s) { - if (m_data) { - SASSERT(s <= reinterpret_cast(m_data)[SIZE_IDX]); - if (CallDestructors) { - iterator it = m_data + s; - iterator e = end(); - for(; it != e; ++it) { - it->~T(); - } - } - reinterpret_cast(m_data)[SIZE_IDX] = s; - } - else { - SASSERT(s == 0); - } - } - - template - void resize(SZ s, Args args...) { - SZ sz = size(); - if (s <= sz) { shrink(s); return; } - while (s > capacity()) { - expand_vector(); - } - SASSERT(m_data != 0); - reinterpret_cast(m_data)[SIZE_IDX] = s; - iterator it = m_data + sz; - iterator end = m_data + s; - for (; it != end; ++it) { - new (it) T(std::forward(args)); - } - } - - void resize(SZ s) { - SZ sz = size(); - if (s <= sz) { shrink(s); return; } - while (s > capacity()) { - expand_vector(); - } - SASSERT(m_data != 0); - reinterpret_cast(m_data)[SIZE_IDX] = s; - iterator it = m_data + sz; - iterator end = m_data + s; - for (; it != end; ++it) { - new (it) T(); - } - } - - void append(vector const & other) { - for(SZ i = 0; i < other.size(); ++i) { - push_back(other[i]); - } - } - - void append(SZ sz, T const * data) { - for(SZ i = 0; i < sz; ++i) { - push_back(data[i]); - } - } - - T * c_ptr() const { - return m_data; - } - - void swap(vector & other) { - std::swap(m_data, other.m_data); - } - - void reverse() { - SZ sz = size(); - for (SZ i = 0; i < sz/2; ++i) { - std::swap(m_data[i], m_data[sz-i-1]); - } - } - - void fill(T const & elem) { - iterator i = begin(); - iterator e = end(); - for (; i != e; ++i) { - *i = elem; - } - } - - void fill(unsigned sz, T const & elem) { - resize(sz); - fill(elem); - } - - bool contains(T const & elem) const { - const_iterator it = begin(); - const_iterator e = end(); - for (; it != e; ++it) { - if (*it == elem) { - return true; - } - } - return false; - } - - // set pos idx with elem. If idx >= size, then expand using default. - void setx(SZ idx, T const & elem, T const & d) { - if (idx >= size()) { - resize(idx+1, d); - } - m_data[idx] = elem; - } - - // return element at position idx, if idx >= size, then return default - T const & get(SZ idx, T const & d) const { - if (idx >= size()) { - return d; - } - return m_data[idx]; - } - - void reserve(SZ s, T const & d) { - if (s > size()) - resize(s, d); - } - - void reserve(SZ s) { - if (s > size()) - resize(s); - } -}; - -template -class ptr_vector : public vector { -public: - ptr_vector():vector() {} - ptr_vector(unsigned s):vector(s) {} - ptr_vector(unsigned s, T * elem):vector(s, elem) {} - ptr_vector(ptr_vector const & source):vector(source) {} - ptr_vector(ptr_vector && other) : vector(std::move(other)) {} - ptr_vector(unsigned s, T * const * data):vector(s, const_cast(data)) {} - ptr_vector & operator=(ptr_vector const & source) { - vector::operator=(source); - return *this; - } -}; +using vector = old_vector; template -class svector : public vector { -public: - svector():vector() {} - svector(SZ s):vector(s) {} - svector(SZ s, T const & elem):vector(s, elem) {} - svector(svector const & source):vector(source) {} - svector(svector && other) : vector(std::move(other)) {} - svector(SZ s, T const * data):vector(s, data) {} - svector & operator=(svector const & source) { - vector::operator=(source); - return *this; - } -}; +using svector = old_svector; -typedef svector int_vector; -typedef svector unsigned_vector; -typedef svector char_vector; -typedef svector signed_char_vector; -typedef svector double_vector; +template +using ptr_vector = old_ptr_vector; + +using int_vector = old_svector; +using unsigned_vector = old_svector; +using char_vector = old_svector; +using signed_char_vector = old_svector; +using double_vector = old_svector; inline std::ostream& operator<<(std::ostream& out, unsigned_vector const& v) { for (unsigned u : v) out << u << " ";