#ifndef BBOXSET_HH #define BBOXSET_HH #include #include #include #include #include #include "bbox.hh" #include "defs.hh" #include "vect.hh" using namespace std; // Choose the implementation of bboxset by #defining exactly one of // these #undef BBOXSET_SET // outdated #undef BBOXSET_LIST // well tested #define BBOXSET_VECTOR // brand new // Forward declaration template class bboxset; // template // bboxset operator+ (const bbox& b1, const bbox& b2); // template // bboxset operator+ (const bbox& b, const bboxset& s); // template // bboxset operator- (const bbox& b1, const bbox& b2); // template // bboxset operator- (const bbox& b, const bboxset& s); // Input template istream& operator>> (istream& is, bboxset& s); // Output template ostream& operator<< (ostream& os, const bboxset& s); // Bounding box set class template class bboxset { // Cost annotations depend on the number of bset elements n, and // assume that normalization is skipped. struct skip_normalize_t { bboxset& s; bool const saved_skip_normalize; skip_normalize_t(bboxset& s_) : s(s_), saved_skip_normalize(s.skip_normalize) { s.skip_normalize = true; } ~skip_normalize_t() { s.skip_normalize = saved_skip_normalize; s.normalize(); } }; // Types typedef bbox box; #ifdef BBOXSET_SET //S typedef set bset; #endif #ifdef BBOXSET_LIST typedef list bset; #endif #ifdef BBOXSET_VECTOR typedef vector bset; #endif // Fields bset bs; // Invariant: // All bboxes have the same stride. // No bbox is empty. // The bboxes don't overlap. bool skip_normalize; public: // Constructors bboxset (); // cost: O(1) bboxset (const box& b); // cost: O(1) bboxset (const bboxset& s); // cost: O(n) bboxset (const list& lb); bboxset (const vector& lb); bboxset (const vector >& vlb); template bboxset (const vector& vb, const bbox U::* const v); template bboxset (const vector& vb, const bboxset U::* const v); static bboxset poison (); // Invariant bool invariant () const CCTK_MEMBER_ATTRIBUTE_PURE; private: // Normalisation void normalize (); public: // Accessors bool empty () const { return bs.empty(); } // cost: O(1) // T size () const; typedef typename box::size_type size_type; size_type size () const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) int setsize () const { return bs.size(); } // cost: O(1) // Find out whether the bbox contains the point x bool contains (const vect& x) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) // Find out whether this bboxset intersects the bbox b bool intersects (const box& b) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) // Add (bboxes that don't overlap) bboxset& operator+= (const box& b); // cost: O(1) bboxset& operator+= (const bboxset& s); // cost: O(n) bboxset& add_transfer (bboxset& s); // cost: O(1) bboxset operator+ (const box& b) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) bboxset operator+ (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) // Union bboxset& operator|= (const box& b); // cost: O(n) bboxset& operator|= (const bboxset& s); // cost: O(n^2) bboxset operator| (const box& b) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) bboxset operator| (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n^2) // Intersection bboxset operator& (const box& b) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) bboxset operator& (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) bboxset& operator&= (const box& b); // cost: O(n) bboxset& operator&= (const bboxset& s); // cost: O(n) // Difference // friend bboxset operator- (const box& b1, const box& b2); static bboxset minus (const box& b1, const box& b2) CCTK_ATTRIBUTE_PURE; // cost: O(1) bboxset operator- (const box& b) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) // cost: O(n) bboxset& operator-= (const box& b) { *this = *this - b; assert (invariant()); return *this; } bboxset& operator-= (const bboxset& s); // cost: O(n^2) bboxset operator- (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n^2) // friend bboxset operator- (const box& b, const bboxset& s); static bboxset minus (const box& b, const bboxset& s) CCTK_ATTRIBUTE_PURE; // cost: O(n^2) /** Find a bbox containing the whole set. */ box container () const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n) /** Find the pseudo-inverse. */ bboxset pseudo_inverse (const int n) const CCTK_MEMBER_ATTRIBUTE_PURE; /** Expand (enlarge) the bboxset by multiples of the stride. */ bboxset expand (const vect& lo, const vect& hi) const CCTK_MEMBER_ATTRIBUTE_PURE; bboxset expand (const vect,2>& lohi) const { return expand (lohi[0], lohi[1]); } /** Shift the bboxset by multiples of the stride. */ bboxset shift (const vect& v) const { return expand (-v, v); } /** Expand (enlarge) the bboxset by multiples of a fraction of the stride. */ // cost: O(n^2) in general, but only O(n) for shifting bboxset expand (const vect& lo, const vect& hi, const vect& denom) const CCTK_MEMBER_ATTRIBUTE_PURE; // cost: O(n^2) in general, but only O(n) for shifting bboxset expand (const vect,2>& lohi, const vect& denom) const { return expand (lohi[0], lohi[1], denom); } /** Shift the bboxset by multiples of a fraction of the stride. */ // cost: O(n) bboxset shift (const vect& v, const vect& denom) const { return expand (-v, v, denom); } /** Find the smallest b-compatible box around this bbox. ("compatible" means having the same stride.) */ bboxset expanded_for (const box& b) const CCTK_MEMBER_ATTRIBUTE_PURE; // TODO: this is incorrect #if 1 /** Find the largest b-compatible box inside this bbox. */ bboxset contracted_for (const box& b) const CCTK_MEMBER_ATTRIBUTE_PURE; #endif // Equality bool operator== (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; bool operator!= (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; bool operator< (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; bool operator<= (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; bool operator> (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; bool operator>= (const bboxset& s) const CCTK_MEMBER_ATTRIBUTE_PURE; // Iterators typedef typename bset::const_iterator const_iterator; typedef typename bset::iterator iterator; const_iterator begin () const { return bs.begin(); } const_iterator end () const { return bs.end(); } // iterator begin () const { return bs.begin(); } // iterator end () const { return bs.end(); } // Memory usage size_t memory () const { return memoryof (bs); } // Input istream& input (istream& is); // Output ostream& output (ostream& os) const; }; template inline bboxset operator+ (const bbox& b1, const bbox& b2) { return bboxset(b1) + bboxset(b2); } template inline bboxset operator+ (const bbox& b, const bboxset& s) { return bboxset(b) + s; } // cost: O(1) template inline bboxset operator- (const bbox& b1, const bbox& b2) { return bboxset::minus(b1,b2); } // cost: O(n^2) template inline bboxset operator- (const bbox& b, const bboxset& s) { return bboxset::minus(b,s); } template inline bboxset operator| (const bbox& b, const bboxset& s) { return s | b; } template inline bboxset operator& (const bbox& b, const bboxset& s) { return s & b; } template inline bool operator== (const bbox& b, const bboxset& s) { return bboxset(b) == s; } template inline bool operator!= (const bbox& b, const bboxset& s) { return bboxset(b) != s; } template inline bool operator< (const bbox& b, const bboxset& s) { return bboxset(b) < s; } template inline bool operator<= (const bbox& b, const bboxset& s) { return bboxset(b) <= s; } template inline bool operator> (const bbox& b, const bboxset& s) { return bboxset(b) > s; } template inline bool operator>= (const bbox& b, const bboxset& s) { return bboxset(b) >= s; } template inline bool operator== (const bboxset& s, const bbox& b) { return s == bboxset(b); } template inline bool operator!= (const bboxset& s, const bbox& b) { return s != bboxset(b); } template inline bool operator< (const bboxset& s, const bbox& b) { return s < bboxset(b); } template inline bool operator<= (const bboxset& s, const bbox& b) { return s <= bboxset(b); } template inline bool operator> (const bboxset& s, const bbox& b) { return s > bboxset(b); } template inline bool operator>= (const bboxset& s, const bbox& b) { return s >= bboxset(b); } // Memory usage template inline size_t memoryof (bboxset const & s) { return s.memory(); } // Input template inline istream& operator>> (istream& is, bboxset& s) { return s.input(is); } // Output template inline ostream& operator<< (ostream& os, const bboxset& s) { return s.output(os); } #endif // BBOXSET_HH