aboutsummaryrefslogtreecommitdiff
path: root/Carpet/CarpetLib
diff options
context:
space:
mode:
authorErik Schnetter <schnetter@cct.lsu.edu>2006-12-05 21:13:00 +0000
committerErik Schnetter <schnetter@cct.lsu.edu>2006-12-05 21:13:00 +0000
commit78399cd596a0c60fcea2d736505d5b478144503d (patch)
tree48ba54f4893f4e9f9f5c2382a727e131802b7569 /Carpet/CarpetLib
parentd4a3f9722bbaf09de6963e7ec07a2274c2cf9f4d (diff)
CarpetLib: Use better algorithm to combine bboxes in bboxset's normalize()
The new algorithm always finds the same canonical configuration of bboxes, independent of how the bboxset is split into bboxes. There is no guarantee that the new representation uses the minimum number of bboxes, since that would be too difficult. darcs-hash:20061205211342-dae7b-2eee2ac16cea06b3ee4fc623deb086d380d5ed37.gz
Diffstat (limited to 'Carpet/CarpetLib')
-rw-r--r--Carpet/CarpetLib/src/bboxset.cc171
1 files changed, 107 insertions, 64 deletions
diff --git a/Carpet/CarpetLib/src/bboxset.cc b/Carpet/CarpetLib/src/bboxset.cc
index 76f2a2083..7725e899b 100644
--- a/Carpet/CarpetLib/src/bboxset.cc
+++ b/Carpet/CarpetLib/src/bboxset.cc
@@ -1,3 +1,4 @@
+#include <algorithm>
#include <cassert>
#include <iostream>
#include <limits>
@@ -57,74 +58,116 @@ bool bboxset<T,D>::invariant () const {
// Normalisation
template<class T, int D>
-void bboxset<T,D>::normalize () {
+void bboxset<T,D>::normalize ()
+{
assert (invariant());
- const int num_initial_boxes = bs.size();
- int num_combined_boxes = 0;
- stack<box> todo, done;
- for (typename set<box>::const_iterator elt = bs.begin(); elt != bs.end(); ++elt) {
- done.push (*elt);
+
+ bboxset const oldbs = * this;
+ int const oldsize = this->size();
+
+ // Split all bboxes into small pieces which have all their
+ // boundaries aligned.
+ for (int d=0; d<D; ++d) {
+ // Find all boundaries
+ set<T> sbnds;
+ for (typename bset::const_iterator si = bs.begin(); si != bs.end(); ++ si) {
+ box const & b = * si;
+ int const bstr = b.stride()[d];
+ int const blo = b.lower()[d];
+ int const bhi = b.upper()[d] + bstr;
+ sbnds.insert (blo);
+ sbnds.insert (bhi);
+ }
+ // Split bboxes
+ bset nbs;
+ for (typename bset::const_iterator si = bs.begin(); si != bs.end(); ++ si) {
+ box const & b = * si;
+ int const bstr = b.stride()[d];
+ int const blo = b.lower()[d];
+ int const bhi = b.upper()[d] + bstr;
+ typename set<T>::const_iterator const ilo
+ = find (sbnds.begin(), sbnds.end(), blo);
+ typename set<T>::const_iterator const ihi
+ = find (sbnds.begin(), sbnds.end(), bhi);
+ assert (ilo != sbnds.end());
+ assert (ihi != sbnds.end());
+ assert (* ilo == blo);
+ assert (* ihi == bhi);
+ // Split one bbox
+ for (typename set<T>::const_iterator curr = ilo; curr != ihi; ++ curr) {
+ typename set<T>::const_iterator next = curr;
+ advance (next, 1);
+ int const nblo = * curr;
+ int const nbhi = * next;
+ box nb (b.lower().replace(d, nblo),
+ b.upper().replace(d, nbhi - bstr),
+ b.stride());
+ nbs.insert (nb);
+ }
+ }
+ // Replace old set
+ bs.swap (nbs);
+ assert (invariant());
}
- int old_num_combined_boxes;
- do {
- old_num_combined_boxes = num_combined_boxes;
- // TODO: This will not catch all cases where bboxes can be combined.
- for (int d=0; d<D; ++d) {
- todo = done;
- done = stack<box>();
- while (! todo.empty()) {
- restart:;
- box item = todo.top();
- todo.pop();
- stack<box> work = done;
- done = stack<box>();
- while (! work.empty()) {
- box comp = work.top();
- work.pop();
- {
- assert (all(comp.stride() == item.stride()));
- if (comp.upper()[d] + item.stride()[d] == item.lower()[d]) {
- if (all((comp.lower() == item.lower()
- && comp.upper() == item.upper()).replace (d, true))) {
- box newbox = box(comp.lower(), item.upper(), item.stride());
- todo.push (newbox);
- while (! work.empty()) {
- done.push (work.top());
- work.pop();
- }
- ++num_combined_boxes;
- goto restart;
- }
- }
- if (item.upper()[d] + item.stride()[d] == comp.lower()[d]) {
- if (all((comp.lower() == item.lower()
- && comp.upper() == item.upper()).replace (d, true))) {
- box newbox = box(item.lower(), comp.upper(), item.stride());
- todo.push (newbox);
- while (! work.empty()) {
- done.push (work.top());
- work.pop();
- }
- ++num_combined_boxes;
- goto restart;
- }
- }
+
+ // Combine bboxes if possible
+ for (int d=0; d<D; ++d) {
+ bset nbs;
+ while (not bs.empty()) {
+ typename bset::iterator si = bs.begin();
+ assert (si != bs.end());
+
+ box const b = * si;
+ int const bstr = b.stride()[d];
+ int const blo = b.lower()[d];
+ int const bhi = b.upper()[d] + bstr;
+
+ for (typename bset::iterator nsi = nbs.begin(); nsi != nbs.end(); ++ nsi)
+ {
+ box const nb = * nsi;
+ int const nblo = nb.lower()[d];
+ int const nbhi = nb.upper()[d] + bstr;
+
+ box const mb (nb.lower().replace(d, blo),
+ nb.upper().replace(d, bhi - bstr),
+ nb.stride());
+
+ // Check whether the other dimensions match
+ if (b == mb) {
+ // Check whether the bboxes are adjacent in this dimension
+ if (nbhi == blo) {
+ // Combine boxes, nb < b
+ box const cb (b.lower().replace(d, nblo),
+ b.upper(),
+ b.stride());
+ bs.erase (si);
+ nbs.erase (nsi);
+ bs.insert (cb);
+ goto done;
+ } else if (bhi == nblo) {
+ // Combine boxes, b < nb
+ box const cb (b.lower(),
+ b.upper().replace(d, nbhi - bstr),
+ b.stride());
+ bs.erase (si);
+ nbs.erase (nsi);
+ bs.insert (cb);
+ goto done;
}
- done.push (comp);
- } // while work
- done.push (item);
- } // while todo
- } // for d
- } while (num_combined_boxes > old_num_combined_boxes);
- bs.clear();
- while (! done.empty()) {
- bs.insert (done.top());
- done.pop();
+ }
+ }
+ bs.erase (si);
+ nbs.insert (b);
+ done:;
+ }
+ bs.swap (nbs);
+ assert (invariant());
}
- const int num_final_boxes = bs.size();
- assert (num_final_boxes <= num_initial_boxes);
- assert (num_initial_boxes - num_combined_boxes == num_final_boxes);
- assert (invariant());
+
+ int const newsize = this->size();
+
+ assert (*this == oldbs);
+ assert (newsize <= oldsize);
}