diff options
author | Tuowen Zhao <ztuowen@gmail.com> | 2016-09-19 21:14:58 +0000 |
---|---|---|
committer | Tuowen Zhao <ztuowen@gmail.com> | 2016-09-19 21:14:58 +0000 |
commit | 210f77d2c32f14d2e99577fd3c9842bb19d47e50 (patch) | |
tree | 5edb327c919b8309e301c3440fb6668a0075c8ef /lib/omega/src/Relation.cc | |
parent | a66ce5cd670c4d3c0dc449720f5bc45dd4c281b8 (diff) | |
download | chill-210f77d2c32f14d2e99577fd3c9842bb19d47e50.tar.gz chill-210f77d2c32f14d2e99577fd3c9842bb19d47e50.tar.bz2 chill-210f77d2c32f14d2e99577fd3c9842bb19d47e50.zip |
Moved most modules into lib
Diffstat (limited to 'lib/omega/src/Relation.cc')
-rw-r--r-- | lib/omega/src/Relation.cc | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/lib/omega/src/Relation.cc b/lib/omega/src/Relation.cc new file mode 100644 index 0000000..1cca43a --- /dev/null +++ b/lib/omega/src/Relation.cc @@ -0,0 +1,279 @@ +/***************************************************************************** + Copyright (C) 1994-2000 the Omega Project Team + Copyright (C) 2005-2011 Chun Chen + All Rights Reserved. + + Purpose: + class Relation + + Notes: + + History: +*****************************************************************************/ + +#include <omega/Relation.h> +#include <omega/Relations.h> +#include <omega/pres_dnf.h> +#include <omega/pres_conj.h> +#include <omega/Rel_map.h> +#include <omega/omega_i.h> +#include <omega/omega_core/debugging.h> + +namespace omega { + +// copy function for Relation, will be removed in the future +// in favor of correct C++ copy constructor and const paramater passing +Relation copy(const Relation &t) { + Relation r = t; + return r; +} + +// +// Create null relation. +// +Relation::Relation() : rel_body(&null_rel) { + rel_body->ref_count = 1; +} + +Relation Relation::Null() { + return Relation(); +} + +bool Relation::is_null() const { + return(rel_body == &null_rel); +} + + +// +// Create a relation. Its will be built later. +// +Relation::Relation(int n_input, int n_output) { + rel_body = new Rel_Body(n_input,n_output); + rel_body->ref_count = 1; +} + +Relation::Relation(Rel_Body &r, int) { + rel_body = &r; + r.ref_count++; +} + +Relation Relation::Empty(const Relation &R) { + if (R.is_set()) return Relation(R.n_set()); + else return Relation(R.n_inp(),R.n_out()); +} + +// +// Create relation which is FALSE or TRUE. +// + +Relation Relation::True(const Relation &R) { + if (R.is_set()) return True(R.n_set()); + else return True(R.n_inp(),R.n_out()); +} + +Relation Relation::False(const Relation &R) { + if (R.is_set()) return False(R.n_set()); + else return False(R.n_inp(),R.n_out()); +} + +Relation Relation::Unknown(const Relation &R) { + if (R.is_set()) return Unknown(R.n_set()); + else return Unknown(R.n_inp(), R.n_out()); +} + + +Relation Relation::True(int setvars) { + Relation R(setvars); + R.add_and(); + R.finalize(); + return R; +} + +Relation Relation::True (int in, int out) { + Relation R(in,out); + R.add_and(); + R.finalize(); + return R; +} + +Relation Relation::False (int setvars) { + Relation R(setvars); + R.add_or(); + R.finalize(); + return R; +} + +Relation Relation::False (int in, int out) { + Relation R(in,out); + R.add_or(); + R.finalize(); + return R; +} + + +Relation Relation::Unknown (int setvars) { + Relation R(setvars); + R.add_and(); + R.finalize(); + R.simplify(); + Conjunct * c= R.single_conjunct(); + c->make_inexact(); + return R; +} + +Relation Relation::Unknown (int in, int out) { + Relation R(in,out); + R.add_and(); + R.finalize(); + R.simplify(); + Conjunct * c= R.single_conjunct(); + c->make_inexact(); + return R; +} + + +// +// Copy a relation. +// +Relation::Relation(const Relation &r) { +#if defined(INCLUDE_COMPRESSION) + assert(!r.is_compressed()); +#endif + if (r.is_finalized()) { + rel_body = r.rel_body; + rel_body->ref_count++; + } else { + assert(! r.rel_body->is_shared()); + // rel_body = new Rel_Body(r.rel_body); + rel_body = r.rel_body->clone(); + rel_body->ref_count = 1; + } +} + +// +// Copy relation r and replace formula in it with conjunct c. +// Wayne (TM) function. +// +Relation::Relation(const Relation &r, Conjunct *c) { + rel_body = new Rel_Body(r.rel_body, c); + rel_body->ref_count = 1; +} + + +// +// Assign a relation r to this relation. +// +Relation &Relation::operator=(const Relation &r) { +#if defined(INCLUDE_COMPRESSION) + assert (!r.is_compressed()); +#endif + + /* === Destroy this === */ + assert(rel_body->ref_count >= 1); + if(rel_body!=&null_rel && --(rel_body->ref_count)==0) { + delete rel_body; + } + + /* === Copy r to this === */ + if (r.is_finalized()) { + rel_body = r.rel_body; + rel_body->ref_count++; + } else { + assert(! r.rel_body->is_shared()); + // rel_body = new Rel_Body(r.rel_body); + rel_body = r.rel_body->clone(); + rel_body->ref_count = 1; + } + return *this; +} + +void Relation::copy_names(Rel_Body &r) { + int t; + for(t = 1; t <= r.n_inp(); t++) + name_input_var(t,r.input_var(t)->base_name); + for(t = 1; t <= r.n_out(); t++) + name_output_var(t,r.output_var(t)->base_name); +} + + +// Like makeSet (see Relations.c), but won't invert the relation -- +// fails if it has output instead of input variables. Called in Relation +// functions just after a MapRel, so that we know there are no outputs anyway. + +void Relation::markAsSet() { + assert(!is_null()); + assert(is_set() || (n_inp() >= 0 && n_out() == 0)); + if (!is_set()) split(); // split if we'll modify this + rel_body->_is_set = true; + invalidate_leading_info(); +} + +void Relation::markAsRelation() { + assert(!is_null()); + if (is_set()) split(); // split if we'll modify this + rel_body->_is_set = false; +} + + +Relation::~Relation() { + assert(rel_body->ref_count >= 1); + assert(this->is_null() == (rel_body == &null_rel)); + if(rel_body!=&null_rel && --(rel_body->ref_count)==0) { + if (rel_body == &null_rel) abort(); + delete rel_body; + } +} + + + +// +// One of the representatives using the body wants to be changed. +// Create a separate body for this rep not to damage other reps. +// Return address of the body. Old rep point to new body. +// +Rel_Body *Relation::split() { + assert(rel_body != &null_rel && "Error: Attempt to modify a null relation"); + assert (rel_body->ref_count >= 1); + if(!(rel_body==&null_rel || rel_body->ref_count==1)) { + if(pres_debug) { + fprintf(DebugFile, "+++ SPLIT relation +++\n"); + } + // Rel_Body *new_body = new Rel_Body(rel_body); + Rel_Body *new_body = rel_body->clone(); + new_body->ref_count = 1; + rel_body->ref_count--; + rel_body = new_body; + if(pres_debug>=2) { + fprintf(DebugFile, " copying 0x%p to give 0x%p\n", this, rel_body); + } + } + return (rel_body); +} + + +void Relation::dimensions(int & ndim_all, int &ndim_domain) { + ndim_all = ndim_domain = 0; + int a,d; + simplify(2,2); + for (DNF_Iterator s(query_DNF()); s.live(); s.next()) { + s.curr()->calculate_dimensions(*this, a, d); + if (a > ndim_all) ndim_all = a; + if (d > ndim_domain) ndim_domain = d; + } +} + +// Make a set: assert that it had only input or output variables, make it +// it have only input, set a flag. Called from domain, range, and difference, +// as well as functions that require a set as input. +void Relation::makeSet() { + assert(!is_null()); + // Assert that it is a set... + assert((n_inp() == 0 && n_out() >= 0) || (n_inp() >= 0 && n_out() == 0)); + + if ((n_inp() == 0 && n_out() != 0) || !is_set()) split(); // split if we'll modify this + if (n_inp() == 0 && n_out() != 0) //Inverse the relation + Inverse(*this); // Modifies "this"; also returns this but we ignore it + rel_body->_is_set = true; +} + +} // namespace |