From 210f77d2c32f14d2e99577fd3c9842bb19d47e50 Mon Sep 17 00:00:00 2001 From: Tuowen Zhao Date: Mon, 19 Sep 2016 21:14:58 +0000 Subject: Moved most modules into lib --- lib/omega/include/basic/Bag.h | 405 ++++++++++++++++ lib/omega/include/basic/BoolSet.h | 641 +++++++++++++++++++++++++ lib/omega/include/basic/Collection.h | 43 ++ lib/omega/include/basic/Collections.h | 12 + lib/omega/include/basic/ConstString.h | 57 +++ lib/omega/include/basic/DynamicArray.h | 318 ++++++++++++ lib/omega/include/basic/Iterator.h | 129 +++++ lib/omega/include/basic/Link.h | 97 ++++ lib/omega/include/basic/List.h | 233 +++++++++ lib/omega/include/basic/Map.h | 127 +++++ lib/omega/include/basic/Section.h | 138 ++++++ lib/omega/include/basic/SimpleList.h | 194 ++++++++ lib/omega/include/basic/Tuple.h | 336 +++++++++++++ lib/omega/include/basic/omega_error.h | 14 + lib/omega/include/basic/util.h | 263 ++++++++++ lib/omega/include/omega.h | 71 +++ lib/omega/include/omega/RelBody.h | 165 +++++++ lib/omega/include/omega/Rel_map.h | 161 +++++++ lib/omega/include/omega/Relation.h | 299 ++++++++++++ lib/omega/include/omega/Relations.h | 88 ++++ lib/omega/include/omega/closure.h | 31 ++ lib/omega/include/omega/evac.h | 15 + lib/omega/include/omega/farkas.h | 19 + lib/omega/include/omega/hull.h | 89 ++++ lib/omega/include/omega/omega_core/debugging.h | 30 ++ lib/omega/include/omega/omega_core/oc.h | 350 ++++++++++++++ lib/omega/include/omega/omega_core/oc_i.h | 79 +++ lib/omega/include/omega/omega_i.h | 30 ++ lib/omega/include/omega/pres_cmpr.h | 49 ++ lib/omega/include/omega/pres_cnstr.h | 192 ++++++++ lib/omega/include/omega/pres_conj.h | 299 ++++++++++++ lib/omega/include/omega/pres_decl.h | 55 +++ lib/omega/include/omega/pres_dnf.h | 87 ++++ lib/omega/include/omega/pres_form.h | 112 +++++ lib/omega/include/omega/pres_gen.h | 192 ++++++++ lib/omega/include/omega/pres_logic.h | 90 ++++ lib/omega/include/omega/pres_quant.h | 63 +++ lib/omega/include/omega/pres_subs.h | 88 ++++ lib/omega/include/omega/pres_tree.h | 15 + lib/omega/include/omega/pres_var.h | 230 +++++++++ lib/omega/include/omega/reach.h | 23 + 41 files changed, 5929 insertions(+) create mode 100644 lib/omega/include/basic/Bag.h create mode 100755 lib/omega/include/basic/BoolSet.h create mode 100644 lib/omega/include/basic/Collection.h create mode 100644 lib/omega/include/basic/Collections.h create mode 100644 lib/omega/include/basic/ConstString.h create mode 100644 lib/omega/include/basic/DynamicArray.h create mode 100644 lib/omega/include/basic/Iterator.h create mode 100644 lib/omega/include/basic/Link.h create mode 100644 lib/omega/include/basic/List.h create mode 100644 lib/omega/include/basic/Map.h create mode 100644 lib/omega/include/basic/Section.h create mode 100644 lib/omega/include/basic/SimpleList.h create mode 100644 lib/omega/include/basic/Tuple.h create mode 100644 lib/omega/include/basic/omega_error.h create mode 100644 lib/omega/include/basic/util.h create mode 100644 lib/omega/include/omega.h create mode 100644 lib/omega/include/omega/RelBody.h create mode 100644 lib/omega/include/omega/Rel_map.h create mode 100644 lib/omega/include/omega/Relation.h create mode 100644 lib/omega/include/omega/Relations.h create mode 100644 lib/omega/include/omega/closure.h create mode 100644 lib/omega/include/omega/evac.h create mode 100644 lib/omega/include/omega/farkas.h create mode 100644 lib/omega/include/omega/hull.h create mode 100644 lib/omega/include/omega/omega_core/debugging.h create mode 100644 lib/omega/include/omega/omega_core/oc.h create mode 100644 lib/omega/include/omega/omega_core/oc_i.h create mode 100644 lib/omega/include/omega/omega_i.h create mode 100644 lib/omega/include/omega/pres_cmpr.h create mode 100644 lib/omega/include/omega/pres_cnstr.h create mode 100644 lib/omega/include/omega/pres_conj.h create mode 100644 lib/omega/include/omega/pres_decl.h create mode 100644 lib/omega/include/omega/pres_dnf.h create mode 100644 lib/omega/include/omega/pres_form.h create mode 100644 lib/omega/include/omega/pres_gen.h create mode 100644 lib/omega/include/omega/pres_logic.h create mode 100644 lib/omega/include/omega/pres_quant.h create mode 100644 lib/omega/include/omega/pres_subs.h create mode 100644 lib/omega/include/omega/pres_tree.h create mode 100644 lib/omega/include/omega/pres_var.h create mode 100644 lib/omega/include/omega/reach.h (limited to 'lib/omega/include') diff --git a/lib/omega/include/basic/Bag.h b/lib/omega/include/basic/Bag.h new file mode 100644 index 0000000..a3d07a0 --- /dev/null +++ b/lib/omega/include/basic/Bag.h @@ -0,0 +1,405 @@ +#if ! defined _Bag_h +#define _Bag_h 1 + +#include +#include +#include +#include +#include + +namespace omega { + +template class Bag : public Collection { +public: +virtual ~Bag(); + Bag(); + Bag(const Bag&); + Bag & operator=(const Bag&); + //! add elements in b + virtual void operator |= (const Bag & b); + Iterator *new_iterator(); + bool empty() const; + void remove(T); + virtual void insert(T); + void clear(); + virtual bool contains(T) const; + int size() const; + T extract(); +// protected: breaks g++ 261 + List_Element* contents; +}; + + +template class Ordered_Bag : public Bag { +public: + Ordered_Bag(); + Ordered_Bag(const Ordered_Bag& B) : Bag(B) {} + void insert(T); + //! add elements in b + virtual void operator |= (const Ordered_Bag & b); + //! add elements in b + void operator |= (const Bag & b); + bool contains(T) const; + bool operator == (const Ordered_Bag&) const; + bool operator != (const Ordered_Bag&) const; + bool operator < (const Ordered_Bag&) const; +}; + +template class Set : public Ordered_Bag { +public: + Set(); + Set(T); + Set(const Set& S) : Ordered_Bag(S) {} + + bool contains (const Set& b) const; + bool contains (T t) const { return Ordered_Bag::contains(t); } + // the above makes "standard" C++ happy + + //! add elements in b + virtual void operator |= (const Set & b); + //! add elements in b + void operator |= (const Ordered_Bag & b); + //! add elements in b + void operator |= (const Bag & b); + + //! delete items also in b + void operator -= (const Set & b); + //! delete items not in b + void operator &= (const Set & b); + //! check for elements in common + bool operator & (const Set &) const; +}; + +} // namespace + +#define instantiate_Bag(T) template class Bag; \ + instantiate_List_Element(T); +#define instantiate_Ordered_Bag(T) template class Ordered_Bag; \ + instantiate_Bag(T) +#define instantiate_Set(T) template class Set; \ + instantiate_Ordered_Bag(T) + + +namespace omega { + +template Bag::Bag() { + contents = new List_Element ; + contents->tail = 0; + } +template Bag::~Bag() { + delete contents; + } + +template Ordered_Bag::Ordered_Bag() {} + +template Set::Set() {} + +template Bag::Bag(const Bag &L) { + contents = new List_Element(*L.contents); + } + +template Bag & Bag::operator=(const Bag &L) { + if (this != &L) { + delete contents; + contents = new List_Element(*L.contents); + } + return *this; + } + + + +template Set::Set(T e) { + assert(this->contents); + this->contents->tail = new List_Element(e, 0); + } + + +/**************************************************************** + * * + * Misc. simple Collection operations * + * * + ****************************************************************/ + +template bool Bag::empty() const { + return contents->tail == 0; + } + +template Iterator *Bag::new_iterator() + { + return new List_Element_Iterator(contents->tail); + } + + +template void Bag::clear() { + if (contents->tail) delete contents->tail; + contents->tail = 0; + } + +template int Bag::size() const { + int i = 0; + List_Element * p = contents->tail; + while (p) { + p = p->tail; + i++; + }; + return i; + } + + +/**************************************************************** + * * + * Collection/Element operations (e.g. insert, contains) * + * * + ****************************************************************/ + +template void Bag::remove(T e) { + List_Element * p = contents; + while (p->tail && p->tail->head != e) p = p->tail; + if (p->tail && p->tail->head == e) { + List_Element * q = p->tail; + p->tail = q->tail; + q->tail = 0; + delete q; + } + } + +template T Bag::extract() { + List_Element * p = contents->tail; + T e = p->head; + contents->tail = p->tail; + p->tail = 0; + delete p; + return e; + } + + +template void Bag::insert(T e) { + List_Element * q = new List_Element(e,contents->tail); + contents->tail = q; + } + +template void Ordered_Bag::insert(T e) { + List_Element * p = this->contents; + while (p->tail && p->tail->head < e) p = p->tail; + if (!p->tail || p->tail->head != e) { + List_Element * q = new List_Element(e,p->tail); + p->tail = q; + } + } + + +template bool Bag::contains(T e) const { + List_Element * p = contents; + while (p->tail && p->tail->head != e) p = p->tail; + return (p->tail && p->tail->head == e); + } + +template bool Ordered_Bag::contains(T e) const { + List_Element * p = this->contents; + while (p->tail && p->tail->head < e) p = p->tail; + return (p->tail && p->tail->head == e); + } + + +template bool Set::contains (const Set& b) const { + List_Element * p = this->contents; + List_Element * q = b.contents; + do { + /* consume matched elements in p and q */ + p = p->tail; + q = q->tail; + if (!q) return 1; /* no more elements to match */ + if (!p) return 0; /* nothing left in p to match with */ + if (q->head < p->head) { + /* nothing smaller than + p->head left in p, so q->head + can't be matched */ + return 0; + }; + while (p && p->head < q->head) { + /* toss away some elements from p */ + p = p->tail; + } + if (!p || q->head < p->head) return 0; + } while (q); + + return 1; + } + + + +/**************************************************************** + * * + * Collection/Collection operations (e.g. |=) * + * * + ****************************************************************/ + +template void Bag::operator |= (const Bag & b) { + assert(this != &b); + List_Element * q = b.contents->tail; + + while (q) { + List_Element * r = new List_Element(q->head,contents->tail); + contents->tail = r; + q = q->tail; + } + } + +template void Ordered_Bag::operator |= (const Ordered_Bag & b) { + if (this == &b) return; + List_Element * p = this->contents; + List_Element * q = b.contents->tail; + + while (q) { + while (p->tail && p->tail->head < q->head) p = p->tail; + List_Element * r = new List_Element(q->head,p->tail); + p->tail = r; + q = q->tail; + } + } + +template void Ordered_Bag::operator |= (const Bag & b) { + Ordered_Bag tmp; + for (List_Element *p = b.contents; p; p=p->tail) { + tmp.insert(p->head); + } + *this |= tmp; +} + +template void Set::operator |= (const Set & b) { + if (this == &b) return; + List_Element * p = this->contents; + List_Element * q = b.contents->tail; + + while (q) { + while (p->tail && p->tail->head < q->head) p = p->tail; + if (!p->tail || p->tail->head != q->head) { + List_Element * r = new List_Element(q->head,p->tail); + p->tail = r; + } + q = q->tail; + } + } + +template void Set::operator |= (const Ordered_Bag & b) { + Set tmp; + for (List_Element *p = b.contents; p; p=p->tail) { + tmp.insert(p->head); + } + *this |= tmp; +} + +template void Set::operator |= (const Bag & b) { + Set tmp; + for (List_Element *p = b.contents; p; p=p->tail) { + tmp.insert(p->head); + } + *this |= tmp; +} + + + +// delete items also in b +template void Set::operator -= (const Set & b) { + if (this == &b) { + this->clear(); + return; + } + List_Element * p = this->contents; + List_Element * q = b.contents->tail; + + while (q) { + while (p->tail && p->tail->head < q->head) p = p->tail; + if (p->tail && p->tail->head == q->head) { + List_Element * r = p->tail; + p->tail = r->tail; + r->tail = 0; + delete r; + } + q = q->tail; + } + } + + +// delete items not in b +template void Set::operator &= (const Set & b) + { + if (this == &b) return; + List_Element * p = this->contents; + List_Element * q = b.contents->tail; + + while (q) { + while (p->tail && p->tail->head < q->head) { + List_Element * r = p->tail; + p->tail = r->tail; + r->tail = 0; + delete r; + }; + if (p->tail && p->tail->head == q->head) { + /* allow p->tail->head into the result */ + p = p->tail; + } + /* q->head has matched anything it is going to match */ + q = q->tail; + } + if (p->tail) { + delete p->tail; + p->tail = 0; + }; + + } + + +template bool Set::operator & (const Set& b) const { + List_Element * p = this->contents; + List_Element * q = b.contents; + do { + p = p->tail; + q = q->tail; + while (p && q && p->head != q->head) { + while (p && p->head < q->head) p = p->tail; + while (p && q && q->head < p->head) q = q->tail; + }; + if (p && q && p->head == q->head) return 1; + } while (p && q); + + return 0; + } + + +template bool Ordered_Bag::operator == (const Ordered_Bag& b) const { + List_Element * p = this->contents; + List_Element * q = b.contents; + while (1) { + p = p->tail; + q = q->tail; + if (!p && !q) return 1; + if (!p || !q) return 0; + if (p->head != q->head) return 0; + }; + + } + +template bool Ordered_Bag::operator != (const Ordered_Bag& b) const { + return !(*this == b); + } + +template bool Ordered_Bag::operator < (const Ordered_Bag& b) const { + List_Element * p = this->contents; + List_Element * q = b.contents; + while (1) { + p = p->tail; + q = q->tail; + if (!p && !q) return 0; + if (!p) return 1; + if (!q) return 0; + if (p->head < q->head) return 1; + if (q->head < p->head) return 0; + }; + + return 1; + } + +} // namespace + +#endif diff --git a/lib/omega/include/basic/BoolSet.h b/lib/omega/include/basic/BoolSet.h new file mode 100755 index 0000000..a78af2e --- /dev/null +++ b/lib/omega/include/basic/BoolSet.h @@ -0,0 +1,641 @@ +/***************************************************************************** + Copyright (C) 2009-2011 Chun Chen + All Rights Reserved. + + Purpose: + BoolSet class, used as a set of integers from 0..n-1 where n is a very + small integer. + + Notes: + Set operands of binary operations can be of different sizes, missing + elements are treated as false. + + History: + 03/30/09 Created by Chun Chen. + 03/26/11 iterator added, -chun +*****************************************************************************/ + +#ifndef _BOOLSET_H +#define _BOOLSET_H + +#include +#include +#include +#include +#include + +namespace omega { + + //! BoolSet class, used as a set of integers from 0 to n-1 where n is a very small integer. +template +class BoolSet { +protected: + unsigned int size_; + std::vector set_; + +public: + BoolSet(unsigned int size = 0); + ~BoolSet() {} + + void set(unsigned int); + void unset(unsigned int); + void set_all(); + void unset_all(); + bool get(unsigned int) const; + unsigned int size() const {return size_;} + unsigned int num_elem() const; + bool imply(const BoolSet &) const; + bool empty() const; + void dump() const; + + BoolSet &operator|=(const BoolSet &); + BoolSet &operator&=(const BoolSet &); + BoolSet &operator-=(const BoolSet &); + + //! union + template friend BoolSet operator|(const BoolSet &, const BoolSet &); + //! intersection + template friend BoolSet operator&(const BoolSet &, const BoolSet &); + //! difference + template friend BoolSet operator-(const BoolSet &, const BoolSet &); + //! complement + template friend BoolSet operator~(const BoolSet &); + template friend bool operator==(const BoolSet &, const BoolSet &); + template friend bool operator!=(const BoolSet &, const BoolSet &); + template friend std::ostream& operator<<(std::ostream &, const BoolSet &); + template friend bool operator<(const BoolSet &, const BoolSet &); + +public: + class iterator; + class const_iterator; + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; +}; + + +template +BoolSet::BoolSet(unsigned int size) { + assert(size >= 0); + size_ = size; + unsigned int n = size / (sizeof(T)*8); + unsigned int r = size % (sizeof(T)*8); + if (r != 0) + n++; + set_ = std::vector(n, static_cast(0)); +} + + +template +void BoolSet::set(unsigned int i) { + assert(i < size_ && i >= 0); + unsigned int n = i / (sizeof(T)*8); + unsigned int r = i % (sizeof(T)*8); + + T t = static_cast(1) << r; + set_[n] |= t; +} + + +template +void BoolSet::unset(unsigned int i) { + assert(i < size_ && i >= 0); + unsigned int n = i / (sizeof(T)*8); + unsigned int r = i % (sizeof(T)*8); + + T t = static_cast(1) << r; + t = ~t; + set_[n] &= t; +} + + +template +void BoolSet::set_all() { + unsigned int r = size_ % (sizeof(T)*8); + if (r == 0) { + for (unsigned int i = 0; i < set_.size(); i++) + set_[i] = ~static_cast(0); + } + else { + for (unsigned int i = 0; i < set_.size()-1; i++) + set_[i] = ~static_cast(0); + set_[set_.size()-1] = static_cast(0); + T t = static_cast(1); + for (unsigned int i = 0; i < r; i++) { + set_[set_.size()-1] |= t; + t = t<<1; + } + } +} + + +template +void BoolSet::unset_all() { + for (unsigned int i = 0; i < set_.size(); i++) + set_[i] = static_cast(0); +} + + +template +bool BoolSet::get(unsigned int i) const { + assert(i < size_ && i >= 0); + unsigned int n = i / (sizeof(T)*8); + unsigned int r = i % (sizeof(T)*8); + + T t = static_cast(1) << r; + t = set_[n] & t; + if (t) + return true; + else + return false; +} + + +template +unsigned int BoolSet::num_elem() const { + unsigned int n = size_; + unsigned int c = 0; + unsigned int p = 0; + while (n != 0) { + unsigned int m; + if (n >= sizeof(T)*8) { + m = sizeof(T)*8; + n -= sizeof(T)*8; + } + else { + m = n; + n = 0; + } + + T v = set_[p++]; + if (v != static_cast(0)) { + for (unsigned int i = 0; i < m; i++) { + if (v & static_cast(1)) + c++; + v >>= 1; + } + } + } + + return c; +} + + +template +bool BoolSet::imply(const BoolSet &b) const { + if (size_ >= b.size_) { + for (unsigned int i = 0; i < b.set_.size(); i++) + if ((set_[i] & b.set_[i]) != b.set_[i]) + return false; + } + else { + for (unsigned int i = 0; i < set_.size(); i++) + if ((set_[i] & b.set_[i]) != b.set_[i]) + return false; + for (unsigned int i = set_.size(); i < b.set_.size(); i++) + if (b.set_[i] != static_cast(0)) + return false; + } + + return true; +} + + +template +bool BoolSet::empty() const { + for (int i = 0; i < set_.size(); i++) + if (set_[i] != static_cast(0)) + return false; + + return true; +} + + +template +void BoolSet::dump() const { + int j = 1; + for (unsigned int i = 0; i < size(); i++) { + if (get(i)) + std::cout << '1'; + else + std::cout << '0'; + if (j%10 == 0 && i != size() - 1) { + std::cout << ' '; + j = 1; + } + else + j++; + } + std::cout << std::endl; + std::cout.flush(); +} + + +template +BoolSet operator|(const BoolSet &a, const BoolSet &b) { + if (a.size_ >= b.size_) { + BoolSet c = a; + for (unsigned int i = 0; i < b.set_.size(); i++) + c.set_[i] |= b.set_[i]; + return c; + } + else { + BoolSet c = b; + for (unsigned int i = 0; i < a.set_.size(); i++) + c.set_[i] |= a.set_[i]; + return c; + } +} + + +template +BoolSet operator&(const BoolSet &a, const BoolSet &b) { + if (a.size_ >= b.size_) { + BoolSet c = a; + for (unsigned int i = 0; i < b.set_.size(); i++) + c.set_[i] &= b.set_[i]; + for (unsigned int i = b.set_.size(); i < a.set_.size(); i++) + c.set_[i] = static_cast(0); + return c; + } + else { + BoolSet c = b; + for (unsigned int i = 0; i < a.set_.size(); i++) + c.set_[i] &= a.set_[i]; + for (unsigned int i = a.set_.size(); i < b.set_.size(); i++) + c.set_[i] = static_cast(0); + return c; + } +} + + +template +BoolSet operator-(const BoolSet &a, const BoolSet &b) { + BoolSet c(a.size_); + + int sz = a.set_.size(); + if (sz > b.set_.size()) + sz = b.set_.size(); + for (int i = 0; i < sz; i++) + c.set_[i] = a.set_[i] ^ (a.set_[i] & b.set_[i]); + for (int i = sz; i < a.set_.size(); i++) + c.set_[i] = a.set_[i]; + + return c; +} + + +template +BoolSet operator~(const BoolSet &b) { + unsigned int r = b.size_ % (sizeof(T)*8); + BoolSet a(b.size_); + for (unsigned int i = 0; i < b.set_.size(); i++) + a.set_[i] = ~b.set_[i]; + + if (r != 0) { + T t = static_cast(1); + for (unsigned int i = 1; i < r; i++) + t = (t << 1) | static_cast(1); + a.set_[a.set_.size()-1] &= t; + } + return a; +} + + +template +bool operator==(const BoolSet &a, const BoolSet &b) { + return (a.size_ == b.size_) && (a.set_ == b.set_); +} + + +template +bool operator!=(const BoolSet &a, const BoolSet &b) { + return !(a == b); +} + + + +template +BoolSet & BoolSet::operator|=(const BoolSet &b) { + *this = *this | b; + return *this; +} + + +template +BoolSet & BoolSet::operator&=(const BoolSet &b) { + *this = *this & b; + return *this; +} + + +template +BoolSet & BoolSet::operator-=(const BoolSet &b) { + *this = *this - b; + return *this; +} + + +template +std::ostream& operator<<(std::ostream &os, const BoolSet &b) { + os << '{'; + for (typename BoolSet::const_iterator i = b.begin(); i != b.end(); i++) { + os << *i; + if (i+1 != b.end()) + os << ','; + } + os << '}'; + + return os; +} + + +template +bool operator<(const BoolSet &a, const BoolSet &b) { + unsigned int t1, t2; + t1 = a.num_elem(); + t2 = b.num_elem(); + if (t1 < t2) + return true; + else if (t1 > t2) + return false; + else { + t1 = a.size(); + t2 = b.size(); + if (t1 < t2) + return true; + else if (t1 > t2) + return false; + else + for (unsigned int i = 0; i < a.set_.size(); i++) + if (a.set_[i] < b.set_[i]) + return true; + } + return false; +} + + +// +// iterator for BoolSet +// + +template +typename BoolSet::iterator BoolSet::begin() { + typename BoolSet::iterator it(this, 0); + if (size_ == 0) + return it; + else if (set_[0] & static_cast(1)) + return it; + else + return ++it; +} + + +template +typename BoolSet::iterator BoolSet::end() { + return typename BoolSet::iterator(this, size_); +} + + +template +typename BoolSet::const_iterator BoolSet::begin() const { + typename BoolSet::const_iterator it(this, 0); + if (size_ == 0) + return it; + else if (set_[0] & static_cast(1)) + return it; + else + return ++it; +} + + +template +typename BoolSet::const_iterator BoolSet::end() const { + return typename BoolSet::const_iterator(this, size_); +} + + +template +class BoolSet::iterator: public std::iterator { +protected: + BoolSet *s_; + unsigned int pos_; + +protected: + iterator(BoolSet *s, unsigned int pos) { s_ = s; pos_ = pos; } + +public: + ~iterator() {} + + typename BoolSet::iterator &operator++(); + typename BoolSet::iterator operator++(int); + typename BoolSet::iterator operator+(int) const; + unsigned int operator*() const; + bool operator==(const BoolSet::iterator &) const; + bool operator!=(const BoolSet::iterator &) const; + operator typename BoolSet::const_iterator(); + + friend class BoolSet; +}; + + +template +typename BoolSet::iterator &BoolSet::iterator::operator++() { + assert(pos_ < s_->size_); + + pos_++; + unsigned int n = pos_ / (sizeof(T)*8); + unsigned int r = pos_ % (sizeof(T)*8); + while (pos_ < s_->size_) { + if (s_->set_[n] == static_cast(0)) { + pos_ += sizeof(T)*8-r; + n++; + r = 0; + if (pos_ >= s_->size_) + break; + } + + if (r == 0) { + while (pos_ < s_->size_) { + if (s_->set_[n] == static_cast(0)) { + pos_ += sizeof(T)*8; + n++; + } + else + break; + } + if (pos_ >= s_->size_) + break; + } + + for (unsigned int i = r; i < sizeof(T)*8; i++) + if (s_->set_[n] & static_cast(1) << i) { + pos_ = pos_+i-r; + return *this; + } + + pos_ += sizeof(T)*8-r; + n++; + r = 0; + } + + pos_ = s_->size_; + return *this; +} + + +template +typename BoolSet::iterator BoolSet::iterator::operator++(int) { + typename BoolSet::iterator it(*this); + ++(*this); + return it; +} + + +template +typename BoolSet::iterator BoolSet::iterator::operator+(int n) const { + assert(n >= 0); + typename BoolSet::iterator it(*this); + while (n > 0) { + ++it; + --n; + } + return it; +} + + +template +unsigned int BoolSet::iterator::operator*() const { + assert(pos_ < s_->size_); + return pos_; +} + + +template +bool BoolSet::iterator::operator==(const BoolSet::iterator &other) const { + return s_ == other.s_ && pos_ == other.pos_; +} + + +template +bool BoolSet::iterator::operator!=(const BoolSet::iterator &other) const { + return !((*this) == other); +} + + +template +BoolSet::iterator::operator typename BoolSet::const_iterator() { + return BoolSet::const_iterator(s_, pos_); +} + + +template +class BoolSet::const_iterator: public std::iterator { +protected: + const BoolSet *s_; + unsigned int pos_; + +protected: + const_iterator(const BoolSet *s, unsigned int pos) { s_ = s; pos_ = pos; } + +public: + ~const_iterator() {} + + typename BoolSet::const_iterator &operator++(); + typename BoolSet::const_iterator operator++(int); + typename BoolSet::const_iterator operator+(int) const; + unsigned int operator*() const; + bool operator==(const BoolSet::const_iterator &) const; + bool operator!=(const BoolSet::const_iterator &) const; + + friend class BoolSet; +}; + + +template +typename BoolSet::const_iterator &BoolSet::const_iterator::operator++() { + assert(pos_ < s_->size_); + + pos_++; + unsigned int n = pos_ / (sizeof(T)*8); + unsigned int r = pos_ % (sizeof(T)*8); + while (pos_ < s_->size_) { + if (s_->set_[n] == static_cast(0)) { + pos_ += sizeof(T)*8-r; + n++; + r = 0; + if (pos_ >= s_->size_) + break; + } + + if (r == 0) { + while (pos_ < s_->size_) { + if (s_->set_[n] == static_cast(0)) { + pos_ += sizeof(T)*8; + n++; + } + else + break; + } + if (pos_ >= s_->size_) + break; + } + + for (unsigned int i = r; i < sizeof(T)*8; i++) + if (s_->set_[n] & static_cast(1) << i) { + pos_ = pos_+i-r; + return *this; + } + + pos_ += sizeof(T)*8-r; + n++; + r = 0; + } + + pos_ = s_->size_; + return *this; +} + + +template +typename BoolSet::const_iterator BoolSet::const_iterator::operator++(int) { + typename BoolSet::const_iterator it(*this); + ++(*this); + return it; +} + + +template +typename BoolSet::const_iterator BoolSet::const_iterator::operator+(int n) const { + assert(n >= 0); + typename BoolSet::const_iterator it(*this); + while (n > 0) { + ++it; + --n; + } + return it; +} + + +template +unsigned int BoolSet::const_iterator::operator*() const { + assert(pos_ < s_->size_); + return pos_; +} + + +template +bool BoolSet::const_iterator::operator==(const BoolSet::const_iterator &other) const { + return s_ == other.s_ && pos_ == other.pos_; +} + + +template +bool BoolSet::const_iterator::operator!=(const BoolSet::const_iterator &other) const { + return !((*this) == other); +} + +} + +#endif diff --git a/lib/omega/include/basic/Collection.h b/lib/omega/include/basic/Collection.h new file mode 100644 index 0000000..80ddf48 --- /dev/null +++ b/lib/omega/include/basic/Collection.h @@ -0,0 +1,43 @@ +#if !defined Already_Included_Collection +#define Already_Included_Collection + +namespace omega { + +template class Iterator; +template class Any_Iterator; + + +//! protocol for any kind of collection +template class Collection { +public: + virtual Iterator *new_iterator() = 0; + virtual Any_Iterator any_iterator() { return Any_Iterator(new_iterator()); } + + virtual int size() const = 0; +}; + + +/*! + * protocol for collections whose elements are ordered + * by the way they are entered into the collection, and + * whose elements can be accessed by "index" + * + * note that the implementation need not be a linked list + */ +template class Sequence : public Collection { +public: + virtual const T &operator[](int) const = 0; + virtual T &operator[](int) = 0; + + /*! Y in X --> X[X.index(Y)] == Y */ + virtual int index(const T &) const = 0; }; + +} // namespace + +#define instantiate_Collection(T) template class Collection; \ + instantiate_Any_Iterator(T) +#define instantiate_Sequence(T) template class Sequence; \ + instantiate_Collection(T) + +#endif + diff --git a/lib/omega/include/basic/Collections.h b/lib/omega/include/basic/Collections.h new file mode 100644 index 0000000..1e68031 --- /dev/null +++ b/lib/omega/include/basic/Collections.h @@ -0,0 +1,12 @@ +#if !defined Already_Included_Collections +#define Already_Included_Collections + +#include +#include +#include +#include +#include +#include + +#endif + diff --git a/lib/omega/include/basic/ConstString.h b/lib/omega/include/basic/ConstString.h new file mode 100644 index 0000000..f149c9d --- /dev/null +++ b/lib/omega/include/basic/ConstString.h @@ -0,0 +1,57 @@ +#if ! defined _Const_String_h +#define _Const_String_h 1 + +#include + +namespace omega { + +// should be inside Const_String, but I can't get it to +// compile the hashTable when it is: hashTable can't be +// global, but if it and its size are static to Const_String, +// the compiler still doesn't seem to like the definition, +// or the declaration either for that matter. +class ConstStringRep { +public: + const char *name; + int count; + ConstStringRep *nextInBucket; + ConstStringRep(const char *t); +}; + +class Const_String { +private: + ConstStringRep *rep; + void buildRep(const char *t); + +public: + Const_String(); + Const_String(const char* t); + Const_String(const std::string &s); + Const_String(const Const_String & t) {rep = t.rep;} + + operator int() const; + int null() const; + + operator const char*() const; + operator std::string() const; + int operator++(int); + int operator++(); + int operator--(int); + int operator--(); + friend int operator==(const Const_String &x, const Const_String &y); + friend int operator!=(const Const_String &x, const Const_String &y); + friend int operator<(const Const_String &x, const Const_String &y); + friend int operator >(const Const_String &x, const Const_String &y); + +}; + +#if defined SCREWED_UP_CASTING_RULES +static int operator==(const Const_String &x, const char *y) +{ return x == (Const_String) y; } +static int operator!=(const Const_String &x, const char *y) +{ return x != (Const_String) y; } +#endif + +} // namespace + +#endif diff --git a/lib/omega/include/basic/DynamicArray.h b/lib/omega/include/basic/DynamicArray.h new file mode 100644 index 0000000..08f8b91 --- /dev/null +++ b/lib/omega/include/basic/DynamicArray.h @@ -0,0 +1,318 @@ +#ifndef Already_Included_DynamicArray +#define Already_Included_DynamicArray + +#include + +namespace omega { + +template class DynamicArray2; +template class DynamicArray3; +template class DynamicArray4; + +template class DynamicArray + { + public: + DynamicArray(DynamicArray &D); + ~DynamicArray(); + + protected: + DynamicArray(); + bool partial; + int *bounds; + T *elements; + + void do_constr(); + void do_destruct(); + }; + + +template class DynamicArray1 : public DynamicArray + { + public: + DynamicArray1(const char *s0 = 0); + DynamicArray1(int d0); + void resize(int d0); + T& operator[](int d); + + friend class DynamicArray2; + + private: + void do_construct(int d0); + }; + + +template class DynamicArray2 : public DynamicArray + { + public: + DynamicArray2(const char *s0 = 0, const char *s1 = 0); + DynamicArray2(int d0, int d1); + void resize(int d0, int d1); + DynamicArray1 operator[](int d); + + friend class DynamicArray3; + + private: + void do_construct(int d0, int d1); + }; + + +template class DynamicArray3 : public DynamicArray + { + public: + DynamicArray3(const char *s0 = 0, const char *s1 = 0, const char *s2 = 0); + DynamicArray3(int d0, int d1, int d2); + void resize(int d0, int d1, int d2); + DynamicArray2 operator[](int d); + + friend class DynamicArray4; + + private: + void do_construct(int d0, int d1, int d2); + }; + +template class DynamicArray4 : public DynamicArray + { + public: + DynamicArray4(const char *s0 = 0, const char *s1 = 0, const char *s2 = 0, const char *s3 = 0); + DynamicArray4(int d0, int d1, int d2, int d3); + void resize(int d0, int d1, int d2, int d3); + DynamicArray3 operator[](int d); + + private: + void do_construct(int d0, int d1, int d2, int d3); + }; + +} // namespace + +#define instantiate_DynamicArray1(T) template class DynamicArray1; \ + template class DynamicArray; + +#define instantiate_DynamicArray2(T) template class DynamicArray2; \ + template class DynamicArray; \ + instantiate_DynamicArray1(T); + +#define instantiate_DynamicArray3(T) template class DynamicArray3; \ + template class DynamicArray; \ + instantiate_DynamicArray2(T); + +#define instantiate_DynamicArray4(T) template class DynamicArray4; \ + template class DynamicArray; \ + instantiate_DynamicArray3(T); + +namespace omega { + +template void DynamicArray::do_constr() + { +// #if ! defined SHUT_UP_ABOUT_STATEMENT_WITH_NO_EFFECT_IN_DYNAMIC_ARRAY_CREATION +// assert(d > 0); +// #endif + bounds = 0; + elements = 0; + partial = false; + } + + +template void DynamicArray1::do_construct(int d0) + { + this->bounds = new int[1]; + this->bounds[0] = d0; + this->elements = new T [d0]; + this->partial = false; + } + +template void DynamicArray2::do_construct(int d0, int d1) + { + this->bounds = new int[2]; + this->bounds[0] = d0; + this->bounds[1] = d1; + this->elements = new T [d0 * d1]; + this->partial = false; + } + +template void DynamicArray3::do_construct(int d0,int d1,int d2) + { + this->bounds = new int[3]; + this->bounds[0] = d0; + this->bounds[1] = d1; + this->bounds[2] = d2; + this->elements = new T [d0 * d1 * d2]; + this->partial = false; + } + +template void DynamicArray4::do_construct(int d0,int d1,int d2,int d3) + { + this->bounds = new int[4]; + this->bounds[0] = d0; + this->bounds[1] = d1; + this->bounds[2] = d2; + this->bounds[3] = d3; + this->elements = new T [d0 * d1 * d2 * d3]; + this->partial = false; + } + +template DynamicArray::DynamicArray() + { + do_constr(); + } + +template DynamicArray1::DynamicArray1(const char *) + { + this->do_constr(); + } + +template DynamicArray2::DynamicArray2(const char *,const char *) + { + this->do_constr(); + } + +template DynamicArray3::DynamicArray3(const char *,const char *,const char *) + { + this->do_constr(); + } + +template DynamicArray4::DynamicArray4(const char *,const char *,const char *,const char *) + { + this->do_constr(); + } + +template DynamicArray1::DynamicArray1(int d0) + { + do_construct(d0); + } + +template DynamicArray2::DynamicArray2(int d0, int d1) + { + do_construct(d0, d1); + } + +template DynamicArray3::DynamicArray3(int d0,int d1,int d2) + { + do_construct(d0, d1, d2); + } + +template DynamicArray4::DynamicArray4(int d0,int d1,int d2,int d3) + { + do_construct(d0, d1, d2, d3); + } + + +template void DynamicArray::do_destruct() + { + if (! partial) + { + delete [] bounds; + delete [] elements; + } + } + + +template DynamicArray::~DynamicArray() + { + do_destruct(); + } + + +template void DynamicArray1::resize(int d0) + { + assert(!this->partial); + this->do_destruct(); + if (d0 == 0) + this->do_constr(); + else + do_construct(d0); + } + +template void DynamicArray2::resize(int d0, int d1) + { + assert(!this->partial); + this->do_destruct(); + if (d0 == 0 && d1 == 0) + this->do_constr(); + else + do_construct(d0, d1); + } + +template void DynamicArray3::resize(int d0, int d1, int d2) + { + assert(!this->partial); + this->do_destruct(); + if (d0 == 0 && d1 == 0 && d2 == 0) + this->do_constr(); + else + do_construct(d0, d1, d2); + } + +template void DynamicArray4::resize(int d0, int d1, int d2, int d3) + { + assert(!this->partial); + this->do_destruct(); + if (d0 == 0 && d1 == 0 && d2 == 0 && d3 == 0) + this->do_constr(); + else + do_construct(d0, d1, d2, d3); + } + + +template T& DynamicArray1::operator[](int d0) + { +#if !defined (NDEBUG) + assert(this->elements != 0 && "Trying to dereference undefined array"); + assert(0 <= d0 && d0 < this->bounds[0] && "Array subscript out of bounds"); +#endif + + return this->elements[d0]; + } + +template DynamicArray1 DynamicArray2::operator[](int d0) + { +#if !defined (NDEBUG) + assert(this->elements != 0 && "Trying to dereference undefined array"); + assert(0 <= d0 && d0 < this->bounds[0] && "Array subscript out of bounds"); +#endif + + DynamicArray1 result; + result.bounds = this->bounds+1; + result.elements = this->elements + this->bounds[1] * d0; + result.partial = true; + return result; + } + +template DynamicArray2 DynamicArray3::operator[](int d0) + { +#if !defined (NDEBUG) + assert(this->elements != 0 && "Trying to dereference undefined array"); + assert(0 <= d0 && d0 < this->bounds[0] && "Array subscript out of bounds"); +#endif + DynamicArray2 result; + result.bounds = this->bounds+1; + result.elements = this->elements + this->bounds[1] * this->bounds[2] * d0; + result.partial = true; + return result; + } + +template DynamicArray3 DynamicArray4::operator[](int d0) + { +#if !defined (NDEBUG) + assert(this->elements != 0 && "Trying to dereference undefined array"); + assert(0 <= d0 && d0 < this->bounds[0] && "Array subscript out of bounds"); +#endif + + DynamicArray3 result; + result.bounds = this->bounds+1; + result.elements = this->elements + this->bounds[1] * this->bounds[2] * this->bounds[3] * d0; + result.partial = true; + return result; + } + + +template + DynamicArray::DynamicArray(DynamicArray &D) + { + assert(D.elements != 0 && "Trying to copy an undefined array"); + partial = true; + bounds = D.bounds; + elements = D.elements; + } + +} // namespace +#endif diff --git a/lib/omega/include/basic/Iterator.h b/lib/omega/include/basic/Iterator.h new file mode 100644 index 0000000..f62874c --- /dev/null +++ b/lib/omega/include/basic/Iterator.h @@ -0,0 +1,129 @@ +/* + * Base classes for iterators, generators + * + * These don't really work yet for constant collections. + * I'm not sure how to make that happen. + */ + +#if ! defined _Iterator_h +#define _Iterator_h 1 + +#include + +namespace omega { + +#define foreach(x,T,S,A) do {for (omega::Any_Iterator __P_##x = (S).any_iterator();__P_##x;__P_##x++) {T & x = *__P_##x; A;}} while (0) + +#define foreachSeparated(x,T,S,A,B) do {for (omega::Any_Iterator __P_##x = (S).any_iterator();__P_##x;) {T & x = *__P_##x; A; __P_##x++; if (__P_##x) B;}} while (0) + +/*! + * \brief Abstract base class Iterator + * + * Supports two styles of iteration: + * ~~~ + * for ( ... initialize i (typically i = collection) ... ; i ; i++ ) + * operate_on(*i) + * ~~~ + * or + * ~~~ + * for ( ... initialize i ... ; i.live() ; i.next() ) + * operate_on(i.curr()) + * ~~~ + * **IF THE COLLECTION IS CHANGED, THE ITERATOR IS NO LONGER VALID** + * + * For collections that are not "Sequence"s, the order in + * which the elements are returned may not be consistent. + */ +template class Iterator { +public: + virtual const T & operator*() const = 0; + virtual T & operator*() = 0; + + virtual void operator++(int) = 0; + virtual void operator++() = 0; + + virtual bool live() const = 0; + operator bool() const { return live(); } + + const T & curr() const { return *(*this); } + T & curr() { return *(*this); } + void next() { (*this)++; } + + virtual Iterator *new_copy() const = 0; + virtual ~Iterator() {} +}; + + +//! A generator is like an iterator but it gives out values +/*! Values may or may not exist in some writable collection */ +template class Generator { +public: + virtual T operator*() const = 0; + + virtual void operator++(int) = 0; + virtual void operator++() = 0; + + virtual int live() const = 0; + operator int() const { return live(); } + + const T curr() const { return *(*this); } + T curr() { return *(*this); } + void next() { (*this)++; } +}; + + + +//! Delegate to any kind of iterator (on the heap) +/*! + * * If created via a reference, become a copy of the iterator + * * If created via a pointer, manipulate that pointer and free *p when this dies + * + * Mostly useful for Collection::iterator `Iterator::Iterator(Collection)` + */ +template class Any_Iterator : public Iterator { +public: + Any_Iterator(Collection &c); + Any_Iterator(const Iterator &i); // copy of i + + virtual ~Any_Iterator() { delete me; } + + Any_Iterator &operator=(const Any_Iterator &rhs) + { delete me; me = rhs.me->new_copy(); return *this; } + + const T & operator*() const { return *(*me); } + T & operator*() { return *(*me); } + void operator++(int) { (*me)++; } + void operator++() { ++(*me); } + bool live() const { return (*me).live(); } + + Iterator *new_copy() const { return new Any_Iterator((*me).new_copy()); } + +private: + //! take over *p, *p MUST BE ON THE HEAP + Any_Iterator(Iterator *p) { me = p; } + friend class Collection; +/* + * // Couldn't make this work with g++258 + * friend Any_Iterator Collection::any_iterator(); + */ + Iterator *me; +}; + +template inline Any_Iterator::Any_Iterator(Collection &c) + { + me = c.new_iterator(); + } + +template inline Any_Iterator::Any_Iterator(const Iterator &i) + { + me = i.new_copy(); + } + +} // namespace + +#define instantiate_Iterator(T) template class Iterator; +#define instantiate_Generator(T) template class Generator; +#define instantiate_Any_Iterator(T) template class Any_Iterator; \ + instantiate_Iterator(T) + +#endif diff --git a/lib/omega/include/basic/Link.h b/lib/omega/include/basic/Link.h new file mode 100644 index 0000000..bdf169c --- /dev/null +++ b/lib/omega/include/basic/Link.h @@ -0,0 +1,97 @@ +#if ! defined _Link_h +#define _Link_h 1 + +#include +#include + +namespace omega { + +// By default, if ndebug is not set, do not do free list + +#if ! defined ListElementFreeList +#if ! defined NDEBUG || defined ASSERTIONS_ANYWAY +#define ListElementFreeList 0 +#else +#define ListElementFreeList 1 +#endif +#endif + +#if ListElementFreeList + // g++ 2.5.8 does not allow static data in template classes, so... + extern void *kludgy_List_Element_new(size_t size); + extern void kludgy_List_Element_delete(void *ptr, size_t size); +#endif +/*! + * \brief List_Element: one item in a list and the pointer to the next. + * + * Each such object should be pointed to by either exactly one + * other List_Element or by some other pointer(s), exactly one + * of which will delete the List_Element. + * ListElements should ONLY be allocated on the heap. + */ +template class List_Element { +public: +#if ListElementFreeList + void *operator new(size_t size) + { + return kludgy_List_Element_new(size); + } + void operator delete(void *ptr, size_t size) + { + kludgy_List_Element_delete(ptr, size); + } +#endif + + T head; + List_Element *tail; + + List_Element() { + tail = 0; + } + List_Element(T h, List_Element * t) { + head = h; + tail = t; + } + List_Element(const List_Element & L) { + head = L.head; + if (L.tail) tail = new List_Element(*L.tail); + else tail = 0; + } + List_Element & operator=(const List_Element &L) { + if (this != &L) { + head = L.head; + if (tail) delete tail; + if (L.tail) tail = new List_Element(*L.tail); + else tail = 0; + } + return *this; + } + virtual ~List_Element() { // virtual ensures 2nd arg of delete is right + delete tail; + } +}; + + + +template class List_Element_Iterator : public Iterator { +public: + List_Element_Iterator(List_Element* j) { i = j; } + virtual const T & operator*() const { return i->head; } + virtual T & operator*() { return i->head; } + virtual void operator++(int) { i = i->tail; } + virtual void operator++() { i = i->tail; } + virtual bool live() const { return i != 0; } + Iterator * new_copy() const { return new List_Element_Iterator(i);} + +protected: + List_Element *i; +}; + +} // namespace + +#define instantiate_Only_List_Element(T) template class List_Element; \ + template class List_Element_Iterator; +#define instantiate_List_Element(T) instantiate_Only_List_Element(T)\ + instantiate_Collection(T) + +#endif diff --git a/lib/omega/include/basic/List.h b/lib/omega/include/basic/List.h new file mode 100644 index 0000000..28ab1d5 --- /dev/null +++ b/lib/omega/include/basic/List.h @@ -0,0 +1,233 @@ +#if ! defined _List_h +#define _List_h 1 + +/* + * Linked lists with an interface like a bit of libg++'s SLList class + */ +#include // for NULL +#include +#include +#include +#include + +namespace omega { + +template class List_Iterator; + +// +// indexing of Lists starts at 1, index == 0 means not there +// + +template class List : public Sequence { +public: + List(const List &l) + { contents = l.contents ? new List_Element(*l.contents) : 0; } + List() { contents = 0; } + virtual ~List() { delete contents; } + + Iterator *new_iterator(); + const T &operator[](int) const; + T &operator[](int); + + int index(const T &) const; + + int size() const; + int length() const { return size(); } + bool empty() const { return size() == 0; } + + T &front() const; + +// insertion/deletion on a list invalidates any iterators +// that are on/after the element added/removed + + T remove_front(); + + void prepend(const T &item); + void append(const T &item); + void ins_after(List_Iterator i, const T &item); + + void del_front(); + void del_after(List_Iterator i); + void clear(); + + void join(List &consumed); + +private: + friend class List_Iterator; + List_Element **end() + { + List_Element **e = &contents; + while (*e) + e = &((*e)->tail); + return e; + } + + List_Element *contents; +}; + + +template class List_Iterator : public List_Element_Iterator { +public: + List_Iterator(List &l); + List_Iterator(const List &l); + List_Iterator(); +private: + List_Element &element() { return *List_Element_Iterator::i; } ; + friend class List; +}; + +} // namespace + +#define instantiate_List(T) template class List; \ + template class List_Iterator; \ + instantiate_Only_List_Element(T) \ + instantiate_Sequence(T) + +namespace omega { + +template List_Iterator::List_Iterator(List &l) +: List_Element_Iterator(l.contents) {} + +template List_Iterator::List_Iterator(const List &l) +: List_Element_Iterator(l.contents) {} + +template List_Iterator::List_Iterator() +: List_Element_Iterator(0) {} + +template Iterator *List::new_iterator() +{ + return new List_Iterator(*this); +} + +template const T &List::operator[](int i) const +{ + assert(i > 0 && "Subscript out of bounds"); + List_Iterator p(*this); + + while(--i > 0 && p) + p++; + + if (p) + return *p; + else + return *((T *)0); +} + +template T &List::operator[](int i) +{ + assert(i > 0 && "Subscript out of bounds"); + List_Iterator p(*this); + + while(--i > 0 && p) + p++; + + if (p) + return *p; + else + return *((T *)0); +} + +template int List::index(const T &item) const +{ + List_Iterator p(*this); + int i = 1; + + while(p && *p != item) + { + p++; + i++; + } + + if (p) + return i; + else + return 0; +} + +template int List::size() const + { + int i = 0; + List_Element * p = contents; + while (p) + { + p = p->tail; + i++; + } + return i; + } + +template T &List::front() const + { + return contents->head; + } + +template T List::remove_front() + { + List_Element *frunt = contents; + contents = contents->tail; + T fruntT = frunt->head; + frunt->tail = 0; + delete frunt; + return fruntT; + } + +template void List::prepend(const T &item) + { + contents = new List_Element(item, contents); + } + + +template void List::append(const T &item) + { + *(end()) = new List_Element(item, 0); + } + +template void List::ins_after(List_Iterator i, + const T &item) + { +#if ! defined NDEBUG + for (List_Element *e = contents; e != &(i.element()); e=e->tail) + { + assert(e); + } +#endif + i.element().tail = new List_Element(item, i.element().tail); + } + +template void List::del_front() + { + List_Element *e = contents; + contents = contents->tail; + e->tail = 0; + delete e; + } + +template void List::del_after(List_Iterator i) + { +#if ! defined NDEBUG + for (List_Element *e0 = contents; e0 != &(i.element()); e0=e0->tail) + { + assert(e0); + } +#endif + List_Element *e = i.element().tail; + i.element().tail = e->tail; + e->tail = 0; + delete e; + } + +template void List::clear() + { + delete contents; + contents = 0; + } + +template void List::join(List &consumed) + { + List_Element *e = consumed.contents; + consumed.contents = 0; + *(end()) = e; + } + +} // namespace +#endif diff --git a/lib/omega/include/basic/Map.h b/lib/omega/include/basic/Map.h new file mode 100644 index 0000000..25a116d --- /dev/null +++ b/lib/omega/include/basic/Map.h @@ -0,0 +1,127 @@ +#if ! defined _Map_h +#define _Map_h 1 + +#include +#include // for NULL + +namespace omega { + +#define foreach_map(k,K,v,V,M,A) {for (omega::MapElementIterator __M_##k = (M).iterator();__M_##k;__M_##k++) {K & k = *__M_##k; V & v = __M_##k.value(); A;}} + +template class MapElement { +public: + K k; + V v; + MapElement *tail; + MapElement(const MapElement&); + MapElement() {} + MapElement & operator=(const MapElement&); + ~MapElement() { delete tail; } +}; + +template class MapElementIterator { +public: + MapElementIterator(MapElement* j) { i = j;} + virtual const K & operator*() const { return i->k; } + virtual K & operator*() { return i->k;} + virtual const V & value() const { return i->v; } + virtual V & value() { return i->v; } + virtual void operator++(int) { i = i->tail; } + virtual void operator++() { i = i->tail; } + virtual bool live() const { return i != NULL; } + operator bool() const { return live(); } +protected: +MapElement *i; +}; + +template class Map { +public: +#if ! defined linux + Map(const V &default_value); +#else + // work around for '386 g++ on Linux + Map(V default_value); +#endif + ~Map(); + MapElementIterator iterator() + {return MapElementIterator(contents);} + int empty() const {return contents == NULL;} + V operator()(K) const; + V& operator[](K); +private: + MapElement * contents; + V _default_value; +}; + +} // namespace + +#define instantiate_Map(T1,T2) template class Map; \ + template class MapElement; \ + template class MapElementIterator; +#define instantiate_MapElement(T1,T2) instantiate_Map(T1,T2) +#define instantiate_MapElementIterator(T1,T2) instantiate_Map(T1,T2) + +namespace omega { + +template MapElement:: MapElement(const MapElement& M) { + if (M.tail) tail = new MapElement(*M.tail); + else tail = 0; + k = M.k; + v = M.v; + } + +template MapElement & + MapElement:: operator=(const MapElement& M) { + if (this != &M) { + if (tail) delete tail; + if (M.tail) tail = new MapElement(*M.tail); + else tail = 0; + k = M.k; + v = M.v; + } + return *this; + } + + + + +#if ! defined linux +template Map ::Map(const V &default_value) +#else +template Map ::Map(V default_value) +#endif + : _default_value(default_value) + { + contents = 0; + } + +template Map ::~Map() + { + delete contents; + } + +template V Map::operator()(K k) const { + MapElement * P = contents; + while (P) { + if (P->k == k) return P->v; + P = P->tail; + }; + return _default_value; + } + +template V & Map::operator[](K k) { + MapElement * P = contents; + while (P) { + if (P->k == k) return P->v; + P = P->tail; + }; + P = new MapElement ; + P->k = k; + P->v = _default_value; + P->tail = contents; + contents = P; + return P->v; + } + +} // namespace +#endif diff --git a/lib/omega/include/basic/Section.h b/lib/omega/include/basic/Section.h new file mode 100644 index 0000000..7a4d241 --- /dev/null +++ b/lib/omega/include/basic/Section.h @@ -0,0 +1,138 @@ +#if ! defined _Section_h +#define _Section_h 1 +/* + Section of an existing collection viewed as a collection + */ + +#include +#include + +namespace omega { + +template class Section_Iterator; + +template class Section : public Sequence { +public: + Section(Sequence *, int start, int length); + + Iterator *new_iterator(); + + const T &operator[](int) const; + T &operator[](int); + + int index(const T &) const; + int size() const; + + friend class Section_Iterator; + +private: + Sequence *it; + int _start, _length; +}; + +template class Section_Iterator : public Iterator { +public: + Section_Iterator(Section &sec); + virtual ~Section_Iterator() { delete it; } + + const T & operator*() const { return *(*it); } + T & operator*() { return *(*it); } + + void operator++(int); + void operator++(); + + bool live() const; + Iterator *new_copy() const; + +private: + Section_Iterator(const Section_Iterator &si); + Iterator *it; + int remaining; +}; + +} // namespace + +#define instantiate_Section(T) template class Section; \ + template class Section_Iterator; \ + instantiate_Sequence(T) +#define instantiate_Section_Iterator(T) instantiate_Section(T) + + +namespace omega { + +template Section::Section(Sequence *s, int start, int length) + { + assert(s->size() >= start-1 + length); + it = s; + _start = start; + _length = length; + } + +template Iterator *Section::new_iterator() + { + return new Section_Iterator(*this); + } + +template const T &Section::operator[](int i) const + { + assert(1 <= i && i <= size()); + return (*it)[i+(_start-1)]; + } + +template T &Section::operator[](int i) + { + assert(1 <= i && i <= size()); + return (*it)[i+(_start-1)]; + } + +template int Section::index(const T &var) const + { + int i; + for (i=1; i<=size(); i++) + if ((*this)[i] == var) + return i; + return 0; + } + +template int Section::size() const + { + return _length; + } + + +template Section_Iterator::Section_Iterator(Section &sec) + { + it = sec.it->new_iterator(); + for (int i = 1; i < sec._start; i++) + (*it)++; + remaining = sec.size(); + } + + +template Section_Iterator::Section_Iterator(const Section_Iterator &si) : it(si.it), remaining(si.remaining) {} + + +template void Section_Iterator::operator++() + { this->operator++(0); } + +template void Section_Iterator::operator++(int) + { + if (remaining > 0) + { + (*it)++; + remaining--; + } + } + +template bool Section_Iterator::live() const + { + return (remaining > 0); + } + +template Iterator *Section_Iterator::new_copy() const + { + return new Section_Iterator(*this); + } + +} // namespace +#endif diff --git a/lib/omega/include/basic/SimpleList.h b/lib/omega/include/basic/SimpleList.h new file mode 100644 index 0000000..104390d --- /dev/null +++ b/lib/omega/include/basic/SimpleList.h @@ -0,0 +1,194 @@ +#if ! defined _Simple_List_h +#define _Simple_List_h 1 + +/* + * Linked lists with an interface like a bit of libg++'s SLSimple_List class + */ + +#include +#include +#include +#include + +namespace omega { + +#define Simple_List Omega_Simple_List +#define Simple_List_Iterator Omega_Simple_List_Iterator + +template class Simple_List_Iterator; + +// A TEMPORARY HACK - ERROR IF YOU TRY TO USE "INDEX" - FERD + +template class Simple_List : public Sequence { +public: + Simple_List(const Simple_List &l) + { contents = l.contents ? new List_Element(*l.contents) : 0; } + Simple_List() { contents = 0; } + virtual ~Simple_List() { delete contents; } + + Iterator *new_iterator(); + const T &operator[](int) const; + T &operator[](int); + + + int size() const; + int length() const { return size(); } + int empty() const { return size() == 0; } + + T &front() const; + +// insertion/deletion on a list invalidates any iterators +// that are on/after the element added/removed + + T remove_front(); + + void prepend(const T &item); + void append(const T &item); + + void del_front(); + void clear(); + + void join(Simple_List &consumed); + + int index(const T &) const { + assert(0&&"ILLEGAL SimpleList operation\n"); + return -1; + } + +private: + friend class Simple_List_Iterator; + List_Element **end() + { + List_Element **e = &contents; + while (*e) + e = &((*e)->tail); + return e; + } + + List_Element *contents; +}; + + +template class Simple_List_Iterator : public List_Element_Iterator { +public: + Simple_List_Iterator(Simple_List &l); + Simple_List_Iterator(const Simple_List &l); + Simple_List_Iterator(); +private: + List_Element &element() { return *this->i; } ; + friend class Simple_List; +}; + +} // namespace + +#define instantiate_Simple_List(T) template class Simple_List; \ + template class Simple_List_Iterator; \ + instantiate_Only_List_Element(T) \ + instantiate_Sequence(T) + +namespace omega { + +template Simple_List_Iterator::Simple_List_Iterator(Simple_List &l) +: List_Element_Iterator(l.contents) {} + +template Simple_List_Iterator::Simple_List_Iterator(const Simple_List &l) +: List_Element_Iterator(l.contents) {} + +template Simple_List_Iterator::Simple_List_Iterator() +: List_Element_Iterator(0) {} + +template Iterator *Simple_List::new_iterator() +{ + return new Simple_List_Iterator(*this); +} + +template const T &Simple_List::operator[](int i) const +{ + Simple_List_Iterator p(*this); + + while(--i > 0 && p) + p++; + + if (p) + return *p; + else + return *((T *)0); +} + +template T &Simple_List::operator[](int i) +{ + Simple_List_Iterator p(*this); + + while(--i > 0 && p) + p++; + + if (p) + return *p; + else + return *((T *)0); +} + + +template int Simple_List::size() const + { + int i = 0; + List_Element * p = contents; + while (p) + { + p = p->tail; + i++; + } + return i; + } + +template T &Simple_List::front() const + { + return contents->head; + } + +template T Simple_List::remove_front() + { + List_Element *frunt = contents; + contents = contents->tail; + T fruntT = frunt->head; + frunt->tail = 0; + delete frunt; + return fruntT; + } + +template void Simple_List::prepend(const T &item) + { + contents = new List_Element(item, contents); + } + + +template void Simple_List::append(const T &item) + { + *(end()) = new List_Element(item, 0); + } + + +template void Simple_List::del_front() + { + List_Element *e = contents; + contents = contents->tail; + e->tail = 0; + delete e; + } + + +template void Simple_List::clear() + { + delete contents; + contents = 0; + } + +template void Simple_List::join(Simple_List &consumed) + { + List_Element *e = consumed.contents; + consumed.contents = 0; + *(end()) = e; + } + +} // namespace +#endif diff --git a/lib/omega/include/basic/Tuple.h b/lib/omega/include/basic/Tuple.h new file mode 100644 index 0000000..e9aae84 --- /dev/null +++ b/lib/omega/include/basic/Tuple.h @@ -0,0 +1,336 @@ +#if !defined _Already_defined_tuple +#define _Already_defined_tuple + +#include + +#include +#include +#include + +namespace omega { + +template class Tuple_Iterator; + +// TUPLES ARE INDEXED STARTING AT 1 +// index\(i\) == 0 MEANS i IS NOT IN THE TUPLE + +template class Tuple : public Sequence { +public: + Tuple(); + Tuple(int size); + Tuple (const Tuple& tpl); + virtual ~Tuple(); + Tuple& operator=(const Tuple& tpl); + int size() const { return sz; } + int length() const { return sz; } + bool operator==(const Tuple &b) const; + void reallocate(const int); + void delete_last(); + void append(const Tuple &v); + void append(const T &v); + void join(Tuple &v); + void clear(); + int empty() const; + + Iterator *new_iterator(); + + virtual T &operator[](int index); + virtual const T &operator[](int index) const; + + int index(const T &) const; + + friend class Tuple_Iterator; + +private: + int prealloc_size(const int req_size) + { return max(req_size+prealloc_pad,prealloc_min); } + int realloc_size(const int oldsize) { return 2*oldsize; } + + + int sz, alloc_sz; // Number of elements, size of allocated array + int prealloc_min,prealloc_pad; // These should be static, but that + // causes portability prob. for initialization + +protected: + T * data; +}; + +template class Tuple_Iterator : public Iterator { +public: + Tuple_Iterator(const Tuple &tpl); + const T & operator*() const; + T & operator*(); + void set_position(const int req_pos); + void operator++(int); + void operator++(); + void operator--(int); + void operator--(); + void set_to_last(); + void set_to_first(); +// void set_position(const int req_pos); Don't do this, compiler bug + bool live() const; + Iterator *new_copy() const; + +private: + Tuple_Iterator(T * cr, T * frst, T *lst, int insz); + T * current, * lastptr, *firstptr; + int sz; +}; + +} // namespace + +#define instantiate_Tuple(T) template class Tuple; \ + template class Tuple_Iterator; \ + instantiate_Sequence(T) + +namespace omega { + +template T &Tuple::operator[](int index) + { + assert(1 <= index && index <= sz); return data[index-1]; + } + +template const T &Tuple::operator[](int index) const + { + assert(1 <= index && index <= sz); return data[index-1]; + } + + +template Tuple::~Tuple() + { + if (data) + delete [] data; + } + +template Tuple::Tuple() : sz(0), alloc_sz(0), + prealloc_min(20),prealloc_pad(5), data(0) +{ + // nothing needs be done + } + +template Tuple::Tuple(int size) : sz(size), + prealloc_min(20),prealloc_pad(5) +{ + if (sz > 0) + { + alloc_sz = prealloc_size(sz); + data = new T[alloc_sz]; + assert(alloc_sz >= sz); + //Need some handling for out of memory. + assert (data!=0); + } + else { + alloc_sz = 0; + data = 0; + } +} + + +template Tuple::Tuple(const Tuple& t) + : sz(t.sz), alloc_sz(t.alloc_sz), prealloc_min(20),prealloc_pad(5) +{ + if (sz > 0) { + data = new T[alloc_sz]; + assert (data!=0); + assert (alloc_sz >= sz); + for (int i=0; i Tuple& Tuple::operator=(const Tuple& t) +{ + if (this != &t) { // Delete this + if (data) + delete [] data; + sz = t.sz; + alloc_sz = t.alloc_sz; + assert(alloc_sz >= sz); + if (sz > 0) { // Copy old + data = new T[alloc_sz]; + assert (data!=0); + for (int i=0; i void Tuple::reallocate(const int req_size) +{ + if (alloc_sz >= req_size) { // if (sz >= req_size), does this. + sz = req_size; + return; + } + alloc_sz = prealloc_size(req_size); + T* tmp_data = new T[alloc_sz]; + for(int i=0;i= req_size); +} + +template void Tuple::delete_last() +{ +assert(sz > 0); +sz --; +} + +template void Tuple::append(const T &v) +{ + // Check if reallocation is necessary. + if (sz == 0) { // Empty Tuple + assert(alloc_sz >= 0); // May be nonzero for cleared tuple + + if(alloc_sz == 0) { // If it's > 1 no allocation is necessary + alloc_sz = prealloc_size(1); + data = new T[alloc_sz]; + } + assert (alloc_sz > 0 && data != 0); + } else { + if(sz == alloc_sz) { // Requires new allocation + alloc_sz = realloc_size(alloc_sz); + T * data_tmp = new T[alloc_sz]; + assert (data_tmp!=0); + assert (alloc_sz > sz); + for (int i=0; i= sz); + data[sz++] = v; +} + +template void Tuple::append(const Tuple& t) { + int old_sz = sz; + reallocate(t.size()+size()); + assert(alloc_sz >= sz); + for(int i=0; i void Tuple::join(Tuple& t) { + int old_sz = sz; + reallocate(t.size()+size()); + assert(alloc_sz >= sz); + for(int i=0; i void Tuple::clear() { if (sz) delete [] data; data = 0; alloc_sz = 0; sz = 0; } + +template int Tuple::empty() const { return (sz == 0); } + +template Iterator *Tuple::new_iterator() +{ + return new Tuple_Iterator(*this); +} + +template int Tuple::index(const T & var) const +/* returns index or 0 if var isn't in the tuple */ +{ + int i; + for (i=0; i bool Tuple::operator == (const Tuple& b) const +{ + int i; + if (sz != b.size()) return false; + for (i=0; i Tuple_Iterator::Tuple_Iterator(const Tuple &tpl) : +current(tpl.data), lastptr(tpl.data+tpl.sz-1), firstptr(tpl.data), sz(tpl.sz) +{ +} + +template Tuple_Iterator::Tuple_Iterator(T * cr, T *frst, T * lst, + int insz) + : current(cr), lastptr(lst), firstptr(frst), sz(insz) +{ +} + +template const T & Tuple_Iterator::operator*() const +{ + assert (current<=lastptr && current>=firstptr); + return *current; +} + +template T & Tuple_Iterator::operator*() +{ + assert (current<=lastptr && current >=firstptr); + return *current; +} + +template void Tuple_Iterator::operator++(int) +{ + current++; +} + +template void Tuple_Iterator::operator++() +{ + current++; +} + +template void Tuple_Iterator::operator--(int) +{ + current--; +} + +template void Tuple_Iterator::operator--() +{ + current--; +} + +template void Tuple_Iterator::set_to_last() +{ + current = lastptr; +} + +template void Tuple_Iterator::set_to_first() +{ + current = firstptr; +} + +template void Tuple_Iterator::set_position(const int req_pos) +{ + assert(req_pos <= sz && 1 <= req_pos); + current = firstptr + (req_pos - 1); +} + + +template bool Tuple_Iterator::live() const +{ + return (current !=0 && current<=lastptr && current >= firstptr); +} + +template Iterator *Tuple_Iterator::new_copy() const { + return new Tuple_Iterator(current, firstptr, lastptr, sz); +} + +} // namespace +#endif diff --git a/lib/omega/include/basic/omega_error.h b/lib/omega/include/basic/omega_error.h new file mode 100644 index 0000000..e342efb --- /dev/null +++ b/lib/omega/include/basic/omega_error.h @@ -0,0 +1,14 @@ +#ifndef OMEGA_ERROR_H +#define OMEGA_ERROR_H + +namespace omega { + +struct presburger_error: public std::runtime_error { + presburger_error(const std::string &msg): std::runtime_error("presburger error: " + msg) {} +}; + + + +} +#endif + diff --git a/lib/omega/include/basic/util.h b/lib/omega/include/basic/util.h new file mode 100644 index 0000000..4e807cd --- /dev/null +++ b/lib/omega/include/basic/util.h @@ -0,0 +1,263 @@ +#if ! defined Already_Included_Util +#define Already_Included_Util + +#include +#include +#include +#include +#include +#include + +namespace omega { + +#define LONG_LONG_COEF 1 + +#if LONG_LONG_COEF +#if defined BOGUS_LONG_DOUBLE_COEF +typedef long double coef_t; // type of coefficients +#define coef_fmt "%llf" +#define posInfinity (1e+24) +#define negInfinity (-1e+24) +#else +#ifdef WIN32 +typedef _int64 coef_t; // type of coefficients +#else +typedef long long coef_t; +#endif +#define coef_fmt "%lld" +#define posInfinity (0x7ffffffffffffffLL) +#define negInfinity (-0x7ffffffffffffffLL) +#endif +#else +typedef int coef_t; // type of coefficients +#define coef_fmt "%d" +#define posInfinity (0x7ffffff) +#define negInfinity (-0x7ffffff) +#endif + + +template inline const T& max(const T &x, const T &y) { + if (x >= y) return x; else return y; +} + + +template inline const T& max(const T &x, const T &y, const T &z) { + return max(x, max(y, z)); +} + +template inline const T& min(const T &x, const T &y) { + if (x <= y) return x; else return y; +} + +template inline const T& min(const T &x, const T &y, const T &z) { + return min(x, min(y, z)); +} + +template inline void set_max(T &m, const T &x) { + if (m < x) m = x; +} + +template inline void set_min(T &m, const T &x) { + if (m > x) m = x; +} + +/* template inline void swap(T &i, T &j) { */ +/* T tmp; */ +/* tmp = i; */ +/* i = j; */ +/* j = tmp; */ +/* } */ + +/* template inline T copy(const T &t) { return t; } */ + + +/* inline coef_t check_pos_mul(coef_t x, coef_t y) { */ +/* if (y >= 48051280 && y < posInfinity) */ +/* fprintf(stderr, "%d %d\n", x, y); */ +/* /\* #if !defined NDEBUG *\/ */ +/* /\* if (x != 0) *\/ */ +/* /\* assert(((MAXINT)/4) / x > y); *\/ */ +/* /\* #elif defined STILL_CHECK_MULT *\/ */ +/* /\* if (x != 0 && !(((MAXINT)/4) / x > y)) { *\/ */ +/* /\* assert(0&&"Integer overflow during multiplication (util.h)"); *\/ */ +/* /\* } *\/ */ +/* /\* #endif *\/ */ +/* #if !defined NDEBUG */ +/* if (x != 0 && y != 0) */ +/* assert(x*y > 0); */ +/* #elif defined STILL_CHECK_MULT */ +/* if (x != 0 && y != 0 && x*y < 0) */ +/* assert(0&&"Integer overflow during multiplication (util.h)"); */ +/* #endif */ +/* return x * y; */ +/* } */ + + +/* inline int */ +/* check_pos_mul(int x, int y) { */ +/* #if !defined NDEBUG */ +/* if (x != 0) */ +/* assert(((posInfinity)/4) / x > y); */ +/* #elif defined STILL_CHECK_MULT */ +/* if (x != 0 && !(((posInfinity)/4) / x > y)) { */ +/* assert(0&&"Integer overflow during multiplication (util.h)"); */ +/* } */ +/* #endif */ +/* return x * y; */ +/* } */ + +/* inline LONGLONG */ +/* check_pos_mul(LONGLONG x, LONGLONG y) { */ +/* #if !defined NDEBUG */ +/* if (x != 0) */ +/* assert(((posInfinity)/4) / x > y); */ +/* #elif defined STILL_CHECK_MULT */ +/* if (x != 0 && !(((posInfinity)/4) / x > y)) { */ +/* assert(0&&"Integer overflow during multiplication (util.h)"); */ +/* } */ +/* #endif */ +/* return x * y; */ +/* } */ + +/* inline LONGLONG abs(LONGLONG c) { return (c>=0?c:(-c)); } */ + +template inline T check_mul(const T &x, const T &y) { +#if defined NDEBUG && ! defined STILL_CHECK_MULT + return x*y; +#else + if (x == 0 || y == 0) + return 0; + + T z = x*y; + int sign_x = (x>0)?1:-1; + int sign_y = (y>0)?1:-1; + int sign_z = (z>0)?1:-1; + + if (sign_x * sign_y != sign_z) + throw std::overflow_error("coefficient multiply overflow"); + + return z; + + /* if (x > 0) { */ + /* if (y > 0) { */ + /* assert(x*y > 0); */ + /* } */ + /* else */ + /* assert(x*y < 0); */ + /* } */ + /* else { */ + /* if (y > 0) */ + /* assert(x*y < 0); */ + /* else */ + /* assert(x*y > 0); */ + /* } */ + /* return x*y; */ +#endif +} + +template inline T abs(const T &v) { + return (v >= static_cast(0))?v:-v; +} + +template inline T int_div(const T &a, const T &b) { + T result; + assert(b > 0); + if (a>0) result = a/b; + else result = -((-a+b-1)/b); + return result; +} + +template inline T int_mod(const T &a, const T &b) { + return a-b*int_div(a,b); +} + +template inline T int_mod_hat(const T &a, const T &b) { + T r; + assert(b > 0); + r = a-b*int_div(a,b); + if (r > -(r-b)) r -= b; + return r; +} + +template inline T gcd(T b, T a) {/* First argument is non-negative */ + assert(a >= 0); + assert(b >= 0); + if (b == 1) + return (1); + while (b != 0) { + T t = b; + b = a % b; + a = t; + } + return (a); +} + +template inline T lcm(T b, T a) { /* First argument is non-negative */ + assert(a >= 0); + assert(b >= 0); + return check_mul(a/gcd(a,b), b); +} + +template T square_root(const T &n, T precision = 1) { + T guess = 1; + + while (true) { + T next_guess = 0.5*(guess+n/guess); + if (abs(next_guess-guess) <= precision) + return next_guess; + else + guess = next_guess; + } +} + +template T factor(const T &n) { + assert(n >= 0); + if (n == 1) return 1; + + static int prime[30] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113}; + + if (n <= 113*113) { + for (int i = 0; i < 30; i++) + if (n % static_cast(prime[i]) == 0) + return static_cast(prime[i]); + + return n; + } + + T i = 1; + T k = 2; + T x = static_cast(rand())%n; + T y = x; + while(i < square_root(n, 1)) { + i++; + x = (x*x-1) % n; + T d = gcd(abs(y-x), n); + if(d != 1 && d != n) + return factor(d); + if(i == k) { + y = x; + k *= 2; + } + } + return n; +} + +/* #define implies(A,B) (A==(A&B)) */ + +template std::string to_string(const T &t) { + std::ostringstream ss; + ss << t; + return ss.str(); +} + +template T from_string(const std::string &s) { + std::istringstream ss(s); + ss.exceptions(std::ios::failbit); + T t; + ss >> t; + return t; +} + +} // namespace + +#endif diff --git a/lib/omega/include/omega.h b/lib/omega/include/omega.h new file mode 100644 index 0000000..8aa2c08 --- /dev/null +++ b/lib/omega/include/omega.h @@ -0,0 +1,71 @@ +/********************************************************************* + Old license information from the Omega Project, updated one can be + found in LICENSE file. + + Copyright (C) 1994-1996 by the Omega Project + All rights reserved. + + NOTICE: This software is provided ``as is'', without any + warranty, including any implied warranty for merchantability or + fitness for a particular purpose. Under no circumstances shall + the Omega Project or its agents be liable for any use of, misuse + of, or inability to use this software, including incidental and + consequential damages. + + License is hereby given to use, modify, and redistribute this + software, in whole or in part, for any purpose, commercial or + non-commercial, provided that the user agrees to the terms of this + copyright notice, including disclaimer of warranty, and provided + that this copyright notice, including disclaimer of warranty, is + preserved in the source code and documentation of anything derived + from this software. Any redistributor of this software or + anything derived from this software assumes responsibility for + ensuring that any parties to whom such a redistribution is made + are fully aware of the terms of this license and disclaimer. + + The Omega project can be contacted at omega@cs.umd.edu + or http://www.cs.umd.edu/projects/omega +*********************************************************************/ + +#ifndef Already_Included_Omega +#define Already_Included_Omega + +/* + * The presburger interface is divided into the following parts. + * These parts are all included together, but are in separate + * files to keep things organized a bit. + * + * In many files, you can include just some of the following, + * specifically: if you are building a presburger tree, just + * include "pres_tree.h"; if you are querying it, include + * "pres_dnf.d" and "pres_conj.h"; if you are doing relational + * operations, include "Relation.h" + * + * Most of the function definitions are in the .c files with + * the same name as the .h that declares them, except: + * the remap and push_exists functions are in pres_var.c + * the DNFize functions are in pres_dnf.c + * the functions involving printing are in pres_print.c + * the beautify functions are in pres_beaut.c + * the rearrange functions are in pres_rear.c + * the compression functions are in pres_cmpr.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#endif diff --git a/lib/omega/include/omega/RelBody.h b/lib/omega/include/omega/RelBody.h new file mode 100644 index 0000000..3c11702 --- /dev/null +++ b/lib/omega/include/omega/RelBody.h @@ -0,0 +1,165 @@ +#if ! defined _RelBody_h +#define _RelBody_h 1 + +#include +#include + +namespace omega { + +typedef enum {under_construction, compressed, uncompressed} Rel_Body_Status; +typedef unsigned char Rel_Unknown_Uses; +const Rel_Unknown_Uses no_u = 1; +const Rel_Unknown_Uses and_u = 2; +const Rel_Unknown_Uses or_u = 4; + +// +// Relation body. +// Body and representative are separated to do reference counting. +// + +class Rel_Body : public Formula { +public: + bool is_null() const; + + inline Node_Type node_type() { return Op_Relation; } + + inline bool is_set() const { return number_output == 0; } + int n_inp() const; + int n_out() const; + int n_set() const; + + inline Variable_ID_Tuple *global_decls() { return &Symbolic; } + int max_ufs_arity(); + int max_shared_ufs_arity(); + int max_ufs_arity_of_set(); + int max_ufs_arity_of_in(); + int max_ufs_arity_of_out(); + + Variable_ID input_var(int nth); + Variable_ID output_var(int nth); + Variable_ID set_var(int nth); + Variable_ID get_local(const Variable_ID v); + Variable_ID get_local(const Global_Var_ID G); + Variable_ID get_local(const Global_Var_ID G, Argument_Tuple of); + bool has_local(const Global_Var_ID G); + bool has_local(const Global_Var_ID G, Argument_Tuple of); + void name_input_var(int, Const_String); + void name_output_var(int, Const_String); + void name_set_var(int, Const_String); + + F_And *and_with_and(); + EQ_Handle and_with_EQ(); + EQ_Handle and_with_EQ(const Constraint_Handle &c); + GEQ_Handle and_with_GEQ(); + GEQ_Handle and_with_GEQ(const Constraint_Handle &c); + + void print(); + void print(FILE *output_file) { print(output_file, true); } + void print(FILE *output_file, bool printSym); + std::string print_variables_to_string(bool printSym); + void print_with_subs(FILE *output_file, bool printSym, bool newline); + void print_with_subs(); + std::string print_with_subs_to_string(bool printSym, bool newline); + std::string print_outputs_with_subs_to_string(); + std::string print_outputs_with_subs_to_string(int i); + std::string print_formula_to_string(); + void prefix_print(); + void prefix_print(FILE *output_file, int debug = 1); + + bool is_satisfiable(); + bool is_lower_bound_satisfiable(); + bool is_upper_bound_satisfiable(); + bool is_obvious_tautology(); + bool is_definite_tautology(); + bool is_unknown(); + DNF* query_DNF(); + DNF* query_DNF(int rdt_conjs, int rdt_constrs); + void simplify(int rdt_conjs = 0, int rdt_constrs = 0); + void finalize(); + inline bool is_finalized() { return finalized; } + inline bool is_shared() { return ref_count > 1; } + + void query_difference(Variable_ID v1, Variable_ID v2, + coef_t &lowerBound, coef_t &upperBound, + bool &quaranteed); + void query_variable_bounds(Variable_ID, coef_t &lowerBound, coef_t &upperBound); + coef_t query_variable_mod(Variable_ID v, coef_t factor); + + Relation extract_dnf_by_carried_level(int level, int direction); + void make_level_carried_to(int level); + + // these are only public to allow the creation of "null_rel" + Rel_Body(); + ~Rel_Body(); + void setup_names(); + +private: + + // These are manipulated primarily as parts of Relations + friend class Relation; + friend_rel_ops; + + friend void remap_DNF_vars(Rel_Body *new_rel, Rel_Body *old_rel); + + Rel_Unknown_Uses unknown_uses(); + + inline bool is_simplified() const { return (simplified_DNF!=NULL && get_children().empty()); } + bool is_compressed(); + Conjunct *rm_first_conjunct(); + Conjunct *single_conjunct(); + bool has_single_conjunct(); + + void beautify(); + void rearrange(); + + friend class EQ_Handle; // these set up names for printing + friend class GEQ_Handle; // and check if simplified + friend class Constraint_Handle; // and update coefficients + + void compress(); + void uncompress(); + + void interpret_unknown_as_true(); + void interpret_unknown_as_false(); + + Rel_Body(int n_input, int n_output); + /* Rel_Body(Rel_Body *r); */ + Rel_Body(Rel_Body *r, Conjunct *c); + Rel_Body &operator=(Rel_Body &r); + Rel_Body *clone(); + + inline Formula *formula() { return children().front(); } + inline Formula *rm_formula() { return children().remove_front(); } + bool can_add_child(); + + void reverse_leading_dir_info(); + void invalidate_leading_info(int changed = -1) { Formula::invalidate_leading_info(changed); } + void enforce_leading_info(int guaranteed, int possible, int dir) { Formula::enforce_leading_info(guaranteed, possible, dir); } + // re-declare this so that Relation (a friend) can call it + + DNF* DNFize(); + void DNF_to_formula(); + + Conjunct *find_available_conjunct(); + F_And *find_available_And(); + + +/* === data === */ +private: + + int ref_count; + Rel_Body_Status status; + + int number_input, number_output; + Tuple In_Names, Out_Names; + Variable_ID_Tuple Symbolic; + + DNF* simplified_DNF; + short r_conjs; // are redundant conjuncts eliminated? + bool finalized; + bool _is_set; +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/Rel_map.h b/lib/omega/include/omega/Rel_map.h new file mode 100644 index 0000000..5641cb3 --- /dev/null +++ b/lib/omega/include/omega/Rel_map.h @@ -0,0 +1,161 @@ +#if ! defined _Rel_map_h +#define _Rel_map_h 1 + +#include +#include + +namespace omega { + +// +// Mapping for relations +// When a relation operation needs to re-arrange the variables, +// it describes the re-arragement with a mapping, and then calls +// align to re-arrange them. +// +// In a mapping, map_in (map_out/map_set) gives the new type and +// position of each of the old input (output/set) variables. +// For variables being mapped to Input, Output, or Set variables, +// the position is the new position in the tuple. +// For variables being mapped to Exists_Var, Forall_Var, or +// Wildcard_Var, the positions can be used to map multiple +// variables to the same quantified variable, by providing +// the same position. Each variable with a negative position +// is given a unique quantified variable that is NOT listed +// in the seen_exists_ids list. +// I'm not sure what the positions mean for Global_Vars - perhaps +// they are ignored? +// +// Currently, align seems to support only mapping to Set, Input, +// Output, and Exists vars. +// + +class Mapping { +public: + inline Mapping(int no_in, int no_out): n_input(no_in), n_output(no_out) {} + inline Mapping(int no_set): n_input(no_set), n_output(0){} + inline Mapping(const Mapping &m): n_input(m.n_input), n_output(m.n_output) { + int i; + for(i=1; i<=n_input; i++) map_in_kind[i] = m.map_in_kind[i]; + for(i=1; i<=n_input; i++) map_in_pos[i] = m.map_in_pos[i]; + for(i=1; i<=n_output;i++) map_out_kind[i] = m.map_out_kind[i]; + for(i=1; i<=n_output;i++) map_out_pos[i] = m.map_out_pos[i]; + } + + inline void set_map (Var_Kind in_kind, int pos, Var_Kind type, int map) { + if(in_kind==Input_Var) + set_map_in(pos,type,map); + else if(in_kind==Set_Var) + set_map_in(pos,type,map); + else if(in_kind==Output_Var) + set_map_out(pos,type,map); + else + assert(0); + } + + inline void set_map_in (int pos, Var_Kind type, int map) { + assert(pos>=1 && pos<=n_input); + map_in_kind[pos] = type; + map_in_pos[pos] = map; + } + inline void set_map_set (int pos, Var_Kind type, int map) { + assert(pos>=1 && pos<=n_input); + map_in_kind[pos] = type; + map_in_pos[pos] = map; + } + + inline void set_map_out(int pos, Var_Kind type, int map) { + assert(pos>=1 && pos<=n_output); + map_out_kind[pos] = type; + map_out_pos[pos] = map; + } + + inline Var_Kind get_map_in_kind(int pos) const { + assert(pos>=1 && pos<=n_input); + return map_in_kind[pos]; + } + + inline int get_map_in_pos(int pos) const { + assert(pos>=1 && pos<=n_input); + return map_in_pos[pos]; + } + + inline Var_Kind get_map_out_kind(int pos) const { + assert(pos>=1 && pos<=n_output); + return map_out_kind[pos]; + } + + inline int get_map_out_pos(int pos) const { + assert(pos>=1 && pos<=n_output); + return map_out_pos[pos]; + } + + inline int n_in() const { return n_input; } + inline int n_out() const { return n_output; } + + // If a tuple as a whole becomes the new Input or Output tuple, + // return the Tuple of they will become (Input, Output) + // Return Unknown_Tuple otherwise + + inline Argument_Tuple get_tuple_fate(Argument_Tuple t, int prefix = -1) const { + return t== Input_Tuple ? get_input_fate(prefix) : + (t==Output_Tuple ? get_output_fate(prefix) : Unknown_Tuple); } + + inline Argument_Tuple get_set_fate(int prefix = -1) const { + return get_input_fate(prefix); } + + inline Argument_Tuple get_input_fate(int prefix = -1) const { + if (prefix < 0) prefix = n_input; + assert(n_input >= prefix); + if (n_input < prefix) + return Unknown_Tuple; + Var_Kind vf = map_in_kind[1]; + for (int i = 1; i<=prefix; i++) + if (map_in_pos[i]!=i || map_in_kind[i]!=vf) + return Unknown_Tuple; + + return vf == Input_Var ? Input_Tuple + : vf == Set_Var ? Set_Tuple + : vf == Output_Var ? Output_Tuple + : Unknown_Tuple; + } + + inline Argument_Tuple get_output_fate(int prefix = -1) const { + if (prefix < 0) prefix = n_output; + assert(n_output >= prefix); + if (n_output < 1) + return Unknown_Tuple; + Var_Kind vf = map_out_kind[1]; + for (int i = 1; i<=prefix; i++) + if (map_out_pos[i]!=i || map_out_kind[i]!=vf) + return Unknown_Tuple; + return vf == Input_Var ? Input_Tuple + : vf == Set_Var ? Set_Tuple + : vf == Output_Var ? Output_Tuple + : Unknown_Tuple; + } + + inline static Mapping Identity(int inp, int outp) { + Mapping m(inp, outp); int i; + for(i=1; i<=m.n_input; i++) m.set_map(Input_Var, i, Input_Var, i); + for(i=1; i<=m.n_output;i++) m.set_map(Output_Var, i, Output_Var, i); + return m; + } + + inline static Mapping Identity(int setvars) { + Mapping m(setvars); int i; + for(i=1; i<=setvars; i++) m.set_map(Set_Var, i, Set_Var, i); + return m; + } + +private: + int n_input; + int n_output; + Var_Kind map_in_kind[maxVars]; + int map_in_pos[maxVars]; + Var_Kind map_out_kind[maxVars]; + int map_out_pos[maxVars]; +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/Relation.h b/lib/omega/include/omega/Relation.h new file mode 100644 index 0000000..b41bef5 --- /dev/null +++ b/lib/omega/include/omega/Relation.h @@ -0,0 +1,299 @@ +#if ! defined _Relation_h +#define _Relation_h 1 + +#include +#include +#include +#include + +namespace omega { + +// +// Relation representative. +// Body and representative are separated to do reference counting. +// +class Relation { +public: + Relation(); + + Relation(int n_input, int n_output = 0); + Relation(const Relation &r); + Relation(const Relation &r, Conjunct *c); + Relation &operator=(const Relation &r); + Relation(Rel_Body &r, int foo); + + static Relation Null(); + static Relation Empty(const Relation &R); + static Relation True(const Relation &R); + static Relation True(int setvars); + static Relation True(int in, int out); + static Relation False(const Relation &R); + static Relation False(int setvars); + static Relation False(int in, int out); + static Relation Unknown(const Relation &R); + static Relation Unknown(int setvars); + static Relation Unknown(int in, int out); + + + bool is_null() const; + + ~Relation(); + + inline F_Forall *add_forall() + { return rel_body->add_forall(); } + inline F_Exists *add_exists() + { return rel_body->add_exists(); } + inline F_And *add_and() + { return rel_body->add_and(); } + inline F_And *and_with() + { return rel_body->and_with(); } + inline F_Or *add_or() + { return rel_body->add_or(); } + inline F_Not *add_not() + { return rel_body->add_not(); } + inline void finalize() + { rel_body->finalize(); } + inline bool is_finalized() const + { return rel_body->finalized; } + inline bool is_set() const + { return rel_body->is_set(); } + inline int n_inp() const + { return rel_body->n_inp(); } + inline int n_out() const + { return rel_body->n_out(); } + inline int n_set() const + { return rel_body->n_set(); } + + inline const Variable_ID_Tuple *global_decls() const + { return rel_body->global_decls(); } + inline int max_ufs_arity() const + { return rel_body->max_ufs_arity(); } + inline int max_ufs_arity_of_in() const + { return rel_body->max_ufs_arity_of_in(); } + inline int max_ufs_arity_of_set() const + { return rel_body->max_ufs_arity_of_set(); } + inline int max_ufs_arity_of_out() const + { return rel_body->max_ufs_arity_of_out(); } + inline int max_shared_ufs_arity() const + { return rel_body->max_shared_ufs_arity(); } + + inline Variable_ID input_var(int nth) + { return rel_body->input_var(nth); } + inline Variable_ID output_var(int nth) + { return rel_body->output_var(nth); } + inline Variable_ID set_var(int nth) + { return rel_body->set_var(nth); } + inline bool has_local(const Global_Var_ID G) + { return rel_body->has_local(G); } + inline bool has_local(const Global_Var_ID G, Argument_Tuple of) + { return rel_body->has_local(G, of); } + inline Variable_ID get_local(const Variable_ID v) + { return split()->get_local(v); } + inline Variable_ID get_local(const Global_Var_ID G) + { return split()->get_local(G); } + inline Variable_ID get_local(const Global_Var_ID G, Argument_Tuple of) + { return split()->get_local(G, of); } + + inline void name_input_var(int nth, Const_String S) + { split()->name_input_var(nth, S); } + inline void name_output_var(int nth, Const_String S) + { split()->name_output_var(nth, S); } + inline void name_set_var(int nth, Const_String S) + { split()->name_set_var(nth, S); } + + + inline F_And *and_with_and() + { return split()->and_with_and(); } + inline EQ_Handle and_with_EQ() + { return split()->and_with_EQ(); } + inline EQ_Handle and_with_EQ(const Constraint_Handle &c) + { return split()->and_with_EQ(c); } + inline GEQ_Handle and_with_GEQ() + { return split()->and_with_GEQ(); } + inline GEQ_Handle and_with_GEQ(const Constraint_Handle &c) + { return split()->and_with_GEQ(c); } + + inline void print() + { rel_body->print(); } + inline void print(FILE *output_file) + { rel_body->print(output_file); } + inline void print_with_subs() + { rel_body->print_with_subs(); } + inline void print_with_subs(FILE *output_file, bool printSym=false, + bool newline=true) + { rel_body->print_with_subs(output_file, printSym, newline); } + inline std::string print_with_subs_to_string(bool printSym=false, + bool newline=true) + { return rel_body->print_with_subs_to_string(printSym, newline); } + inline std::string print_outputs_with_subs_to_string() + { return rel_body->print_outputs_with_subs_to_string(); } + inline std::string print_outputs_with_subs_to_string(int i) + { return rel_body->print_outputs_with_subs_to_string(i); } + inline void prefix_print() + { rel_body->prefix_print(); } + inline void prefix_print(FILE *output_file, int debug = 1) + { rel_body->prefix_print(output_file, debug); } + inline std::string print_formula_to_string() { + return rel_body->print_formula_to_string(); + } + void dimensions(int & ndim_all, int &ndim_domain); + + inline bool is_lower_bound_satisfiable() + { return rel_body->is_lower_bound_satisfiable(); } + inline bool is_upper_bound_satisfiable() + { return rel_body->is_upper_bound_satisfiable(); } + inline bool is_satisfiable() + { return rel_body->is_satisfiable(); } + + inline bool is_tautology() + { return rel_body->is_obvious_tautology(); } // for compatibility + inline bool is_obvious_tautology() + { return rel_body->is_obvious_tautology(); } + inline bool is_definite_tautology() + { return rel_body->is_definite_tautology(); } + + // return x s.t. forall conjuncts c, c has >= x leading 0s + // for set, return -1 (pass this in, in case there are no conjuncts + inline int number_of_conjuncts() + { return rel_body->query_DNF()->length(); } + + // return x s.t. forall conjuncts c, c has >= x leading 0s + // for set, return -1 (pass this in, in case there are no conjuncts + inline int query_guaranteed_leading_0s() + { return rel_body->query_DNF()->query_guaranteed_leading_0s(this->is_set() ? -1 : 0); } + + // return x s.t. forall conjuncts c, c has <= x leading 0s + // if no conjuncts return min of input and output tuple sizes, or -1 if relation is a set + inline int query_possible_leading_0s() + { return rel_body->query_DNF()->query_possible_leading_0s( + this->is_set()? -1 : min(n_inp(),n_out())); } + + // return +-1 according to sign of leading dir, or 0 if we don't know + inline int query_leading_dir() + { return rel_body->query_DNF()->query_leading_dir(); } + + inline DNF* query_DNF() + { return rel_body->query_DNF(); } + inline DNF* query_DNF(int rdt_conjs, int rdt_constrs) + { return rel_body->query_DNF(rdt_conjs, rdt_constrs); } + inline void simplify(int rdt_conjs = 0, int rdt_constrs = 0) + { rel_body->simplify(rdt_conjs, rdt_constrs); } + inline bool is_simplified() + { return rel_body->is_simplified(); } + inline bool is_compressed() const + { return rel_body->is_compressed(); } + inline Conjunct *rm_first_conjunct() + { return rel_body->rm_first_conjunct(); } + inline Conjunct *single_conjunct() + { return rel_body->single_conjunct(); } + inline bool has_single_conjunct() + { return rel_body->has_single_conjunct(); } + + + void query_difference(Variable_ID v1, Variable_ID v2, coef_t &lowerBound, coef_t &upperBound, bool &guaranteed) { + rel_body->query_difference(v1, v2, lowerBound, upperBound, guaranteed); + } + void query_variable_bounds(Variable_ID v, coef_t &lowerBound, coef_t &upperBound) { + rel_body->query_variable_bounds(v,lowerBound,upperBound); + } + coef_t query_variable_mod(Variable_ID v, coef_t factor) { + assert(factor > 0); + return rel_body->query_variable_mod(v, factor); + } + int query_variable_mod(Variable_ID v, int factor) { + assert(sizeof(int) <= sizeof(coef_t)); + coef_t result = rel_body->query_variable_mod(v, static_cast(factor)); + if (result == posInfinity) + return INT_MAX; + else + return static_cast(result); + } + + + inline void make_level_carried_to(int level) + { + split()->make_level_carried_to(level); + } + + inline Relation extract_dnf_by_carried_level(int level, int direction) + { + return split()->extract_dnf_by_carried_level(level, direction); + } + + inline void compress() + { +#if defined(INCLUDE_COMPRESSION) + split()->compress(); +#endif + } + void uncompress() + { rel_body->uncompress(); } + + inline bool is_exact() const + { return !(rel_body->unknown_uses() & (and_u | or_u)) ; } + inline bool is_inexact() const + { return !is_exact(); } + inline bool is_unknown() const + { return rel_body->is_unknown(); } + inline Rel_Unknown_Uses unknown_uses() const + { return rel_body->unknown_uses(); } + + void setup_names() {rel_body->setup_names();} + void copy_names(const Relation &r) { + copy_names(*r.rel_body); + }; + void copy_names(Rel_Body &r); + +private: + // Functions that have to create sets from relations: + friend class Rel_Body; + friend_rel_ops; + + + Rel_Body *split(); + + DNF* simplified_DNF() { + simplify(); + return rel_body->simplified_DNF; + }; + + inline void invalidate_leading_info(int changed = -1) + { split()->invalidate_leading_info(changed); } + inline void enforce_leading_info(int guaranteed, int possible, int dir) + { + split()->enforce_leading_info(guaranteed, possible, dir); + } + + + void makeSet(); + void markAsSet(); + void markAsRelation(); + + friend bool operator==(const Relation &, const Relation &); + + void reverse_leading_dir_info() + { split()->reverse_leading_dir_info(); } + void interpret_unknown_as_true() + { split()->interpret_unknown_as_true(); } + void interpret_unknown_as_false() + { split()->interpret_unknown_as_false(); } + + + Rel_Body *rel_body; + + + friend Relation merge_rels(Tuple &R, const Tuple > > &mapping, const Tuple &inverse, Combine_Type ctype, int number_input, int number_output); +}; + +inline std::ostream & operator<<(std::ostream &o, Relation &R) +{ + return o << R.print_with_subs_to_string(); +} + +Relation copy(const Relation &r); + +} // namespace + +#include + +#endif diff --git a/lib/omega/include/omega/Relations.h b/lib/omega/include/omega/Relations.h new file mode 100644 index 0000000..4fd81e6 --- /dev/null +++ b/lib/omega/include/omega/Relations.h @@ -0,0 +1,88 @@ +#if ! defined _Relations_h +#define _Relations_h 1 + +#include +#include + +namespace omega { + +// UPDATE friend_rel_ops IN pres_gen.h WHEN ADDING TO THIS LIST +// REMEMBER TO TAKE OUT DEFAULT ARGUMENTS IN THAT FILE + +/* The following allows us to avoid warnings about passing + temporaries as non-const references. This is useful but + has suddenly become illegal. */ +Relation consume_and_regurgitate(NOT_CONST Relation &R); + +// +// Operations over relations +// +Relation Union(NOT_CONST Relation &r1, NOT_CONST Relation &r2); +Relation Intersection(NOT_CONST Relation &r1, NOT_CONST Relation &r2); +Relation Extend_Domain(NOT_CONST Relation &R); +Relation Extend_Domain(NOT_CONST Relation &R, int more); +Relation Extend_Range(NOT_CONST Relation &R); +Relation Extend_Range(NOT_CONST Relation &R, int more); +Relation Extend_Set(NOT_CONST Relation &R); +Relation Extend_Set(NOT_CONST Relation &R, int more); +Relation Restrict_Domain(NOT_CONST Relation &r1, NOT_CONST Relation &r2); // Takes set as 2nd +Relation Restrict_Range(NOT_CONST Relation &r1, NOT_CONST Relation &r2); // Takes set as 2nd +Relation Domain(NOT_CONST Relation &r); // Returns set +Relation Range(NOT_CONST Relation &r); // Returns set +Relation Cross_Product(NOT_CONST Relation &A, NOT_CONST Relation &B); // Takes two sets +Relation Inverse(NOT_CONST Relation &r); +Relation After(NOT_CONST Relation &r, int carried_by, int new_output,int dir=1); +Relation Deltas(NOT_CONST Relation &R); // Returns set +Relation Deltas(NOT_CONST Relation &R, int eq_no); // Returns set +Relation DeltasToRelation(NOT_CONST Relation &R, int n_input, int n_output); +Relation Complement(NOT_CONST Relation &r); +Relation Project(NOT_CONST Relation &R, Global_Var_ID v); +Relation Project(NOT_CONST Relation &r, int pos, Var_Kind vkind); +Relation Project(NOT_CONST Relation &S, Variable_ID v); +Relation Project(NOT_CONST Relation &S, Sequence &s); +Relation Project_Sym(NOT_CONST Relation &R); +Relation Project_On_Sym(NOT_CONST Relation &R, + NOT_CONST Relation &context = Relation::Null()); +Relation GistSingleConjunct(NOT_CONST Relation &R, NOT_CONST Relation &R2, int effort=0); +Relation Gist(NOT_CONST Relation &R1, NOT_CONST Relation &R2, int effort=0); +Relation Difference(NOT_CONST Relation &r1, NOT_CONST Relation &r2); +Relation Approximate(NOT_CONST Relation &R, bool strides_allowed = false); +Relation Identity(int n_inp); +Relation Identity(NOT_CONST Relation &r); +bool Must_Be_Subset(NOT_CONST Relation &r1, NOT_CONST Relation &r2); +bool Might_Be_Subset(NOT_CONST Relation &r1, NOT_CONST Relation &r2); +// May is the same as might, just another name +bool May_Be_Subset(NOT_CONST Relation &r1, NOT_CONST Relation &r2); +bool Is_Obvious_Subset(NOT_CONST Relation &r1, NOT_CONST Relation &r2); +Relation Composition(NOT_CONST Relation &F, NOT_CONST Relation &G); +bool prepare_relations_for_composition(Relation &F, Relation &G); +Relation Join(NOT_CONST Relation &G, NOT_CONST Relation &F); +Relation EQs_to_GEQs(NOT_CONST Relation &, bool excludeStrides=false); +Relation Symbolic_Solution(NOT_CONST Relation &S); +Relation Symbolic_Solution(NOT_CONST Relation &S, Sequence &T); +Relation Sample_Solution(NOT_CONST Relation &S); +Relation Solution(NOT_CONST Relation &S, Sequence &T); +Relation Upper_Bound(NOT_CONST Relation &r); +Relation Lower_Bound(NOT_CONST Relation &r); + +Relation merge_rels(Tuple &R, const Tuple > > &mapping, const Tuple &inverse, Combine_Type ctype, int number_input = -1, int number_output = -1); + +// The followings might retire in the futrue!!! +void MapRel1(Relation &inputRel, + const Mapping &map, + Combine_Type ctype, + int number_input=-1, int number_output=-1, + bool invalidate_resulting_leading_info = true, + bool finalize = true); +Relation MapAndCombineRel2(Relation &R1, Relation &R2, + const Mapping &mapping1, const Mapping &mapping2, + Combine_Type ctype, + int number_input=-1, int number_output=-1); +void align(Rel_Body *originalr, Rel_Body *newr, F_Exists *fe, + Formula *f, const Mapping &mapping, bool &newrIsSet, + List &seen_exists, + Variable_ID_Tuple &seen_exists_ids); + +} // namespace + +#endif diff --git a/lib/omega/include/omega/closure.h b/lib/omega/include/omega/closure.h new file mode 100644 index 0000000..67088dd --- /dev/null +++ b/lib/omega/include/omega/closure.h @@ -0,0 +1,31 @@ +#if ! defined _closure_h +#define _closure_h + +#include + +namespace omega { + +Relation VennDiagramForm( + Tuple &Rs, + NOT_CONST Relation &Context_In); +Relation VennDiagramForm( + NOT_CONST Relation &R_In, + NOT_CONST Relation &Context_In = Relation::Null()); + +// Given a Relation R, returns a relation deltas +// that correspond to the ConicHull of the detlas of R +Relation ConicClosure (NOT_CONST Relation &R); + +Relation TransitiveClosure (NOT_CONST Relation &r, + int maxExpansion = 1, + NOT_CONST Relation &IterationSpace=Relation::Null()); + +/* Tomasz Klimek */ +Relation calculateTransitiveClosure(NOT_CONST Relation &r); + +/* Tomasz Klimek */ +Relation ApproxClosure(NOT_CONST Relation &r); + +} // namespace + +#endif diff --git a/lib/omega/include/omega/evac.h b/lib/omega/include/omega/evac.h new file mode 100644 index 0000000..a561f8c --- /dev/null +++ b/lib/omega/include/omega/evac.h @@ -0,0 +1,15 @@ +#if defined STUDY_EVACUATIONS + +namespace omega { + +// study the evacuation from one side of C to the other for UFS's of +// arity up to max_arity +extern void study_evacuation(Conjunct *C, which_way dir, int max_arity); + +// study the evacuation from the joined C2's output and C1's input to +// either of the other possible tuples +extern void study_evacuation(Conjunct *C1, Conjunct *C2, int max_arity); + +} // namespace + +#endif diff --git a/lib/omega/include/omega/farkas.h b/lib/omega/include/omega/farkas.h new file mode 100644 index 0000000..e77ed66 --- /dev/null +++ b/lib/omega/include/omega/farkas.h @@ -0,0 +1,19 @@ +#ifndef Already_Included_Affine_Closure +#define Already_Included_Affine_Closure + +#include + +namespace omega { + +enum Farkas_Type {Basic_Farkas, Decoupled_Farkas, + Linear_Combination_Farkas, Positive_Combination_Farkas, + Affine_Combination_Farkas, Convex_Combination_Farkas }; + +Relation Farkas(NOT_CONST Relation &R, Farkas_Type op, bool early_bailout = false); + +extern coef_t farkasDifficulty; +extern Global_Var_ID coefficient_of_constant_term; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/hull.h b/lib/omega/include/omega/hull.h new file mode 100644 index 0000000..928d0c6 --- /dev/null +++ b/lib/omega/include/omega/hull.h @@ -0,0 +1,89 @@ +#ifndef Already_Included_Hull +#define Already_Included_Hull + +#include + +namespace omega { + +Relation SimpleHull(const Relation &R, bool allow_stride_constraint = false, bool allow_irregular_constraint = false); +Relation SimpleHull(const std::vector &Rs, bool allow_stride_constraint = false, bool allow_irregular_constraint = false); + + +// All of the following first call approximate on R to +// eliminate any wildcards and strides. + +// x in Convex Hull of R +// iff +// exist a_i, y_i s.t. +// x = Sum_i a_i y_i s.t. +// forall i, y_i in R +// forall i, a_i >=0 +// sum_i a_i = 1 +Relation ConvexHull(NOT_CONST Relation &R); + +// DecoupledConvexHull is the same as ConvexHull, +// except that it only finds constraints that involve +// both variables x&y if there is a constraint +// that involves both x&y in one of the conjuncts +// of R. +Relation DecoupledConvexHull(NOT_CONST Relation &R); + +// The affine hull just consists of equality constraints +// but is otherwise the tightest hull on R. +// x in Affine Hull of R +// iff +// exist a_i, y_i s.t. +// x = Sum_i a_i y_i s.t. +// forall i, y_i in R +// sum_i a_i = 1 +Relation AffineHull(NOT_CONST Relation &R); + +// x in Linear Hull of R +// iff +// exist a_i, y_i s.t. +// x = Sum_i a_i y_i s.t. +// forall i, y_i in R +Relation LinearHull(NOT_CONST Relation &R); + +// The conic hull is the tighest cone that contains R +// x in Conic Hull of R. +// iff +// exist a_i, y_i s.t. +// x = Sum_i a_i y_i s.t. +// forall i, y_i in R +// forall i, a_i >=0 +Relation ConicHull(NOT_CONST Relation &R); + +// RectHull includes readily-available constraints from relation +// that can be part of hull, plus rectangular bounds calculated +// from input/output/set variables' range. +Relation RectHull(NOT_CONST Relation &Rel); + +// A constraint is in the result of QuickHull only if it appears in one of +// the relations and is directly implied by a single constraint in each of +// the other relations. +Relation QuickHull(Relation &R); // deprecated +Relation QuickHull(Tuple &Rs); // deprecated + +Relation FastTightHull(NOT_CONST Relation &input_R, + NOT_CONST Relation &input_H); +Relation Hull(NOT_CONST Relation &R, + bool stridesAllowed = false, + int effort=1, + NOT_CONST Relation &knownHull = Relation::Null() + ); +Relation Hull(Tuple &Rs, + const std::vector &validMask, + int effort = 1, + bool stridesAllowed = false, + NOT_CONST Relation &knownHull = Relation::Null()); + +// If a union of several conjuncts is a convex, their union +// representaition can be simplified by their convex hull. +Relation ConvexRepresentation(NOT_CONST Relation &R); +Relation CheckForConvexPairs(NOT_CONST Relation &S); // deprecated +Relation CheckForConvexRepresentation(NOT_CONST Relation &R_In); // deprecated + +} + +#endif diff --git a/lib/omega/include/omega/omega_core/debugging.h b/lib/omega/include/omega/omega_core/debugging.h new file mode 100644 index 0000000..e217ae9 --- /dev/null +++ b/lib/omega/include/omega/omega_core/debugging.h @@ -0,0 +1,30 @@ +#if !defined(Already_included_debugging) +#define Already_included_debugging + +// Debugging flags. Can set any of these. + +#include +#include + +namespace omega { + + + +extern int omega_core_debug; +extern int pres_debug; +extern int relation_debug; +extern int closure_presburger_debug; +extern int hull_debug; +extern int farkas_debug; +extern int code_gen_debug; + +enum negation_control { any_negation, one_geq_or_eq, one_geq_or_stride }; +extern negation_control pres_legal_negations; + +#if defined STUDY_EVACUATIONS +extern int evac_debug; +#endif + +} // namespace + +#endif diff --git a/lib/omega/include/omega/omega_core/oc.h b/lib/omega/include/omega/omega_core/oc.h new file mode 100644 index 0000000..e4f5444 --- /dev/null +++ b/lib/omega/include/omega/omega_core/oc.h @@ -0,0 +1,350 @@ +#ifndef Already_Included_OC +#define Already_Included_OC 1 + +#include +#include +#include +#include +#include + +namespace omega { + +// Manu:: commented the line below -- fortran bug workaround +//#define maxVars 256 /* original 56, increased by chun */ +#define maxVars 100 + +extern int maxGEQs; +extern int maxEQs; + +// Manu:: commented the lines below -- fortran bug workaround +//const int maxmaxGEQs = 2048; // original 512, increaded by chun +//const int maxmaxEQs = 512; // original 256, increased by chun +const int maxmaxGEQs = 512; +const int maxmaxEQs = 256; + +/* #if ! defined maxmaxGEQs */ +/* #define maxmaxGEQs 2048 /\* original 512, increaded by chun *\/ */ +/* #endif */ +/* #if ! defined maxmaxEQs */ +/* #define maxmaxEQs 512 /\* original 256, increased by chun *\/ */ +/* #endif */ + + +#if 0 +#if ! defined Already_Included_Portable +typedef unsigned char bool; /* what a gross thing to do */ +#endif +#endif + +typedef int EqnKey; + +enum {EQ_BLACK = 0, EQ_RED = 1}; +enum {OC_SOLVE_UNKNOWN = 2, OC_SOLVE_SIMPLIFY = 3}; + +struct eqn { + EqnKey key; + coef_t touched; // see oc_simple.c + int color; + int essential; + int varCount; + coef_t coef[maxVars + 1]; +}; + +// typedef eqn * Eqn; +enum redType {notRed=0, redEQ, redGEQ, redLEQ, redStride}; +enum redCheck {noRed=0, redFalse, redConstraints}; +enum normalizeReturnType {normalize_false, normalize_uncoupled, + normalize_coupled}; + +extern char wildName[200][20]; + +extern FILE *outputFile; /* printProblem writes its output to this file */ +#define doTrace (trace && TRACE) +#define isRed(e) (desiredResult == OC_SOLVE_SIMPLIFY && (e)->color) +// #define eqnncpy(e1,e2,s) {int *p00,*q00,*r00; p00 = (int *)(e1); q00 = (int *)(e2); r00 = &p00[headerWords+1+s]; while(p00 < r00) *p00++ = *q00++; } +// #define eqncpy(e1,e2) eqnncpy(e1,e2,nVars) +// #define eqnnzero(e,s) {int *p00,*r00; p00 = (int *)(e); r00 = &p00[headerWords+1+(s)]; while(p00 < r00) *p00++ = 0;} +// #define eqnzero(e) eqnnzero(e,nVars) + +//void eqnncpy(eqn *dest, eqn *src, int); +//void eqnnzero(eqn *e, int); + +inline void eqnncpy(eqn *dest, eqn *src, int nVars) { + dest->key = src->key; + dest->touched = src->touched; + dest->color = src->color; + dest->essential = src->essential; + dest->varCount = src->varCount; + for (int i = 0; i <= nVars; i++) + dest->coef[i] = src->coef[i]; +} + + +inline void eqnnzero(eqn *e, int nVars) { + e->key = 0; + e->touched = 0; + e->color = EQ_BLACK; + e->essential = 0; + e->varCount = 0; + for (int i = 0; i <= nVars; i++) + e->coef[i] = 0; +} + +extern int mayBeRed; + +#ifdef SPEED +#define TRACE 0 +#define DBUG 0 +#define DEBUG 0 +#else +#define TRACE (omega_core_debug) +#define DBUG (omega_core_debug > 1) +#define DEBUG (omega_core_debug > 2) +#endif + + +class Memory { +public: + int length; + coef_t stride; + redType kind; + coef_t constantTerm; + coef_t coef[maxVars + 1]; + int var[maxVars + 1]; +}; + +/* #define headerWords ((4*sizeof(int) + sizeof(coef_t))/sizeof(int)) */ + +void check_number_EQs(int); +void check_number_GEQs(int); +extern eqn SUBs[]; +extern Memory redMemory[]; + +class Problem { +public: + short nVars, safeVars; + short nEQs, nGEQs,nSUBs,nMemories,allocEQs,allocGEQs; + short varsOfInterest; + bool variablesInitialized; + bool variablesFreed; + short var[maxVars+2]; + short forwardingAddress[maxVars+2]; + // int variableColor[maxVars+2]; + int hashVersion; + const char *(*get_var_name)(unsigned int var, void *args); + void *getVarNameArgs; + eqn *GEQs; + eqn *EQs; + bool isTemporary; + + Problem(int in_eqs=0, int in_geqs=0); + Problem(const Problem &); + ~Problem(); + Problem & operator=(const Problem &); + +/* Allocation parameters and functions */ + + static const int min_alloc,first_alloc_pad; + int padEQs(int oldalloc, int newreq) { + check_number_EQs(newreq); + return min((newreq < 2*oldalloc ? 2*oldalloc : 2*newreq),maxmaxEQs); + } + int padGEQs(int oldalloc, int newreq) { + check_number_GEQs(newreq); + return min((newreq < 2*oldalloc ? 2*oldalloc : 2*newreq),maxmaxGEQs); + } + int padEQs(int newreq) { + check_number_EQs(newreq); + return min(max(newreq+first_alloc_pad,min_alloc), maxmaxEQs); + } + int padGEQs(int newreq) { + check_number_GEQs(newreq); + return min(max(newreq+first_alloc_pad,min_alloc), maxmaxGEQs); + } + + + void zeroVariable(int i); + + void putVariablesInStandardOrder(); + void noteEssential(int onlyWildcards); + int findDifference(int e, int &v1, int &v2); + int chainKill(int color,int onlyWildcards); + + int newGEQ(); + int newEQ(); + int newSUB(){ + return nSUBs++; + } + + + void initializeProblem(); + void initializeVariables() const; + void printProblem(int debug = 1) const; + void printSub(int v) const; + std::string print_sub_to_string(int v) const; + void clearSubs(); + void printRedEquations() const; + int countRedEquations() const; + int countRedGEQs() const; + int countRedEQs() const; + int countRedSUBs() const; + void difficulty(int &numberNZs, coef_t &maxMinAbsCoef, coef_t &sumMinAbsCoef) const; + int prettyPrintProblem() const; + std::string prettyPrintProblemToString() const; + int prettyPrintRedEquations() const; + int simplifyProblem(int verify, int subs, int redundantElimination); + int simplifyProblem(); + int simplifyAndVerifyProblem(); + int simplifyApproximate(bool strides_allowed); + void coalesce(); + void partialElimination(); + void unprotectVariable(int var); + void negateGEQ(int); + void convertEQstoGEQs(bool excludeStrides); + void convertEQtoGEQs(int eq); + void nameWildcard(int i); + void useWildNames(); + void ordered_elimination(int symbolic); + int eliminateRedundant (bool expensive); + void eliminateRed(bool expensive); + void constrainVariableSign(int color, int var, int sign); + void constrainVariableValue(int color, int var, int value); + void query_difference(int v1, int v2, coef_t &lowerBound, coef_t &upperBound, bool &guaranteed); + int solve(int desiredResult); + std::string print_term_to_string(const eqn *e, int c) const; + void printTerm(const eqn * e, int c) const; + std::string printEqnToString(const eqn * e, int test, int extra) const; + void sprintEqn(char *str, const eqn * e, int is_geq,int extra) const; + void printEqn(const eqn * e, int is_geq, int extra) const; + void printEQ(const eqn *e) const {printEqn(e,0,0); } + std::string print_EQ_to_string(const eqn *e) const {return printEqnToString(e,0,0);} + std::string print_GEQ_to_string(const eqn *e) const {return printEqnToString(e,1,0);} + void printGEQ(const eqn *e) const {printEqn(e,1,0); } + void printGEQextra(const eqn *e) const {printEqn(e,1,1); } + void printSubstitution(int s) const; + void printVars(int debug = 1) const; + void swapVars(int i, int j); + void reverseProtectedVariables(); + redCheck redSimplifyProblem(int effort, int computeGist); + + // calculate value of variable mod integer from set of equations -- by chun 12/14/2006 + coef_t query_variable_mod(int v, coef_t factor, int color=EQ_BLACK, int nModularEQs=0, int nModularVars=0) const; + coef_t query_variable_mod(int v, coef_t factor, int color, int nModularEQs, int nModularVars, Tuple &working_on) const; // helper function + + int queryVariable(int i, coef_t *lowerBound, coef_t *upperBound); + int query_variable_bounds(int i, coef_t *l, coef_t *u); + void queryCoupledVariable(int i, coef_t *l, coef_t *u, int *couldBeZero, coef_t lowerBound, coef_t upperBound); + int queryVariableSigns(int i, int dd_lt, int dd_eq, int dd_gt, coef_t lowerBound, coef_t upperBound, bool *distKnown, coef_t *dist); + void addingEqualityConstraint(int e); + normalizeReturnType normalize(); + void normalize_ext(); + void cleanoutWildcards(); + void substitute(eqn *sub, int i, coef_t c); + void deleteVariable( int i); + void deleteBlack(); + int addNewProtectedWildcard(); + int addNewUnprotectedWildcard(); + int protectWildcard( int i); + void doMod( coef_t factor, int e, int j); + void freeEliminations( int fv); + int verifyProblem(); + void resurrectSubs(); + int solveEQ(); + int combineToTighten() ; + int quickKill(int onlyWildcards, bool desperate = false); + int expensiveEqualityCheck(); + int expensiveRedKill(); + int expensiveKill(); + int smoothWeirdEquations(); + void quickRedKill(int computeGist); + void chainUnprotect(); + void freeRedEliminations(); + void doElimination( int e, int i); + void analyzeElimination( + int &v, + int &darkConstraints, + int &darkShadowFeasible, + int &unit, + coef_t ¶llelSplinters, + coef_t &disjointSplinters, + coef_t &lbSplinters, + coef_t &ubSplinters, + int ¶llelLB); + int parallelSplinter(int e, int diff, int desiredResult); + int solveGEQ( int desiredResult); + void setInternals(); + void setExternals(); + int reduceProblem(); + void problem_merge(Problem &); + void deleteRed(); + void turnRedBlack(); + void checkGistInvariant() const; + void check() const; + coef_t checkSum() const; + void rememberRedConstraint(eqn *e, redType type, coef_t stride); + void recallRedMemories(); + void simplifyStrideConstraints(); + const char * orgVariable(int i) const { + return ((i == 0) ? // cfront likes this form better + "1" : + ((i < 0) ? + wildName[-i] : + (*get_var_name)(i,getVarNameArgs))); + }; + const char * variable(int i) const { + return orgVariable(var[i]) ; + }; + + void deleteGEQ(int e) { + if (DEBUG) { + fprintf(outputFile,"Deleting %d (last:%d): ",e,nGEQs-1); + printGEQ(&GEQs[e]); + fprintf(outputFile,"\n"); + }; + if (e < nGEQs-1) + eqnncpy (&GEQs[e], &GEQs[nGEQs - 1],(nVars)); + nGEQs--; + }; + void deleteEQ(int e) { + if (DEBUG) { + fprintf(outputFile,"Deleting %d (last:%d): ",e,nEQs-1); + printGEQ(&EQs[e]); + fprintf(outputFile,"\n"); + }; + if (e < nEQs-1) + eqnncpy (&EQs[e], &EQs[nEQs - 1],(nVars)); + nEQs--; + }; + +}; + + + +/* #define UNKNOWN 2 */ +/* #define SIMPLIFY 3 */ +/* #define _red 1 */ +/* #define black 0 */ + + +extern int print_in_code_gen_style; + + +void initializeOmega(void); + + +/* set extra to 0 for normal use */ +int singleVarGEQ(eqn *e); + +void setPrintLevel(int level); + +void printHeader(); + +void setOutputFile(FILE *file); + +extern void check_number_EQs(int nEQs); +extern void check_number_GEQs(int nGEQs); +extern void checkVars(int nVars); + +} // namespace + +#endif diff --git a/lib/omega/include/omega/omega_core/oc_i.h b/lib/omega/include/omega/omega_core/oc_i.h new file mode 100644 index 0000000..9533a40 --- /dev/null +++ b/lib/omega/include/omega/omega_core/oc_i.h @@ -0,0 +1,79 @@ +#if !defined(Already_included_oc_i) +#define Already_included_oc_i + +#include +#include +#include +#include +#include +#include + +namespace omega { + +#define maxWildcards 18 + +extern int findingImplicitEqualities; +extern int firstCheckForRedundantEquations; +extern int use_ugly_names; +extern int doItAgain; +extern int newVar; +extern int conservative; +extern FILE *outputFile; /* printProblem writes its output to this file */ +extern int nextWildcard; +extern int trace; +extern int depth; +extern int packing[maxVars]; +extern int headerLevel; +extern int inApproximateMode; +extern int inStridesAllowedMode; +extern int addingOuterEqualities; +extern int outerColor; + +const int keyMult = 31; +const int hashTableSize =5*maxmaxGEQs; +const int maxKeys = 8*maxmaxGEQs; +extern int hashVersion; +extern eqn hashMaster[hashTableSize]; +extern int fastLookup[maxKeys*2]; +extern int nextKey; + +extern int reduceWithSubs; +extern int pleaseNoEqualitiesInSimplifiedProblems; + +#define noProblem ((Problem *) 0) + +extern Problem *originalProblem; +int checkIfSingleVar(eqn *e, int i); +/* Solve e = factor alpha for x_j and substitute */ + +void negateCoefficients(eqn * eqn, int nV); + +extern int omegaInitialized; +extern Problem full_answer, context,redProblem; + +#if defined BRAIN_DAMAGED_FREE +static inline void free(const Problem *p) +{ + free((char *)p); +} +#endif + +#if defined NDEBUG +#define CHECK_FOR_DUPLICATE_VARIABLE_NAMES +#else +#define CHECK_FOR_DUPLICATE_VARIABLE_NAMES \ + { \ + std::vector name(nVars); \ + for(int i=1; i<=nVars; i++) { \ + name[i-1] = variable(i); \ + assert(!name[i-1].empty()); \ + for(int j=1; j + +namespace omega { + +/* #define Assert(c,t) if(!(c)) PresErrAssert(t) */ +/* void PresErrAssert(const char *t); */ + +extern Rel_Body null_rel; + +extern int skip_finalization_check; +// extern int skip_set_checks; + +// Global input and output variable tuples. + +extern Global_Input_Output_Tuple input_vars; +extern Global_Input_Output_Tuple output_vars; +extern Global_Input_Output_Tuple &set_vars; + +} // namespace + +#if ! defined DONT_INCLUDE_TEMPLATE_CODE +// with g++258, everything will need to make Tuple, as a +// function taking it as an argument is a friend of lots of classes +#include +#endif + +#endif diff --git a/lib/omega/include/omega/pres_cmpr.h b/lib/omega/include/omega/pres_cmpr.h new file mode 100644 index 0000000..fb3e6f0 --- /dev/null +++ b/lib/omega/include/omega/pres_cmpr.h @@ -0,0 +1,49 @@ +#if ! defined _pres_cmpr_h +#define _pres_cmpr_h 1 + +#include + +namespace omega { + +// +// Compressed problem: rectangular non-0 cut from the big problem. +// +class Comp_Constraints { +public: + Comp_Constraints(eqn *constrs, int no_constrs, int no_vars); + void UncompressConstr(eqn *constrs, short &pn_constrs); + ~Comp_Constraints(); + bool no_constraints() const + { return n_constrs == 0; } + int n_constraints() const + { return n_constrs; } + +protected: + inline int coef_index(int e, int v) + {return e*(n_vars+1) + v;} + +private: + int n_constrs; + int n_vars; + coef_t *coefs; +}; + +class Comp_Problem { +public: + Comp_Problem(Problem *problem); + Problem *UncompressProblem(); + bool no_constraints() const + { return eqs.no_constraints() && geqs.no_constraints(); } + +private: +/* === data === */ + int _nVars, _safeVars; + const char *(*_get_var_name)(unsigned int var, void *args); + void *_getVarNameArgs; + Comp_Constraints eqs; + Comp_Constraints geqs; +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_cnstr.h b/lib/omega/include/omega/pres_cnstr.h new file mode 100644 index 0000000..7b2d98d --- /dev/null +++ b/lib/omega/include/omega/pres_cnstr.h @@ -0,0 +1,192 @@ +#if ! defined _pres_cnstr_h +#define _pres_cnstr_h 1 + +#include +#include + +namespace omega { + +// +// Constraint handles +// + + + +void copy_constraint(Constraint_Handle H, const Constraint_Handle initial); + +class Constraint_Handle { +public: + Constraint_Handle() {} + virtual ~Constraint_Handle() {} + + void update_coef(Variable_ID, coef_t delta); + void update_const(coef_t delta); + coef_t get_coef(Variable_ID v) const; + coef_t get_const() const; + bool has_wildcards() const; + int max_tuple_pos() const; + int min_tuple_pos() const; + bool is_const(Variable_ID v); + bool is_const_except_for_global(Variable_ID v); + + virtual std::string print_to_string() const; + virtual std::string print_term_to_string() const; + + Variable_ID get_local(const Global_Var_ID G); + Variable_ID get_local(const Global_Var_ID G, Argument_Tuple of); + // not sure that the second one can be used in a meaningful + // way if the conjunct is in multiple relations + + void finalize(); + void multiply(int multiplier); + Rel_Body *relation() const; + + +protected: + Conjunct *c; + eqn **eqns; + int e; + + friend class Constr_Vars_Iter; + friend class Constraint_Iterator; + + Constraint_Handle(Conjunct *, eqn **, int); + +#if defined PROTECTED_DOESNT_WORK + friend class EQ_Handle; + friend class GEQ_Handle; +#endif + + void update_coef_during_simplify(Variable_ID, coef_t delta); + void update_const_during_simplify(coef_t delta); + coef_t get_const_during_simplify() const; + coef_t get_coef_during_simplify(Variable_ID v) const; + + +public: + friend class Conjunct; // assert_leading_info updates coef's + // as does move_UFS_to_input + friend class DNF; // and DNF::make_level_carried_to + + friend void copy_constraint(Constraint_Handle H, + const Constraint_Handle initial); + // copy_constraint does updates and gets at c and e + +}; + +class GEQ_Handle : public Constraint_Handle { +public: + inline GEQ_Handle() {} + + virtual std::string print_to_string() const; + virtual std::string print_term_to_string() const; + bool operator==(const Constraint_Handle &that); + + void negate(); + +private: + friend class Conjunct; + friend class GEQ_Iterator; + + GEQ_Handle(Conjunct *, int); +}; + + +class EQ_Handle : public Constraint_Handle { +public: + inline EQ_Handle() {} + + virtual std::string print_to_string() const; + virtual std::string print_term_to_string() const; + bool operator==(const Constraint_Handle &that); + +private: + friend class Conjunct; + friend class EQ_Iterator; + + EQ_Handle(Conjunct *, int); +}; + + +// +// Conjuct iterators -- for querying resulting DNF. +// +class Constraint_Iterator : public Generator { +public: + Constraint_Iterator(Conjunct *); + int live() const; + void operator++(int); + void operator++(); + Constraint_Handle operator* (); + Constraint_Handle operator* () const; + +private: + Conjunct *c; + int current,last; + eqn **eqns; +}; + + +class EQ_Iterator : public Generator { +public: + EQ_Iterator(Conjunct *); + int live() const; + void operator++(int); + void operator++(); + EQ_Handle operator* (); + EQ_Handle operator* () const; + +private: + Conjunct *c; + int current, last; +}; + + +class GEQ_Iterator : public Generator { +public: + GEQ_Iterator(Conjunct *); + int live() const; + void operator++(int); + void operator++(); + GEQ_Handle operator* (); + GEQ_Handle operator* () const; + +private: + Conjunct *c; + int current, last; +}; + + +// +// Variables of constraint iterator. +// +struct Variable_Info { + Variable_ID var; + coef_t coef; + Variable_Info(Variable_ID _var, coef_t _coef) + { var = _var; coef = _coef; } +}; + +class Constr_Vars_Iter : public Generator { +public: + Constr_Vars_Iter(const Constraint_Handle &ch, bool _wild_only = false); + int live() const; + void operator++(int); + void operator++(); + Variable_Info operator*() const; + + Variable_ID curr_var() const; + coef_t curr_coef() const; + +private: + eqn **eqns; + int e; + Problem *prob; + Variable_ID_Tuple &vars; + bool wild_only; + int current; +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_conj.h b/lib/omega/include/omega/pres_conj.h new file mode 100644 index 0000000..ea10a2c --- /dev/null +++ b/lib/omega/include/omega/pres_conj.h @@ -0,0 +1,299 @@ +#if ! defined _pres_conj_h +#define _pres_conj_h 1 + +#include +#include +#include +#include + +namespace omega { + +// +// Conjunct +// +// About variables in Conjunct: +// All varaibles appear in exactly one declaration. +// All variables used in Conjunct are referenced in mappedVars. +// Wildcard variables are referenced both in mappedVars and in myLocals, +// since they are declared in the conjunct. +// All other variables are declared at the levels above. +// Column number is: +// in forwardingAddress in Problem if variablesInitialized is set, +// equal to position of Variable_ID in mappedVars list otherwise. +// + +class Conjunct : public F_Declaration { +public: + Constraint_Iterator constraints(); + Variable_ID_Tuple *variables(); + EQ_Iterator EQs(); + GEQ_Iterator GEQs(); + inline int n_EQs() { return problem->nEQs; } + inline int n_GEQs() { return problem->nGEQs; } + + void promise_that_ub_solutions_exist(Relation &R); + + inline Node_Type node_type() {return Op_Conjunct;} + + inline int is_true() {return problem->nEQs==0 && problem->nGEQs==0 + && exact;} + + void query_difference(Variable_ID v1, Variable_ID v2, + coef_t &lowerBound, coef_t &upperBound, bool &guaranteed); + void query_variable_bounds(Variable_ID v, coef_t &lowerBound, coef_t &upperBound); + coef_t query_variable_mod(Variable_ID v, coef_t factor); + bool query_variable_used(Variable_ID v); + + int countNonzeros() const { + int numberNZs; + coef_t maxCoef, SumAbsCoef; + problem->difficulty(numberNZs,maxCoef,SumAbsCoef); + return numberNZs; + } + + void difficulty(int &numberNZs, coef_t &maxCoef, coef_t &SumAbsCoef) const { + problem->difficulty(numberNZs,maxCoef,SumAbsCoef); + } + + int query_guaranteed_leading_0s() { + count_leading_0s(); + return guaranteed_leading_0s; + } + + int query_possible_leading_0s() { + count_leading_0s(); + return possible_leading_0s; + } + + int query_leading_dir() { + count_leading_0s(); + return leading_dir; + } + + void calculate_dimensions(Relation &R, int &ndim_all, int &ndim_domain); + int max_ufs_arity_of_set(); + int max_ufs_arity_of_in(); + int max_ufs_arity_of_out(); + + int rank(); + + ~Conjunct(); + + bool is_unknown() const; + inline bool is_exact() const { return exact;} + inline bool is_inexact() const { return !exact;} + inline void make_inexact() { exact=false;} + + +#if ! defined NDEBUG + void assert_leading_info(); +#else + void assert_leading_info() {} +#endif + + + // PRINTING FUNCTIONS + void print(FILE *output_file); + void prefix_print(FILE *output_file, int debug = 1); + std::string print_to_string(int true_printed); + std::string print_EQ_to_string(eqn *e) { return problem->print_EQ_to_string(e); } + std::string print_GEQ_to_string(eqn *e) { return problem->print_GEQ_to_string(e); } + std::string print_EQ_to_string(int e) + { return problem->print_EQ_to_string(&(problem->EQs[e])); } + std::string print_GEQ_to_string(int e) + { return problem->print_GEQ_to_string(&(problem->GEQs[e])); } + std::string print_term_to_string(eqn *e) { return problem->print_term_to_string(e,1); } + std::string print_EQ_term_to_string(int e) + { return problem->print_term_to_string(&(problem->EQs[e]),1); } + std::string print_GEQ_term_to_string(int e) + { return problem->print_term_to_string(&(problem->GEQs[e]),1); } + std::string print_sub_to_string(int col) { return problem->print_sub_to_string(col); } + +private: + + inline void interpret_unknown_as_true() { exact=true;} + + friend Relation approx_closure(NOT_CONST Relation &r, int n); + + virtual Conjunct *really_conjunct(); + + + // create new constraints with all co-efficients 0 + // These are public in F_And, use them from there. + EQ_Handle add_stride(int step, int preserves_level = 0); + EQ_Handle add_EQ(int preserves_level = 0); + GEQ_Handle add_GEQ(int preserves_level = 0); + EQ_Handle add_EQ(const Constraint_Handle &c, int preserves_level = 0); + GEQ_Handle add_GEQ(const Constraint_Handle &c, int preserves_level = 0); + + friend class GEQ_Handle; + friend class EQ_Handle; + friend class Sub_Handle; + friend class Constraint_Handle; + friend class Constraint_Iterator; + friend class GEQ_Iterator; + friend class EQ_Iterator; + friend class Sub_Iterator; + friend class Constr_Vars_Iter; + + + // FUNCTIONS HAVING TO DO WITH BUILDING FORMULAS/DNFs + bool can_add_child(); + void remap(); + void beautify(); + DNF* DNFize(); + int priority(); + virtual Conjunct *find_available_conjunct(); + void finalize(); + + friend class DNF; + + + + // CREATING CONJUNCTS + Conjunct(); + Conjunct(Conjunct &); + Conjunct(Formula *, Rel_Body *); + + friend class Formula; // add_conjunct (a private function) creates Conjuncts + friend class F_Not; + friend class F_Or; + // class F_And; is a friend below + + + // VARIOUS FUNCTIONS TO CREATE / WORK WITH VARIABLES + Variable_ID declare(Const_String s); + Variable_ID declare(); + Variable_ID declare(Variable_ID v); + + friend const char *get_var_name(unsigned int, void *); + void push_exists(Variable_ID_Tuple &S); + int get_column(Variable_ID); + int find_column(Variable_ID); + int map_to_column(Variable_ID); + void combine_columns(); + void reorder(); + void reorder_for_print(bool reverseOrder=false, + int first_pass_input=0, + int first_pass_output=0, + bool sort=false); + + friend void remap_DNF_vars(Rel_Body *new_rel, Rel_Body *old_rel); + + void localize_var(Variable_ID D); + + + // this creates variables in conjuncts for us: + friend int new_WC(Conjunct *nc, Problem *np); + + + // UFS/LEADING ZEROS STUFF + + void move_UFS_to_input(); + + void count_leading_0s(); + void invalidate_leading_info(int changed = -1); + void enforce_leading_info(int guaranteed, int possible, int dir); + + void reverse_leading_dir_info(); + + + + // CONJUNCT SPECIFIC STUFF + + void rm_color_constrs(); + inline int N_protected() { return problem->safeVars; } + + + void ordered_elimination(int symLen) { problem->ordered_elimination(symLen);} + void convertEQstoGEQs(bool excludeStrides); + + int cost(); + + inline Formula* copy(Formula *parent, Rel_Body *reln) + { return copy_conj_diff_relation(parent,reln); } + Conjunct* copy_conj_diff_relation(Formula *parent, Rel_Body *reln); + inline Conjunct* copy_conj_same_relation() + { return copy_conj_diff_relation(&(parent()), relation()); } + friend void internal_copy_conjunct(Conjunct* to, Conjunct* fr); + friend void copy_constraint(Constraint_Handle H, + const Constraint_Handle initial); + +#if defined STUDY_EVACUATIONS + // The core function of "evac.c" does lots of work with conjuncts: + friend bool check_subseq_n(Conjunct *c, Sequence &evac_from, Sequence &evac_to, int n_from, int n_to, int max_arity, int n, bool allow_offset); + friend void assert_subbed_syms(Conjunct *c); + friend bool check_affine(Conjunct *d, Sequence &evac_from, Sequence &evac_to, int n_from, int n_to, int max_arity); + friend evac study(Conjunct *C, Sequence &evac_from, Sequence &evac_to, int n_from, int n_to, int max_arity); +#endif + + // The relational ops tend to do lots of demented things to Conjuncts: + friend class Rel_Body; + friend_rel_ops; + + // F_And sometimes absorbs conjuncts + friend class F_And; + + // Various DNFize functions also get a the problem: + + friend DNF* conj_and_not_dnf(Conjunct *pos_conj, DNF *neg_conjs, bool weak); + friend class F_Exists; + + // Substitutions are a wrapper around a low-level Problem operation + friend class Substitutions; + + // private functions to call problem functions + int simplifyProblem(); + int simplifyProblem(int verify, int subs, int redundantElimination); + int redSimplifyProblem(int effort, int computeGist); + + friend int simplify_conj(Conjunct* conj, int ver_sim, int elim_red, int color); + friend DNF* negate_conj(Conjunct* conj); + friend Conjunct* merge_conjs(Conjunct* conj1, Conjunct* conj2, + Merge_Action action, Rel_Body *body = 0); + friend void copy_conj_header(Conjunct* to, Conjunct* fr); + + + // === at last, the data === + + Variable_ID_Tuple mappedVars; + + int n_open_constraints; + bool cols_ordered; + bool simplified; + bool verified; + + int guaranteed_leading_0s; // -1 if unknown + int possible_leading_0s; // -1 if unknown + int leading_dir; // 0 if unknown, else +/- 1 + int leading_dir_valid_and_known(); + + bool exact; + + short r_constrs; // are redundant constraints eliminated? + Problem *problem; + + bool is_compressed(); + void compress(); + void uncompress(); + + friend class Comp_Problem; + Comp_Problem *comp_problem; +}; + + +/* === Misc. problem manipulation utilities === */ + +const int CantBeNegated = INT_MAX-10; +const int AvoidNegating = INT_MAX-11; + +void copy_column(Problem *tp, int to_col, + Problem *fp, int fr_col, + int start_EQ, int start_GEQ); +void zero_column(Problem *tp, int to_col, + int start_EQ, int start_GEQ, + int no_EQs, int no_GEQs); + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_decl.h b/lib/omega/include/omega/pres_decl.h new file mode 100644 index 0000000..7fec0bc --- /dev/null +++ b/lib/omega/include/omega/pres_decl.h @@ -0,0 +1,55 @@ +#if ! defined _pres_decl_h +#define _pres_decl_h 1 + +#include +#include +#include + +namespace omega { + +// +// Base class for presburger formula nodes with variables +// + +class F_Declaration : public Formula { +public: + virtual Variable_ID declare(Const_String s)=0; + virtual Variable_ID declare()=0; + virtual Variable_ID declare(Variable_ID)=0; + virtual Section declare_tuple(int size); + + void finalize(); + + inline Variable_ID_Tuple &locals() {return myLocals;} + +protected: + F_Declaration(Formula *, Rel_Body *); + F_Declaration(Formula *, Rel_Body *, Variable_ID_Tuple &); + ~F_Declaration(); + + Variable_ID do_declare(Const_String s, Var_Kind var_kind); + + void prefix_print(FILE *output_file, int debug = 1); + void print(FILE *output_file); + + void setup_names(); + void setup_anonymous_wildcard_names(); + + Variable_ID_Tuple myLocals; + friend class F_Forall; // rearrange needs to access myLocals + friend class F_Or; // push_exists + +private: + virtual bool can_add_child(); + + int priority(); + + friend void align(Rel_Body *originalr, Rel_Body *newr, F_Exists *fe, + Formula *f, const Mapping &mapping, bool &newrIsSet, + List &seen_exists, + Variable_ID_Tuple &seen_exists_ids); +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_dnf.h b/lib/omega/include/omega/pres_dnf.h new file mode 100644 index 0000000..93d5942 --- /dev/null +++ b/lib/omega/include/omega/pres_dnf.h @@ -0,0 +1,87 @@ +#if ! defined _pres_dnf_h +#define _pres_dnf_h 1 + +#include + +namespace omega { + +// +// Disjunctive Normal Form -- list of Conjuncts +// +class DNF { +public: + void print(FILE *out_file); + void prefix_print(FILE *out_file, int debug = 1, bool parent_names_setup=false); + + bool is_definitely_false() const; + bool is_definitely_true() const; + int length() const; + + Conjunct *single_conjunct() const; + bool has_single_conjunct() const; + Conjunct *rm_first_conjunct(); + void clear(); + int query_guaranteed_leading_0s(int what_to_return_for_empty_dnf); + int query_possible_leading_0s(int what_to_return_for_empty_dnf); + int query_leading_dir(); + +private: + // all DNFize functions need to access the dnf builders: + friend class F_And; + friend class F_Or; + friend class Conjunct; + friend DNF * negate_conj(Conjunct *); + + friend class Rel_Body; + friend_rel_ops; + + DNF(); + ~DNF(); + + DNF* copy(Rel_Body *); + + void simplify(); + void make_level_carried_to(int level); + void count_leading_0s(); + + void add_conjunct(Conjunct*); + void join_DNF(DNF*); + void rm_conjunct(Conjunct *c); + + void rm_redundant_conjs(int effort); + void rm_redundant_inexact_conjs(); + void DNF_to_formula(Formula* root); + + + friend void remap_DNF_vars(Rel_Body *new_rel, Rel_Body *old_rel); + void remap(); + + void setup_names(); + + void remove_inexact_conj(); + + // These may need to get at the conjList itself: + friend DNF* DNF_and_DNF(DNF*, DNF*); + friend DNF* DNF_and_conj(DNF*, Conjunct*); + friend DNF* conj_and_not_dnf(Conjunct *pos_conj, DNF *neg_conjs, bool weak); + + friend class DNF_Iterator; + + List conjList; +}; + +DNF* conj_and_not_dnf(Conjunct *pos_conj, DNF *neg_conjs, bool weak=false); + +// +// DNF iterator +// +class DNF_Iterator : public List_Iterator { +public: + DNF_Iterator(DNF*dnf) : List_Iterator(dnf->conjList) {} + DNF_Iterator() {} + void curr_set(Conjunct *c) { *(*this) = c; } +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_form.h b/lib/omega/include/omega/pres_form.h new file mode 100644 index 0000000..ed3258e --- /dev/null +++ b/lib/omega/include/omega/pres_form.h @@ -0,0 +1,112 @@ +#if ! defined _pres_form_h +#define _pres_form_h 1 + +#include + +namespace omega { + +typedef enum {Op_Relation, Op_Not, Op_And, Op_Or, + Op_Conjunct, Op_Forall, Op_Exists} Node_Type; + + +// +// Presburger Formula base class +// + +class Formula { +public: + virtual Node_Type node_type()=0; + + F_Forall *add_forall(); + F_Exists *add_exists(); + virtual F_And *and_with(); + F_And *add_and(); + F_Or *add_or(); + F_Not *add_not(); + void add_unknown(); + + virtual void finalize(); + virtual void print(FILE *output_file); + + Rel_Body *relation() { return myRelation; } + +protected: + virtual ~Formula(); +private: + Formula(Formula *, Rel_Body *); + + // The relational operations need to work with formula trees + friend class Relation; + friend_rel_ops; + // as do the functions that build DNF's + friend class DNF; + // or other parts of the tree + friend class Conjunct; + friend class F_Declaration; + friend class F_Exists; + friend class F_Forall; + friend class F_Or; + friend class F_And; + friend class F_Not; + friend class Rel_Body; + + + // Operations needed for manipulation of formula trees: + + void remove_child(Formula *); + void replace_child(Formula *child, Formula *new_child); + virtual bool can_add_child(); + void add_child(Formula *); + + Conjunct *add_conjunct(); + virtual Conjunct *find_available_conjunct() = 0; + + virtual Formula *copy(Formula *parent, Rel_Body *reln); + F_Exists *add_exists(Variable_ID_Tuple &S); + virtual void push_exists(Variable_ID_Tuple &S); + + // Accessor functions for tree building + + List &children() {return myChildren;} + int n_children() const {return myChildren.length();} + const List &get_children() const {return myChildren;} + Formula &parent() {return *myParent;} + void set_parent(Formula *p) {myParent = p;} + + + virtual int priority(); + + void verify_tree(); // should be const, but iterators are used + + virtual void reverse_leading_dir_info(); + virtual void invalidate_leading_info(int changed = -1); + virtual void enforce_leading_info(int guaranteed, int possible, int dir); + + virtual void remap(); + virtual DNF* DNFize() = 0; + virtual void beautify(); + virtual void rearrange(); + virtual void setup_names(); + + virtual void print_separator(FILE *output_file); + virtual void combine_columns(); + virtual void prefix_print(FILE *output_file, int debug = 1); + void print_head(FILE *output_file); + + void set_relation(Rel_Body *r); + void set_parent(Formula *parent, Rel_Body *reln); + + void assert_not_finalized(); + + virtual Conjunct *really_conjunct(); // until we get RTTI + +private: + List myChildren; + Formula *myParent; + Rel_Body *myRelation; + +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_gen.h b/lib/omega/include/omega/pres_gen.h new file mode 100644 index 0000000..ba6a793 --- /dev/null +++ b/lib/omega/include/omega/pres_gen.h @@ -0,0 +1,192 @@ +#if ! defined _pres_gen_h +#define _pres_gen_h 1 + +#include +#include +#include +#include +#include +#include +#include + +namespace omega { + +// +// general presburger stuff thats needed everywhere +// + +/* The following allows us to avoid warnings about passing + temporaries as non-const references. This is useful but + has suddenly become illegal. */ + +#if !defined(LIE_ABOUT_CONST_TO_MAKE_ANSI_COMMITTEE_HAPPY) +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)) +#define LIE_ABOUT_CONST_TO_MAKE_ANSI_COMMITTEE_HAPPY 1 +#else +#define LIE_ABOUT_CONST_TO_MAKE_ANSI_COMMITTEE_HAPPY 0 +#endif +#endif + +#if LIE_ABOUT_CONST_TO_MAKE_ANSI_COMMITTEE_HAPPY +#define NOT_CONST const +#else +#define NOT_CONST +#endif + +// +// I/O and error processing and control flags (also in omega_core/debugging.h) +// + +extern FILE *DebugFile; +extern int pres_debug; + +extern int mega_total; +extern int use_ugly_names; + +extern negation_control pres_legal_negations; + + +// +// Lots of things refer to each other, +// so we forward declare these classes: +// + +class Var_Decl; +typedef enum {Input_Var, Set_Var = Input_Var, Output_Var, + Global_Var, Forall_Var, Exists_Var, Wildcard_Var} Var_Kind; +class Global_Var_Decl; +typedef enum {Unknown_Tuple = 0, Input_Tuple = 1, Output_Tuple = 2, + Set_Tuple = Input_Tuple } Argument_Tuple; + +class Constraint_Handle; +class EQ_Handle; +class GEQ_Handle; +typedef EQ_Handle Stride_Handle; + +class Formula; +class F_Declaration; +class F_Forall; +class F_Exists; +class F_And; +class F_Or; +class F_Not; +class Conjunct; +class Relation; +class Rel_Body; +class DNF; +class Mapping; +class Omega_Var; +class Coef_Var_Decl; + +typedef Var_Decl *Variable_ID; +typedef Global_Var_Decl *Global_Var_ID; + +typedef Tuple Variable_ID_Tuple; +typedef Sequence Variable_ID_Sequence; // use only for rvalues +typedef Tuple_Iterator Variable_ID_Tuple_Iterator; +typedef Tuple_Iterator Variable_ID_Iterator; + +typedef Variable_ID_Iterator Variable_Iterator; + +typedef enum {Comb_Id, Comb_And, Comb_Or, Comb_AndNot} Combine_Type; + + +// things that are (hopefully) used only privately +class Comp_Problem; +class Comp_Constraints; + +// this has to be here rather than in pres_conj.h because +// MergeConj has to be a friend of Constraint_Handle +typedef enum {MERGE_REGULAR, MERGE_COMPOSE, MERGE_GIST} Merge_Action; + + +// Conjunct can be exact or lower or upper bound. +// For lower bound conjunct, the upper bound is assumed to be true; +// For upper bound conjunct, the lower bound is assumed to be false + +typedef enum {EXACT_BOUND, UPPER_BOUND, LOWER_BOUND, UNSET_BOUND} Bound_Type; + + +#if defined STUDY_EVACUATIONS +typedef enum { in_to_out = 0, out_to_in = 1} which_way; + +enum evac { evac_trivial = 0, + evac_offset = 1, + evac_subseq = 2, + evac_offset_subseq = 3, +// evac_permutation = , + evac_affine = 4, + evac_nasty = 5 }; + +extern char *evac_names[]; + +#endif + +// the following list should be updated in sync with Relations.h + +#define friend_rel_ops \ +friend Relation Union(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend Relation Intersection(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend Relation After(NOT_CONST Relation &R, int carried_by, int new_output, int dir);\ +friend Relation Extend_Domain(NOT_CONST Relation &R); \ +friend Relation Extend_Domain(NOT_CONST Relation &R, int more); \ +friend Relation Extend_Range(NOT_CONST Relation &R); \ +friend Relation Extend_Range(NOT_CONST Relation &R, int more); \ +friend Relation Extend_Set(NOT_CONST Relation &R); \ +friend Relation Extend_Set(NOT_CONST Relation &R, int more); \ +friend Relation Restrict_Domain(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend Relation Restrict_Range(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend Relation Domain(NOT_CONST Relation &r); \ +friend Relation Range(NOT_CONST Relation &r); \ +friend Relation Cross_Product(NOT_CONST Relation &A, NOT_CONST Relation &B); \ +friend Relation Inverse(NOT_CONST Relation &r); \ +friend Relation Deltas(NOT_CONST Relation &R); \ +friend Relation Deltas(NOT_CONST Relation &R, int eq_no); \ +friend Relation DeltasToRelation(NOT_CONST Relation &R, int n_input, int n_output); \ +friend Relation Complement(NOT_CONST Relation &r); \ +friend Relation Project(NOT_CONST Relation &R, Global_Var_ID v); \ +friend Relation Project(NOT_CONST Relation &r, int pos, Var_Kind vkind); \ +friend Relation Project(NOT_CONST Relation &S, Sequence &s); \ +friend Relation Project_Sym(NOT_CONST Relation &R); \ +friend Relation Project_On_Sym(NOT_CONST Relation &R, NOT_CONST Relation &context); \ +friend Relation GistSingleConjunct(NOT_CONST Relation &R1, NOT_CONST Relation &R2, int effort); \ +friend Relation Gist(NOT_CONST Relation &R1, NOT_CONST Relation &R2, int effort); \ +friend Relation Difference(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend Relation Approximate(NOT_CONST Relation &R, bool strides_allowed); \ +friend Relation Identity(int n_inp); \ +friend Relation Identity(NOT_CONST Relation &r); \ +friend bool do_subset_check(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend bool Must_Be_Subset(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend bool Might_Be_Subset(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend bool May_Be_Subset(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend bool Is_Obvious_Subset(NOT_CONST Relation &r1, NOT_CONST Relation &r2); \ +friend Relation Join(NOT_CONST Relation &G, NOT_CONST Relation &F); \ +friend Relation Composition(NOT_CONST Relation &F, NOT_CONST Relation &G); \ +friend bool can_do_exact_composition(NOT_CONST Relation &F, NOT_CONST Relation &G); \ +friend Relation EQs_to_GEQs(NOT_CONST Relation &, bool excludeStrides); \ +friend Relation Symbolic_Solution(NOT_CONST Relation &S); \ +friend Relation Symbolic_Solution(NOT_CONST Relation &S, Sequence &T); \ +friend Relation Sample_Solution(NOT_CONST Relation &S); \ +friend Relation Solution(NOT_CONST Relation &S, Sequence &T); \ +friend void MapRel1(Relation &inputRel, const Mapping &map, \ + Combine_Type ctype, int number_input, \ + int number_output, bool, bool); \ +friend Relation MapAndCombineRel2(Relation &R1, Relation &R2, \ + const Mapping &mapping1, \ + const Mapping &mapping2, \ + Combine_Type ctype, \ + int number_input, \ + int number_output); \ +friend void align(Rel_Body *, Rel_Body *, F_Exists *, \ + Formula *, const Mapping &, bool &, \ + List &, Variable_ID_Tuple &); \ +friend Relation Lower_Bound(NOT_CONST Relation &r); \ +friend Relation Upper_Bound(NOT_CONST Relation &r) + + +// REMEMBER - THE LAST LINE OF THE MACRO SHOULD NOT HAVE A ; +/* TransitiveClosure doesn't need to be in friend_rel_ops */ + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_logic.h b/lib/omega/include/omega/pres_logic.h new file mode 100644 index 0000000..27c4553 --- /dev/null +++ b/lib/omega/include/omega/pres_logic.h @@ -0,0 +1,90 @@ +#if ! defined _pres_logic_h +#define _pres_logic_h 1 + +#include + +namespace omega { +// +// Presburger formula classes for logical operations: and, or not +// + +class F_And : public Formula { +public: + inline Node_Type node_type() {return Op_And;} + + // "preserves level" should be 0 unless we know this will not + // change the "level" of the constraints - ie the number of + // leading corresponding in,out variables known to be equal + GEQ_Handle add_GEQ(int preserves_level = 0); + EQ_Handle add_EQ(int preserves_level = 0); + Stride_Handle add_stride(int step, int preserves_level = 0); + EQ_Handle add_EQ(const Constraint_Handle &c, int preserves_level = 0); + GEQ_Handle add_GEQ(const Constraint_Handle &c, int preserves_level = 0); + + F_And *and_with(); + void add_unknown(); + +private: + friend class Formula; // add_and() + F_And(Formula *p, Rel_Body *r); + +private: + Formula *copy(Formula *parent, Rel_Body *reln); + virtual Conjunct *find_available_conjunct(); + int priority(); + void print_separator(FILE *output_file); + void prefix_print(FILE *output_file, int debug = 1); + void beautify(); + DNF* DNFize(); + + Conjunct *pos_conj; +}; + + +class F_Or : public Formula { +public: + inline Node_Type node_type() {return Op_Or;} + +private: + friend class Formula; // add_or + F_Or(Formula *, Rel_Body *); + +private: + Formula *copy(Formula *parent, Rel_Body *reln); + + virtual Conjunct *find_available_conjunct(); + void print_separator(FILE *output_file); + void prefix_print(FILE *output_file, int debug = 1); + void beautify(); + int priority(); + DNF* DNFize(); + void push_exists(Variable_ID_Tuple &S); +}; + + +class F_Not : public Formula { +public: + inline Node_Type node_type() {return Op_Not;} + void finalize(); + +private: + friend class Formula; + F_Not(Formula *, Rel_Body *); + +private: + Formula *copy(Formula *parent, Rel_Body *reln); + + virtual Conjunct *find_available_conjunct(); + friend class F_Forall; + bool can_add_child(); + void beautify(); + void rearrange(); + int priority(); + DNF* DNFize(); + void print(FILE *output_file); + void prefix_print(FILE *output_file, int debug = 1); +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_quant.h b/lib/omega/include/omega/pres_quant.h new file mode 100644 index 0000000..98c30df --- /dev/null +++ b/lib/omega/include/omega/pres_quant.h @@ -0,0 +1,63 @@ +#if ! defined _pres_quant_h +#define _pres_quant_h 1 + +#include + +namespace omega { + +// +// Presburger formula nodes for quantifiers +// + +class F_Exists : public F_Declaration { +public: + inline Node_Type node_type() {return Op_Exists;} + Variable_ID declare(Const_String s); + Variable_ID declare(); + Variable_ID declare(Variable_ID v); + virtual void push_exists(Variable_ID_Tuple &S); + +protected: + friend class Formula; + + F_Exists(Formula *, Rel_Body *); + F_Exists(Formula *, Rel_Body *, Variable_ID_Tuple &); + +private: + Formula *copy(Formula *parent, Rel_Body *reln); + + virtual Conjunct *find_available_conjunct(); + void print(FILE *output_file); + void prefix_print(FILE *output_file, int debug = 1); + void beautify(); + void rearrange(); + DNF* DNFize(); +}; + + +class F_Forall : public F_Declaration { +public: + inline Node_Type node_type() {return Op_Forall;} + Variable_ID declare(Const_String s); + Variable_ID declare(); + Variable_ID declare(Variable_ID v); + +protected: + friend class Formula; + + F_Forall(Formula *, Rel_Body *); + +private: + Formula *copy(Formula *parent, Rel_Body *reln); + + virtual Conjunct *find_available_conjunct(); + void print(FILE *output_file); + void prefix_print(FILE *output_file, int debug = 1); + void beautify(); + void rearrange(); + DNF* DNFize(); +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_subs.h b/lib/omega/include/omega/pres_subs.h new file mode 100644 index 0000000..8a9ee92 --- /dev/null +++ b/lib/omega/include/omega/pres_subs.h @@ -0,0 +1,88 @@ +#if !defined(pres_subs_h) +#define pres_subs_h + +/* Interface to omega core's substitutions. + + Creating an object of class Substitutions causes ordered elimination, + i.e. variables in the input and output tuples are substituted for by + functions of earlier variables. Could conceivablely create a more + flexible interface to orderedElimination if we developed a way to + specify the desired variable order. + + This is not an entirely consistent interface, since Sub_Handles + shouldn't really permit update_coef on SUBs. It is not a real + problem since subs are now no longer part of a conjunct, but it is + a slightly odd situation. + + Don't try to simplify r after performing orderedElimination. +*/ + + +#include +#include +#include +#include + +namespace omega { + +class Sub_Handle; +class Sub_Iterator; + +class Substitutions { +public: + Substitutions(Relation &input_R, Conjunct *input_c); + ~Substitutions(); + Sub_Handle get_sub(Variable_ID v); + bool substituted(Variable_ID v); + bool sub_involves(Variable_ID v, Var_Kind kind); +private: + friend class Sub_Iterator; + friend class Sub_Handle; + Relation *r; + Conjunct *c; + eqn *subs; + Variable_ID_Tuple subbed_vars; +}; + + +//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +class Sub_Handle: public Constraint_Handle { +public: + inline Sub_Handle() {} + + virtual std::string print_to_string() const; + virtual std::string print_term_to_string() const; + Variable_ID variable() {return v;} + +private: + friend class Substitutions; + friend class Sub_Iterator; + Sub_Handle(Substitutions *, int, Variable_ID); +// Sub_Handle(Substitutions *, int); + + Variable_ID v; +}; + +//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +class Sub_Iterator : public Generator { +public: + Sub_Iterator(Substitutions *input_s): s(input_s), current(0), + last(s->c->problem->nSUBs-1) {} + int live() const; + void operator++(int); + void operator++(); + Sub_Handle operator* (); + Sub_Handle operator* () const; + +private: + Substitutions *s; + int current, last; +}; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/pres_tree.h b/lib/omega/include/omega/pres_tree.h new file mode 100644 index 0000000..ad78ad0 --- /dev/null +++ b/lib/omega/include/omega/pres_tree.h @@ -0,0 +1,15 @@ +#if ! defined _pres_tree_h +#define _pres_tree_h 1 + +// +// Header to include if you need all the classes to build +// a Presburger formula: +// variables, constraints, nodes for logical operations & quantifiers +// + +#include +#include +#include +#include + +#endif diff --git a/lib/omega/include/omega/pres_var.h b/lib/omega/include/omega/pres_var.h new file mode 100644 index 0000000..bf60dcb --- /dev/null +++ b/lib/omega/include/omega/pres_var.h @@ -0,0 +1,230 @@ +#if ! defined _pres_var_h +#define _pres_var_h 1 + +#include +#include + +namespace omega { + +// +// Variable declaration. +// Variables are free or quantified. +// Free variables are classified as input, output and global. +// Quantified variables are classified as forall, exists and wildcard. +// All global variables are functions symbols of (possibly 0) arguments +// Local variables that correspond to >0-ary functions are identified +// as functions of a prefix of the input, output, or both tuples +// +// +// typedef enum {Input_Var, Output_Var, Set_Var, +// Global_Var, Forall_Var, Exists_Var, Wildcard_Var} Var_Kind; + +typedef enum {Free_Var, Coef_Var, Bomega_Var} Global_Kind; + +// NOW IN PRES_GEN.H, as its used as an argument and can't +// be forward declared: +// typedef enum {Unknown_Tuple = 0, Input_Tuple = 1, Output_Tuple = 2, +// Set_Tuple = Input_Tuple } Argument_Tuple; +// Only Input, Output, and Set can be passed to get_local, +// but the values 0 and 3 are also used internally. + + +class Var_Decl { +public: + inline Var_Kind kind() { return var_kind; } + int get_position(); + Global_Var_ID get_global_var(); + Argument_Tuple function_of(); // valid iff kind() == Global_var + + Const_String base_name; + void name_variable(char *newname); + + // The following should be used with care, as they are only valid + // after setup_names has been used on the relation containing this + // variable. + std::string name(); + const char* char_name(); + void set_kind(Var_Kind v) { var_kind = v; } + + // Operation to allow the remap field to be used for + // union-find operations on variables. + // Be sure to reset the remap fields afterward + void UF_union(Variable_ID v); + Variable_ID UF_owner(); + +private: + Var_Decl(Const_String name, Var_Kind vkind, int pos); + Var_Decl(Var_Kind vkind, int pos); + Var_Decl(Variable_ID v); + Var_Decl(Const_String name, Global_Var_ID v); + Var_Decl(Const_String name, Global_Var_ID v, Argument_Tuple function_of); + + friend class F_Declaration; // creates local variables + friend class Global_Var_Decl; // its constructors create Var_Decls. + + friend class Global_Input_Output_Tuple; + friend void copy_var_decls(Variable_ID_Tuple &new_vl, Variable_ID_Tuple &vl); + +private: + int instance; + void setup_name(); + + // these set up the names + friend class Rel_Body; +// friend class F_Declaration; already a friend + +private: + Variable_ID remap; // pointer to new copy of this node + + // lots of things need to get at "remap" - lots of relation ops, + // and functions that move UFS's around: + // dnf::make_level_carried_to and Conjunct::move_UFS_to_input() + // Also of course Conjunct::remap and push_exists + friend_rel_ops; + friend class DNF; + friend class Conjunct; + + // this prints remap to the debugging output + friend void print_var_addrs(std::string &s, Variable_ID v); + + friend void reset_remap_field(Variable_ID v); + friend void reset_remap_field(Sequence &S); + friend void reset_remap_field(Sequence &S, int var_no); + friend void reset_remap_field(Variable_ID_Tuple &S); + friend void reset_remap_field(Variable_ID_Tuple &S, int var_no); + +private: + + Var_Kind var_kind; + int position; // only for Input_Var, Output_Var + Global_Var_ID global_var; // only for Global_Var + Argument_Tuple of; // only for Global_Var +}; + +bool rm_variable(Variable_ID_Tuple &vl, Variable_ID v); +void reset_remap_field(Sequence &S); +void reset_remap_field(Sequence &S, int var_no); +void reset_remap_field(Variable_ID v); +void reset_remap_field(Variable_ID_Tuple &S); +void reset_remap_field(Variable_ID_Tuple &S, int var_no); + +class Global_Input_Output_Tuple: public Tuple { +public: + Global_Input_Output_Tuple(Var_Kind in_my_kind, int init=-1); + ~Global_Input_Output_Tuple(); + virtual Variable_ID &operator[](int index); + virtual const Variable_ID &operator[](int index) const; +private: + Var_Kind my_kind; + static const int initial_allocation; +}; + +extern Global_Input_Output_Tuple input_vars; +extern Global_Input_Output_Tuple output_vars; +// This allows the user to refer to set_vars to query sets, w/o knowing +// they are really inputs. +extern Global_Input_Output_Tuple &set_vars; + +Variable_ID input_var(int nth); +Variable_ID output_var(int nth); +Variable_ID set_var(int nth); + + + +// +// Global_Var_ID uniquely identifies global var-s through the whole program. +// Global_Var_Decl is an ADT with the following operations: +// - create global variable, +// - find the arity of the variable, (default = 0, for symbolic consts) +// - get the name of global variable, +// - tell if two variables are the same (if they are the same object) +// + +class Global_Var_Decl { +public: + Global_Var_Decl(Const_String baseName); + + virtual Const_String base_name() const + { + return loc_rep1.base_name; + } + + virtual void set_base_name(Const_String newName) + { + loc_rep1.base_name = newName; + loc_rep2.base_name = newName; + } + + virtual int arity() const + { + return 0; // default compatible with old symbolic constant stuff + } + + virtual Omega_Var *really_omega_var(); // until we get RTTI in C++ + virtual Coef_Var_Decl *really_coef_var(); // until we get RTTI in C++ + virtual Global_Kind kind() const; + +private: + + friend class Rel_Body; // Rel_Body::get_local calls this get_local + + Variable_ID get_local() + { + assert(arity() == 0); + return &loc_rep1; + } + Variable_ID get_local(Argument_Tuple of) + { + assert(arity() == 0 || of == Input_Tuple || of == Output_Tuple); + return ((arity() == 0 || of == Input_Tuple) ? &loc_rep1 : &loc_rep2); + } + + // local representative, there is just 1 for every 0-ary global variable + Var_Decl loc_rep1; // arity == 0, or arity > 0 and of == In + Var_Decl loc_rep2; // arity > 0 and of == Out + +public: +// friend class Rel_Body; // Rel_Body::setup_names sets instance + friend class Var_Decl; + int instance; +}; + + +class Coef_Var_Decl : public Global_Var_Decl { +public: + Coef_Var_Decl(int id, int var); + int stmt() const; + int var() const; + virtual Global_Kind kind() const; + virtual Coef_Var_Decl *really_coef_var(); // until we get RTTI in C++ + +private: + int i, v; +}; + + + +// +// Test subclass for Global_Var: named global variable +// +class Free_Var_Decl : public Global_Var_Decl { +public: + Free_Var_Decl(Const_String name); + Free_Var_Decl(Const_String name, int arity); + int arity() const; + virtual Global_Kind kind() const; + +private: + int _arity; +}; + + +/* === implementation functions === */ +void copy_var_decls(Variable_ID_Tuple &new_vl, Variable_ID_Tuple &vl); +void free_var_decls(Variable_ID_Tuple &vl); + +extern int wildCardInstanceNumber; + +} // namespace + +#endif diff --git a/lib/omega/include/omega/reach.h b/lib/omega/include/omega/reach.h new file mode 100644 index 0000000..76d7dee --- /dev/null +++ b/lib/omega/include/omega/reach.h @@ -0,0 +1,23 @@ +#if ! defined _reach_h +#define _reach_h 1 + +namespace omega { + +class reachable_information { +public: + Tuple node_names; + Tuple node_arity; + DynamicArray1 start_nodes; + DynamicArray2 transitions; +}; + + +DynamicArray1 * +Reachable_Nodes(reachable_information * reachable_info); + +DynamicArray1 * +I_Reachable_Nodes(reachable_information * reachable_info); + +} // namespace + +#endif -- cgit v1.2.3-70-g09d2