mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
added facility to persist model transformations
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
fd49a0c89c
195 changed files with 3601 additions and 2139 deletions
|
@ -28,6 +28,7 @@ z3_add_component(util
|
|||
lbool.cpp
|
||||
luby.cpp
|
||||
memory_manager.cpp
|
||||
min_cut.cpp
|
||||
mpbq.cpp
|
||||
mpf.cpp
|
||||
mpff.cpp
|
||||
|
|
|
@ -149,6 +149,13 @@ public:
|
|||
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) {
|
||||
|
|
122
src/util/container_util.h
Normal file
122
src/util/container_util.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
container_util.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Useful functions for containers
|
||||
|
||||
Author:
|
||||
|
||||
Krystof Hoder, Nikolaj Bjorner 2017-10-24
|
||||
|
||||
Revision History:
|
||||
|
||||
Extracted from dl_util.h
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef CONTAINER_UTIL_H_
|
||||
#define CONTAINER_UTIL_H_
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// container functions
|
||||
//
|
||||
// -----------------------------------
|
||||
|
||||
template<class Set1, class Set2>
|
||||
void set_intersection(Set1 & tgt, const Set2 & src) {
|
||||
svector<typename Set1::data> to_remove;
|
||||
for (auto const& itm : tgt)
|
||||
if (!src.contains(itm))
|
||||
to_remove.push_back(itm);
|
||||
while (!to_remove.empty()) {
|
||||
tgt.remove(to_remove.back());
|
||||
to_remove.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
template<class Set>
|
||||
void set_difference(Set & tgt, const Set & to_remove) {
|
||||
for (auto const& itm : to_remove)
|
||||
tgt.remove(itm);
|
||||
}
|
||||
|
||||
template<class Set1, class Set2>
|
||||
void set_union(Set1 & tgt, const Set2 & to_add) {
|
||||
for (auto const& itm : to_add)
|
||||
tgt.insert(itm);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void unite_disjoint_maps(T & tgt, const T & src) {
|
||||
for (auto const& kv : src) {
|
||||
SASSERT(!tgt.contains(kv.m_key));
|
||||
tgt.insert(kv.m_key, kv.m_value);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
void collect_map_range(T & acc, const U & map) {
|
||||
for (auto const& kv : map)
|
||||
acc.push_back(kv.m_value);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void print_container(const T & begin, const T & end, std::ostream & out) {
|
||||
T it = begin;
|
||||
out << "(";
|
||||
bool first = true;
|
||||
for(; it!=end; ++it) {
|
||||
if(first) { first = false; } else { out << ","; }
|
||||
out << (*it);
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void print_container(const T & cont, std::ostream & out) {
|
||||
print_container(cont.begin(), cont.end(), out);
|
||||
}
|
||||
|
||||
template<class T, class M>
|
||||
void print_container(const ref_vector<T,M> & cont, std::ostream & out) {
|
||||
print_container(cont.c_ptr(), cont.c_ptr() + cont.size(), out);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void print_map(const T & cont, std::ostream & out) {
|
||||
out << "(";
|
||||
bool first = true;
|
||||
for (auto const& kv : cont) {
|
||||
if (first) { first = false; } else { out << ","; }
|
||||
out << kv.m_key << "->" << kv.m_value;
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
|
||||
template<class It, class V>
|
||||
unsigned find_index(const It & begin, const It & end, const V & val) {
|
||||
It it = begin;
|
||||
for (unsigned idx = 0; it != end; it++, idx++) {
|
||||
if (*it == val) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
bool containers_equal(const T & begin1, const T & end1, const U & begin2, const U & end2) {
|
||||
T it1 = begin1;
|
||||
U it2 = begin2;
|
||||
for (; it1 != end1 && it2 != end2 && *it1 == *it2; ++it1, ++it2) {};
|
||||
return it1 == end1 && it2 == end2;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -46,6 +46,9 @@ public:
|
|||
m_manager.set(m_one, ebits, sbits, 1);
|
||||
}
|
||||
|
||||
f2n(f2n && other) : m_manager(other.m_manager), m_mode(other.m_mode), m_ebits(other.m_ebits), m_sbits(other.m_sbits),
|
||||
m_tmp1(std::move(other.m_tmp1)), m_one(std::move(other.m_one)) {}
|
||||
|
||||
~f2n() {
|
||||
m().del(m_tmp1);
|
||||
m().del(m_one);
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
bool is_used() const { return m_state == HT_USED; }
|
||||
T & get_data() { return m_data; }
|
||||
const T & get_data() const { return m_data; }
|
||||
void set_data(const T & d) { m_data = d; m_state = HT_USED; }
|
||||
void set_data(T && d) { m_data = std::move(d); m_state = HT_USED; }
|
||||
void set_hash(unsigned h) { m_hash = h; }
|
||||
void mark_as_deleted() { m_state = HT_DELETED; }
|
||||
void mark_as_free() { m_state = HT_FREE; }
|
||||
|
@ -187,10 +187,42 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
static void move_table(entry * source, unsigned source_capacity, entry * target, unsigned target_capacity) {
|
||||
SASSERT(target_capacity >= source_capacity);
|
||||
unsigned target_mask = target_capacity - 1;
|
||||
entry * source_end = source + source_capacity;
|
||||
entry * target_end = target + target_capacity;
|
||||
for (entry * source_curr = source; source_curr != source_end; ++source_curr) {
|
||||
if (source_curr->is_used()) {
|
||||
unsigned hash = source_curr->get_hash();
|
||||
unsigned idx = hash & target_mask;
|
||||
entry * target_begin = target + idx;
|
||||
entry * target_curr = target_begin;
|
||||
for (; target_curr != target_end; ++target_curr) {
|
||||
SASSERT(!target_curr->is_deleted());
|
||||
if (target_curr->is_free()) {
|
||||
*target_curr = std::move(*source_curr);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
for (target_curr = target; target_curr != target_begin; ++target_curr) {
|
||||
SASSERT(!target_curr->is_deleted());
|
||||
if (target_curr->is_free()) {
|
||||
*target_curr = std::move(*source_curr);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
end:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void expand_table() {
|
||||
unsigned new_capacity = m_capacity << 1;
|
||||
entry * new_table = alloc_table(new_capacity);
|
||||
copy_table(m_table, m_capacity, new_table, new_capacity);
|
||||
move_table(m_table, m_capacity, new_table, new_capacity);
|
||||
delete_table();
|
||||
m_table = new_table;
|
||||
m_capacity = new_capacity;
|
||||
|
@ -202,7 +234,7 @@ protected:
|
|||
if (memory::is_out_of_memory())
|
||||
return;
|
||||
entry * new_table = alloc_table(m_capacity);
|
||||
copy_table(m_table, m_capacity, new_table, m_capacity);
|
||||
move_table(m_table, m_capacity, new_table, m_capacity);
|
||||
delete_table();
|
||||
m_table = new_table;
|
||||
m_num_deleted = 0;
|
||||
|
@ -321,7 +353,7 @@ public:
|
|||
#define INSERT_LOOP_BODY() { \
|
||||
if (curr->is_used()) { \
|
||||
if (curr->get_hash() == hash && equals(curr->get_data(), e)) { \
|
||||
curr->set_data(e); \
|
||||
curr->set_data(std::move(e)); \
|
||||
return; \
|
||||
} \
|
||||
HS_CODE(m_st_collision++;); \
|
||||
|
@ -330,7 +362,7 @@ public:
|
|||
entry * new_entry; \
|
||||
if (del_entry) { new_entry = del_entry; m_num_deleted--; } \
|
||||
else { new_entry = curr; } \
|
||||
new_entry->set_data(e); \
|
||||
new_entry->set_data(std::move(e)); \
|
||||
new_entry->set_hash(hash); \
|
||||
m_size++; \
|
||||
return; \
|
||||
|
@ -342,7 +374,7 @@ public:
|
|||
} \
|
||||
} ((void) 0)
|
||||
|
||||
void insert(data const & e) {
|
||||
void insert(data && e) {
|
||||
if ((m_size + m_num_deleted) << 2 > (m_capacity * 3)) {
|
||||
// if ((m_size + m_num_deleted) * 2 > (m_capacity)) {
|
||||
expand_table();
|
||||
|
@ -363,6 +395,11 @@ public:
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void insert(const data & e) {
|
||||
data tmp(e);
|
||||
insert(std::move(tmp));
|
||||
}
|
||||
|
||||
#define INSERT_LOOP_CORE_BODY() { \
|
||||
if (curr->is_used()) { \
|
||||
if (curr->get_hash() == hash && equals(curr->get_data(), e)) { \
|
||||
|
@ -375,7 +412,7 @@ public:
|
|||
entry * new_entry; \
|
||||
if (del_entry) { new_entry = del_entry; m_num_deleted--; } \
|
||||
else { new_entry = curr; } \
|
||||
new_entry->set_data(e); \
|
||||
new_entry->set_data(std::move(e)); \
|
||||
new_entry->set_hash(hash); \
|
||||
m_size++; \
|
||||
et = new_entry; \
|
||||
|
@ -393,7 +430,7 @@ public:
|
|||
Return true if it is a new element, and false otherwise.
|
||||
Store the entry/slot of the table in et.
|
||||
*/
|
||||
bool insert_if_not_there_core(data const & e, entry * & et) {
|
||||
bool insert_if_not_there_core(data && e, entry * & et) {
|
||||
if ((m_size + m_num_deleted) << 2 > (m_capacity * 3)) {
|
||||
// if ((m_size + m_num_deleted) * 2 > (m_capacity)) {
|
||||
expand_table();
|
||||
|
@ -415,6 +452,11 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool insert_if_not_there_core(const data & e, entry * & et) {
|
||||
data temp(e);
|
||||
return insert_if_not_there_core(std::move(temp), et);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Insert the element e if it is not in the table.
|
||||
Return a reference to e or to an object identical to e
|
||||
|
|
232
src/util/min_cut.cpp
Normal file
232
src/util/min_cut.cpp
Normal file
|
@ -0,0 +1,232 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Arie Gurfinkel
|
||||
|
||||
Module Name:
|
||||
|
||||
min_cut.cpp
|
||||
|
||||
Abstract:
|
||||
min cut solver
|
||||
|
||||
Author:
|
||||
Bernhard Gleiss
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
#include "util/min_cut.h"
|
||||
#include "util/trace.h"
|
||||
|
||||
min_cut::min_cut() {
|
||||
// push back two empty vectors for source and sink
|
||||
m_edges.push_back(edge_vector());
|
||||
m_edges.push_back(edge_vector());
|
||||
}
|
||||
|
||||
unsigned min_cut::new_node() {
|
||||
m_edges.push_back(edge_vector());
|
||||
return m_edges.size() - 1;
|
||||
}
|
||||
|
||||
void min_cut::add_edge(unsigned int i, unsigned int j, unsigned capacity) {
|
||||
m_edges.reserve(i + 1);
|
||||
m_edges[i].push_back(edge(j, capacity));
|
||||
TRACE("spacer.mincut", tout << "adding edge (" << i << "," << j << ")\n";);
|
||||
}
|
||||
|
||||
void min_cut::compute_min_cut(unsigned_vector& cut_nodes) {
|
||||
if (m_edges.size() == 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_d.resize(m_edges.size());
|
||||
m_pred.resize(m_edges.size());
|
||||
|
||||
// compute initial distances and number of nodes
|
||||
compute_initial_distances();
|
||||
|
||||
unsigned i = 0;
|
||||
|
||||
while (m_d[0] < m_edges.size()) {
|
||||
unsigned j = get_admissible_edge(i);
|
||||
|
||||
if (j < m_edges.size()) {
|
||||
// advance(i)
|
||||
m_pred[j] = i;
|
||||
i = j;
|
||||
|
||||
// if i is the sink, augment path
|
||||
if (i == 1) {
|
||||
augment_path();
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// retreat
|
||||
compute_distance(i);
|
||||
if (i != 0) {
|
||||
i = m_pred[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// split nodes into reachable and unreachable ones
|
||||
bool_vector reachable(m_edges.size());
|
||||
compute_reachable_nodes(reachable);
|
||||
|
||||
// find all edges between reachable and unreachable nodes and
|
||||
// for each such edge, add corresponding lemma to unsat-core
|
||||
compute_cut_and_add_lemmas(reachable, cut_nodes);
|
||||
}
|
||||
|
||||
void min_cut::compute_initial_distances() {
|
||||
unsigned_vector todo;
|
||||
bool_vector visited(m_edges.size());
|
||||
|
||||
todo.push_back(0); // start at the source, since we do postorder traversel
|
||||
|
||||
while (!todo.empty()) {
|
||||
unsigned current = todo.back();
|
||||
|
||||
// if we haven't already visited current
|
||||
if (!visited[current]) {
|
||||
bool exists_unvisited_parent = false;
|
||||
|
||||
// add unprocessed parents to stack for DFS. If there is at least
|
||||
// one unprocessed parent, don't compute the result
|
||||
// for current now, but wait until those unprocessed parents are processed
|
||||
for (auto const& edge : m_edges[current]) {
|
||||
unsigned parent = edge.node;
|
||||
|
||||
// if we haven't visited the current parent yet
|
||||
if (!visited[parent]) {
|
||||
// add it to the stack
|
||||
todo.push_back(parent);
|
||||
exists_unvisited_parent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if we already visited all parents, we can visit current too
|
||||
if (!exists_unvisited_parent) {
|
||||
visited[current] = true;
|
||||
todo.pop_back();
|
||||
|
||||
compute_distance(current); // I.H. all parent distances are already computed
|
||||
}
|
||||
}
|
||||
else {
|
||||
todo.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned min_cut::get_admissible_edge(unsigned i) {
|
||||
for (const auto& edge : m_edges[i]) {
|
||||
if (edge.weight > 0 && m_d[i] == m_d[edge.node] + 1) {
|
||||
return edge.node;
|
||||
}
|
||||
}
|
||||
return m_edges.size(); // no element found
|
||||
}
|
||||
|
||||
void min_cut::augment_path() {
|
||||
// find bottleneck capacity
|
||||
unsigned max = std::numeric_limits<unsigned int>::max();
|
||||
unsigned k = 1;
|
||||
while (k != 0) {
|
||||
unsigned l = m_pred[k];
|
||||
for (const auto& edge : m_edges[l]) {
|
||||
if (edge.node == k) {
|
||||
max = std::min(max, edge.weight);
|
||||
}
|
||||
}
|
||||
k = l;
|
||||
}
|
||||
|
||||
k = 1;
|
||||
while (k != 0) {
|
||||
unsigned l = m_pred[k];
|
||||
|
||||
// decrease capacity
|
||||
for (auto& edge : m_edges[l]) {
|
||||
if (edge.node == k) {
|
||||
edge.weight -= max;
|
||||
}
|
||||
}
|
||||
// increase reverse flow
|
||||
bool already_exists = false;
|
||||
for (auto& edge : m_edges[k]) {
|
||||
if (edge.node == l) {
|
||||
already_exists = true;
|
||||
edge.weight += max;
|
||||
}
|
||||
}
|
||||
if (!already_exists) {
|
||||
m_edges[k].push_back(edge(1, max));
|
||||
}
|
||||
k = l;
|
||||
}
|
||||
}
|
||||
|
||||
void min_cut::compute_distance(unsigned i) {
|
||||
if (i == 1) { // sink node
|
||||
m_d[1] = 0;
|
||||
}
|
||||
else {
|
||||
unsigned min = std::numeric_limits<unsigned int>::max();
|
||||
|
||||
// find edge (i,j) with positive residual capacity and smallest distance
|
||||
for (const auto& edge : m_edges[i]) {
|
||||
if (edge.weight > 0) {
|
||||
min = std::min(min, m_d[edge.node] + 1);
|
||||
}
|
||||
}
|
||||
m_d[i] = min;
|
||||
}
|
||||
}
|
||||
|
||||
void min_cut::compute_reachable_nodes(bool_vector& reachable) {
|
||||
unsigned_vector todo;
|
||||
|
||||
todo.push_back(0);
|
||||
while (!todo.empty()) {
|
||||
unsigned current = todo.back();
|
||||
todo.pop_back();
|
||||
|
||||
if (!reachable[current]) {
|
||||
reachable[current] = true;
|
||||
|
||||
for (const auto& edge : m_edges[current]) {
|
||||
if (edge.weight > 0) {
|
||||
todo.push_back(edge.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void min_cut::compute_cut_and_add_lemmas(bool_vector& reachable, unsigned_vector& cut_nodes) {
|
||||
unsigned_vector todo;
|
||||
bool_vector visited(m_edges.size());
|
||||
|
||||
todo.push_back(0);
|
||||
while (!todo.empty()) {
|
||||
unsigned current = todo.back();
|
||||
todo.pop_back();
|
||||
|
||||
if (!visited[current]) {
|
||||
visited[current] = true;
|
||||
|
||||
for (const auto& edge : m_edges[current]) {
|
||||
unsigned successor = edge.node;
|
||||
if (reachable[successor]) {
|
||||
todo.push_back(successor);
|
||||
}
|
||||
else {
|
||||
cut_nodes.push_back(successor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
63
src/util/min_cut.h
Normal file
63
src/util/min_cut.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Arie Gurfinkel
|
||||
|
||||
Module Name:
|
||||
|
||||
min_cut.h
|
||||
|
||||
Abstract:
|
||||
min cut solver
|
||||
|
||||
Author:
|
||||
Bernhard Gleiss
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef MIN_CUT_H_
|
||||
#define MIN_CUT_H_
|
||||
|
||||
#include "util/vector.h"
|
||||
|
||||
|
||||
class min_cut {
|
||||
public:
|
||||
min_cut();
|
||||
|
||||
/*
|
||||
\brief create a node
|
||||
*/
|
||||
unsigned new_node();
|
||||
|
||||
/*
|
||||
\brief add an i -> j edge with (unit) capacity
|
||||
*/
|
||||
void add_edge(unsigned i, unsigned j, unsigned capacity = 1);
|
||||
|
||||
/*
|
||||
\brief produce a min cut between source node = 0 and target node = 1.
|
||||
NB. the function changes capacities on edges.
|
||||
*/
|
||||
void compute_min_cut(unsigned_vector& cut_nodes);
|
||||
|
||||
private:
|
||||
|
||||
typedef svector<bool> bool_vector;
|
||||
struct edge { unsigned node; unsigned weight; edge(unsigned n, unsigned w): node(n), weight(w) {} edge(): node(0), weight(0) {} };
|
||||
typedef svector<edge> edge_vector;
|
||||
|
||||
vector<edge_vector> m_edges; // map from node to all outgoing edges together with their weights (also contains "reverse edges")
|
||||
unsigned_vector m_d; // approximation of distance from node to sink in residual graph
|
||||
unsigned_vector m_pred; // predecessor-information for reconstruction of augmenting path
|
||||
|
||||
void compute_initial_distances();
|
||||
unsigned get_admissible_edge(unsigned i);
|
||||
void augment_path();
|
||||
void compute_distance(unsigned i);
|
||||
void compute_reachable_nodes(bool_vector& reachable);
|
||||
void compute_cut_and_add_lemmas(bool_vector& reachable, unsigned_vector& cut_nodes);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -40,12 +40,6 @@ mpf::mpf(unsigned _ebits, unsigned _sbits):
|
|||
set(ebits, sbits);
|
||||
}
|
||||
|
||||
mpf::mpf(mpf const & other) {
|
||||
// It is safe if the mpz numbers are small.
|
||||
// I need it for resize method in vector.
|
||||
// UNREACHABLE();
|
||||
}
|
||||
|
||||
mpf::~mpf() {
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,12 @@ class mpf {
|
|||
public:
|
||||
mpf();
|
||||
mpf(unsigned ebits, unsigned sbits);
|
||||
mpf(mpf const & other);
|
||||
mpf(mpf && other) :
|
||||
ebits(other.ebits),
|
||||
sbits(other.sbits),
|
||||
sign(other.sign),
|
||||
significand(std::move(other.significand)),
|
||||
exponent(other.exponent) {}
|
||||
~mpf();
|
||||
unsigned get_ebits() const { return ebits; }
|
||||
unsigned get_sbits() const { return sbits; }
|
||||
|
|
|
@ -31,11 +31,10 @@ class mpq {
|
|||
public:
|
||||
mpq(int v):m_num(v), m_den(1) {}
|
||||
mpq():m_den(1) {}
|
||||
mpq(mpq && other) : m_num(std::move(other.m_num)), m_den(std::move(other.m_den)) {}
|
||||
void swap(mpq & other) { m_num.swap(other.m_num); m_den.swap(other.m_den); }
|
||||
mpz const & numerator() const { return m_num; }
|
||||
mpz const & denominator() const { return m_den; }
|
||||
|
||||
double get_double() const;
|
||||
};
|
||||
|
||||
inline void swap(mpq & m1, mpq & m2) { m1.swap(m2); }
|
||||
|
@ -745,6 +744,12 @@ public:
|
|||
reset_denominator(a);
|
||||
}
|
||||
|
||||
mpq dup(const mpq & source) {
|
||||
mpq temp;
|
||||
set(temp, source);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void swap(mpz & a, mpz & b) { mpz_manager<SYNCH>::swap(a, b); }
|
||||
|
||||
void swap(mpq & a, mpq & b) {
|
||||
|
|
|
@ -94,6 +94,9 @@ class mpz {
|
|||
public:
|
||||
mpz(int v):m_val(v), m_ptr(0) {}
|
||||
mpz():m_val(0), m_ptr(0) {}
|
||||
mpz(mpz && other) : m_val(other.m_val), m_ptr(0) {
|
||||
std::swap(m_ptr, other.m_ptr);
|
||||
}
|
||||
void swap(mpz & other) {
|
||||
std::swap(m_val, other.m_val);
|
||||
std::swap(m_ptr, other.m_ptr);
|
||||
|
@ -668,6 +671,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void set(mpz & target, mpz && source) {
|
||||
del(target);
|
||||
target.m_val = source.m_val;
|
||||
std::swap(target.m_ptr, source.m_ptr);
|
||||
}
|
||||
|
||||
void set(mpz & a, int val) {
|
||||
del(a);
|
||||
a.m_val = val;
|
||||
|
@ -700,6 +709,12 @@ public:
|
|||
|
||||
void set(mpz & target, unsigned sz, digit_t const * digits);
|
||||
|
||||
mpz dup(const mpz & source) {
|
||||
mpz temp;
|
||||
set(temp, source);
|
||||
return temp;
|
||||
}
|
||||
|
||||
void reset(mpz & a) {
|
||||
del(a);
|
||||
a.m_val = 0;
|
||||
|
|
|
@ -69,6 +69,10 @@ public:
|
|||
m_key(k),
|
||||
m_value(v) {
|
||||
}
|
||||
key_data(Key * k, Value && v) :
|
||||
m_key(k),
|
||||
m_value(std::move(v)) {
|
||||
}
|
||||
Value const & get_value() const { return m_value; }
|
||||
Key & get_key () const { return *m_key; }
|
||||
unsigned hash() const { return m_key->hash(); }
|
||||
|
@ -86,7 +90,7 @@ public:
|
|||
bool is_used() const { return m_data.m_key != reinterpret_cast<Key *>(0) && m_data.m_key != reinterpret_cast<Key *>(1); }
|
||||
key_data const & get_data() const { return m_data; }
|
||||
key_data & get_data() { return m_data; }
|
||||
void set_data(key_data const & d) { m_data = d; }
|
||||
void set_data(key_data && d) { m_data = std::move(d); }
|
||||
void set_hash(unsigned h) { SASSERT(h == m_data.hash()); }
|
||||
void mark_as_deleted() { m_data.m_key = reinterpret_cast<Key *>(1); }
|
||||
void mark_as_free() { m_data.m_key = 0; }
|
||||
|
@ -137,6 +141,10 @@ public:
|
|||
void insert(Key * const k, Value const & v) {
|
||||
m_table.insert(key_data(k, v));
|
||||
}
|
||||
|
||||
void insert(Key * const k, Value && v) {
|
||||
m_table.insert(key_data(k, std::move(v)));
|
||||
}
|
||||
|
||||
key_data const & insert_if_not_there(Key * k, Value const & v) {
|
||||
return m_table.insert_if_not_there(key_data(k, v));
|
||||
|
|
|
@ -53,6 +53,10 @@ public:
|
|||
inc_ref();
|
||||
}
|
||||
|
||||
obj_ref(obj_ref && other) : m_obj(0), m_manager(other.m_manager) {
|
||||
std::swap(m_obj, other.m_obj);
|
||||
}
|
||||
|
||||
~obj_ref() { dec_ref(); }
|
||||
|
||||
TManager & get_manager() const { return m_manager; }
|
||||
|
|
|
@ -41,6 +41,7 @@ public:
|
|||
rational() {}
|
||||
|
||||
rational(rational const & r) { m().set(m_val, r.m_val); }
|
||||
rational(rational && r) : m_val(std::move(r.m_val)) {}
|
||||
|
||||
explicit rational(int n) { m().set(m_val, n); }
|
||||
|
||||
|
|
|
@ -45,6 +45,10 @@ public:
|
|||
typedef T * data;
|
||||
|
||||
ref_vector_core(Ref const & r = Ref()):Ref(r) {}
|
||||
|
||||
ref_vector_core(ref_vector_core && other) :
|
||||
Ref(std::move(other)),
|
||||
m_nodes(std::move(other.m_nodes)) {}
|
||||
|
||||
~ref_vector_core() {
|
||||
dec_range_ref(m_nodes.begin(), m_nodes.end());
|
||||
|
@ -63,7 +67,7 @@ public:
|
|||
void resize(unsigned sz) {
|
||||
if (sz < m_nodes.size())
|
||||
dec_range_ref(m_nodes.begin() + sz, m_nodes.end());
|
||||
m_nodes.resize(sz, 0);
|
||||
m_nodes.resize(sz);
|
||||
}
|
||||
|
||||
void resize(unsigned sz, T * d) {
|
||||
|
@ -80,7 +84,7 @@ public:
|
|||
void reserve(unsigned sz) {
|
||||
if (sz <= m_nodes.size())
|
||||
return;
|
||||
m_nodes.resize(sz, 0);
|
||||
m_nodes.resize(sz);
|
||||
}
|
||||
|
||||
void shrink(unsigned sz) {
|
||||
|
@ -207,6 +211,8 @@ public:
|
|||
this->append(other);
|
||||
}
|
||||
|
||||
ref_vector(ref_vector && other) : super(std::move(other)) {}
|
||||
|
||||
ref_vector(TManager & m, unsigned sz, T * const * data):
|
||||
super(ref_manager_wrapper<T, TManager>(m)) {
|
||||
this->append(sz, data);
|
||||
|
|
|
@ -63,8 +63,7 @@ public:
|
|||
unsigned old_sz = this->size();
|
||||
if (sz <= old_sz)
|
||||
shrink(sz);
|
||||
typename Manager::numeral zero(0);
|
||||
svector<typename Manager::numeral>::resize(sz, zero);
|
||||
svector<typename Manager::numeral>::resize(sz, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
bool empty() const { return m_vector.empty(); }
|
||||
void resize(unsigned sz) {
|
||||
if (sz < m_vector.size()) {
|
||||
for (unsigned i = m_vector.size(); i < sz; i++)
|
||||
for (unsigned i = m_vector.size(); i-- > sz; )
|
||||
dealloc(m_vector[i]);
|
||||
m_vector.shrink(sz);
|
||||
}
|
||||
|
|
|
@ -185,4 +185,15 @@ public:
|
|||
|
||||
#endif
|
||||
|
||||
struct scoped_watch {
|
||||
stopwatch &m_sw;
|
||||
scoped_watch (stopwatch &sw, bool reset=false): m_sw(sw) {
|
||||
if (reset) m_sw.reset();
|
||||
m_sw.start();
|
||||
}
|
||||
~scoped_watch() {
|
||||
m_sw.stop ();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -55,6 +55,7 @@ static_assert(sizeof(int64) == 8, "64 bits");
|
|||
#ifdef _WINDOWS
|
||||
#define SSCANF sscanf_s
|
||||
#define SPRINTF sprintf_s
|
||||
#define _Exit exit
|
||||
#else
|
||||
#define SSCANF sscanf
|
||||
#define SPRINTF sprintf
|
||||
|
@ -333,7 +334,7 @@ bool compare_arrays(const T * array1, const T * array2, unsigned size) {
|
|||
template<typename T>
|
||||
void force_ptr_array_size(T & v, unsigned sz) {
|
||||
if (sz > v.size()) {
|
||||
v.resize(sz, 0);
|
||||
v.resize(sz);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ Revision History:
|
|||
|
||||
#include "util/debug.h"
|
||||
#include<algorithm>
|
||||
#include<type_traits>
|
||||
#include<memory.h>
|
||||
#include "util/memory_manager.h"
|
||||
#include "util/hash.h"
|
||||
|
@ -75,9 +76,27 @@ class vector {
|
|||
UNREACHABLE();
|
||||
throw default_exception("Overflow encountered when expanding vector");
|
||||
}
|
||||
SZ *mem = (SZ*)memory::reallocate(reinterpret_cast<SZ*>(m_data)-2, new_capacity_T);
|
||||
*mem = new_capacity;
|
||||
m_data = reinterpret_cast<T *>(mem + 2);
|
||||
SZ *mem, *old_mem = reinterpret_cast<SZ*>(m_data) - 2;
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
|
||||
if (__has_trivial_copy(T)) {
|
||||
#else
|
||||
if (std::is_trivially_copyable<T>::value) {
|
||||
#endif
|
||||
mem = (SZ*)memory::reallocate(old_mem, new_capacity_T);
|
||||
m_data = reinterpret_cast<T *>(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<T *>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,6 +168,10 @@ public:
|
|||
SASSERT(size() == source.size());
|
||||
}
|
||||
|
||||
vector(vector&& other) : m_data(0) {
|
||||
std::swap(m_data, other.m_data);
|
||||
}
|
||||
|
||||
vector(SZ s, T const * data):
|
||||
m_data(0) {
|
||||
for (SZ i = 0; i < s; i++) {
|
||||
|
@ -180,6 +203,16 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
vector & operator=(vector && source) {
|
||||
if (this == &source) {
|
||||
return *this;
|
||||
}
|
||||
destroy();
|
||||
m_data = 0;
|
||||
std::swap(m_data, source.m_data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (m_data) {
|
||||
if (CallDestructors) {
|
||||
|
@ -293,6 +326,11 @@ public:
|
|||
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);
|
||||
|
@ -319,6 +357,14 @@ public:
|
|||
reinterpret_cast<SZ *>(m_data)[SIZE_IDX]++;
|
||||
}
|
||||
|
||||
void push_back(T && elem) {
|
||||
if (m_data == 0 || reinterpret_cast<SZ *>(m_data)[SIZE_IDX] == reinterpret_cast<SZ *>(m_data)[CAPACITY_IDX]) {
|
||||
expand_vector();
|
||||
}
|
||||
new (m_data + reinterpret_cast<SZ *>(m_data)[SIZE_IDX]) T(std::move(elem));
|
||||
reinterpret_cast<SZ *>(m_data)[SIZE_IDX]++;
|
||||
}
|
||||
|
||||
void insert(T const & elem) {
|
||||
push_back(elem);
|
||||
}
|
||||
|
@ -358,7 +404,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void resize(SZ s, T const & elem=T()) {
|
||||
template<typename Args>
|
||||
void resize(SZ s, Args args...) {
|
||||
SZ sz = size();
|
||||
if (s <= sz) { shrink(s); return; }
|
||||
while (s > capacity()) {
|
||||
|
@ -368,8 +415,23 @@ public:
|
|||
reinterpret_cast<SZ *>(m_data)[SIZE_IDX] = s;
|
||||
iterator it = m_data + sz;
|
||||
iterator end = m_data + s;
|
||||
for(; it != end; ++it) {
|
||||
new (it) T(elem);
|
||||
for (; it != end; ++it) {
|
||||
new (it) T(std::forward<Args>(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<SZ *>(m_data)[SIZE_IDX] = s;
|
||||
iterator it = m_data + sz;
|
||||
iterator end = m_data + s;
|
||||
for (; it != end; ++it) {
|
||||
new (it) T();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,10 +502,15 @@ public:
|
|||
return m_data[idx];
|
||||
}
|
||||
|
||||
void reserve(SZ s, T const & d = T()) {
|
||||
void reserve(SZ s, T const & d) {
|
||||
if (s > size())
|
||||
resize(s, d);
|
||||
}
|
||||
|
||||
void reserve(SZ s) {
|
||||
if (s > size())
|
||||
resize(s);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -453,7 +520,12 @@ public:
|
|||
ptr_vector(unsigned s):vector<T *, false>(s) {}
|
||||
ptr_vector(unsigned s, T * elem):vector<T *, false>(s, elem) {}
|
||||
ptr_vector(ptr_vector const & source):vector<T *, false>(source) {}
|
||||
ptr_vector(ptr_vector && other) : vector<T*, false>(std::move(other)) {}
|
||||
ptr_vector(unsigned s, T * const * data):vector<T *, false>(s, const_cast<T**>(data)) {}
|
||||
ptr_vector & operator=(ptr_vector const & source) {
|
||||
vector<T *, false>::operator=(source);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename SZ = unsigned>
|
||||
|
@ -463,7 +535,12 @@ public:
|
|||
svector(SZ s):vector<T, false, SZ>(s) {}
|
||||
svector(SZ s, T const & elem):vector<T, false, SZ>(s, elem) {}
|
||||
svector(svector const & source):vector<T, false, SZ>(source) {}
|
||||
svector(svector && other) : vector<T, false, SZ>(std::move(other)) {}
|
||||
svector(SZ s, T const * data):vector<T, false, SZ>(s, data) {}
|
||||
svector & operator=(svector const & source) {
|
||||
vector<T, false, SZ>::operator=(source);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef svector<int> int_vector;
|
||||
|
@ -500,23 +577,4 @@ struct vector_hash : public vector_hash_tpl<Hash, vector<typename Hash::data> >
|
|||
template<typename Hash>
|
||||
struct svector_hash : public vector_hash_tpl<Hash, svector<typename Hash::data> > {};
|
||||
|
||||
#include <vector>
|
||||
// Specialize vector<std::string> to be an instance of std::vector instead.
|
||||
// This will catch any regression of issue #564 and #420.
|
||||
|
||||
template <>
|
||||
class vector<std::string, true, unsigned> : public std::vector<std::string> {
|
||||
public:
|
||||
vector(vector<std::string, true, unsigned> const& other): std::vector<std::string>(other) {}
|
||||
vector(size_t sz, char const* s): std::vector<std::string>(sz, s) {}
|
||||
vector() {}
|
||||
|
||||
void reset() { clear(); }
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* VECTOR_H_ */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue