| version 1.3 | version 1.4 |
|---|
| |
| */ | */ |
| class Element_Bucket { | class Element_Bucket { |
| public: | public: |
| /// This is a heap data structure used to sort elements | /// This is a bucket data structure used to sort elements |
| typedef struct { | typedef struct { |
| int elID; | int elID; // the element ID |
| double len; | double len; // the sorting criteria |
| } elemHeap; | int leftIdx; // lesser elements |
| /// Elements to coarsen (ordered smallest to largest) | int rightIdx; // greater elements |
| elemHeap *coarsenElements; | } elemEntry; |
| /// Elements to refine (ordered largest to smallest) | /// Element bucket |
| elemHeap *refineElements; | elemEntry *elements; |
| /// A stack of elements used for refine | /// The number of entries in the bucket |
| elemHeap *refineStack; | int numElements; |
| /// The number of entries in the coarsen heap | /// The number of spaces in the bucket |
| int coarsenHeapSize; | int bucketSz; |
| /// The number of entries in the refine heap | /// index of the first element in the bucket |
| int refineHeapSize; | int root; |
| /// The number of entries in refinestack | |
| int refineTop; | |
| Element_Bucket() { | Element_Bucket() { |
| coarsenHeapSize = refineHeapSize = refineTop = 0; | root = -1; |
| coarsenElements = refineElements = refineStack = NULL; | numElements = bucketSz = 0; |
| | elements = NULL; |
| } | } |
| void Reset(int numElements) { | void Alloc(int n) { |
| if (refineStack) delete [] refineStack; | elements = new elemEntry[n]; |
| refineStack = new elemHeap[numElements]; | for (int i=0; i<n; i++) { |
| if (refineElements) delete [] refineElements; | elements[i].elID = -1; |
| refineElements = new elemHeap[numElements+1]; | elements[i].len = -1.0; |
| } | elements[i].leftIdx = -1; |
| bool RefineEmpty() { | elements[i].rightIdx = -1; |
| return((refineHeapSize==0) && (refineTop==0)); | |
| } | |
| int Delete_Top() { | |
| if (refineTop > 0) { | |
| refineTop--; | |
| return refineStack[refineTop].elID; | |
| } | } |
| return -1; | bucketSz = n; |
| | numElements = 0; |
| | root = -1; |
| | } |
| | void Resize(int n) { |
| | elemEntry *newBkt = new elemEntry[n]; |
| | for (int i=0; i<n; i++) { |
| | newBkt[i].elID = -1; |
| | newBkt[i].len = -1.0; |
| | newBkt[i].leftIdx = -1; |
| | newBkt[i].rightIdx = -1; |
| | } |
| | for (int i=0; i<bucketSz; i++) { |
| | newBkt[i].elID = elements[i].elID; |
| | newBkt[i].len = elements[i].len; |
| | newBkt[i].leftIdx = elements[i].leftIdx; |
| | newBkt[i].rightIdx = elements[i].rightIdx; |
| } | } |
| | bucketSz = n; |
| | if (elements) delete[] elements; |
| | elements = newBkt; |
| | } |
| | void Clear() { |
| | if (elements) delete[] elements; |
| | bucketSz = numElements = 0; |
| | root = -1; |
| | } |
| | bool IsBucketEmpty() { return(numElements == 0); } |
| /// Insert element to be refined/coarsened | /// Insert element to be refined/coarsened |
| void Insert(int elID, double len, int cFlag); | void Insert(int elID, double len) { |
| /// Get next element to be refined/coarsenen | CkAssert(numElements <= bucketSz); |
| int Delete_Min(int cFlag, double *len); | if (numElements == bucketSz) { |
| | Resize(bucketSz+100); |
| | } |
| | CkAssert(elID < bucketSz); |
| | if (root==-1) { |
| | root = 0; |
| | elements[0].elID = elID; |
| | elements[0].len = len; |
| | elements[0].leftIdx = elements[0].rightIdx = -1; |
| | numElements++; |
| | } |
| | else { |
| | int pos = findEmptySlot(); |
| | elements[pos].elID = elID; |
| | elements[pos].len = len; |
| | elements[pos].leftIdx = elements[pos].rightIdx = -1; |
| | if ((len < elements[root].len) || ((len == elements[root].len) && (elID < elements[root].elID))) { |
| | // go left |
| | if (elements[root].leftIdx == -1) { |
| | elements[root].leftIdx = pos; |
| | } |
| | else { |
| | Insert_help(elements[root].leftIdx, pos); |
| | } |
| | numElements++; |
| | } |
| | else if ((len > elements[root].len) || ((len == elements[root].len) && (elID >= elements[root].elID))) { |
| | // go right |
| | if (elements[root].rightIdx == -1) { |
| | elements[root].rightIdx = pos; |
| | } |
| | else { |
| | Insert_help(elements[root].rightIdx, pos); |
| | } |
| | numElements++; |
| | } |
| | else { // invalid case |
| | CkAbort("ERROR: Element_Bucket::Insert: unreachable case!\n"); |
| | } |
| | } |
| | sanity_check(); |
| | } |
| | |
| | void Insert_help(int subtree, int pos) { |
| | if ((elements[pos].len < elements[subtree].len) || |
| | ((elements[pos].len == elements[subtree].len) && (elements[pos].elID < elements[subtree].elID))) { |
| | // go left |
| | if (elements[subtree].leftIdx == -1) { |
| | elements[subtree].leftIdx = pos; |
| | } |
| | else { |
| | Insert_help(elements[subtree].leftIdx, pos); |
| | } |
| | } |
| | else if ((elements[pos].len > elements[subtree].len) || |
| | ((elements[pos].len == elements[subtree].len) && (elements[pos].elID >=elements[subtree].elID))) { |
| | // go right |
| | if (elements[subtree].rightIdx == -1) { |
| | elements[subtree].rightIdx = pos; |
| | } |
| | else { |
| | Insert_help(elements[subtree].rightIdx, pos); |
| | } |
| | } |
| | else { // invalid case |
| | CkAbort("ERROR: Element_Bucket::Insert_help: unreachable case!\n"); |
| | } |
| | } |
| | |
| | /// Get next element to be refined/coarsened |
| | int Remove(double *len) { |
| | // ASSERT: bucket is not empty; however, will return -1 in this case |
| | int elID, leftIdx, rightIdx; |
| | if (numElements == 0) { |
| | return -1; |
| | } |
| | int idx = root; |
| | int parent = root; |
| | while (elements[idx].leftIdx != -1) { |
| | if (parent != idx) parent = idx; |
| | idx = elements[idx].leftIdx; |
| | } |
| | elID = elements[idx].elID; |
| | CkAssert((elID < bucketSz) && (elID >=0)); |
| | (*len) = elements[idx].len; |
| | if (elements[idx].rightIdx == -1) { // no children |
| | elements[idx].elID = -1; |
| | elements[idx].len = -1.0; |
| | elements[parent].leftIdx = -1; |
| | } |
| | else { // there is a right child |
| | elements[idx].elID = -1; |
| | elements[idx].len = -1.0; |
| | if (parent == idx) { |
| | root = elements[idx].rightIdx; |
| | } |
| | else { |
| | elements[parent].leftIdx = elements[idx].rightIdx; |
| | } |
| | elements[idx].rightIdx = -1; |
| | } |
| | numElements--; |
| | if (numElements==0) { |
| | root=-1; |
| | } |
| | CkPrintf("In Element_Bucket::Remove: the elId to be returned is: %d\n", elID); |
| | sanity_check(); |
| | return elID; |
| | } |
| | |
| | int findEmptySlot() { |
| | for (int i=0; i<numElements+1; i++) { |
| | if (elements[i].elID == -1) { |
| | return i; |
| | } |
| | } |
| | CkAbort("ERROR: Element_Bucket::findEmptySlot: more than numElements solts appear to be full!\n"); |
| | } |
| | |
| | void sanity_check() { |
| | int idx = root; |
| | int count = 0; |
| | CkAssert((root == -1) || ((root < bucketSz) && (root >=0))); |
| | if (root == -1) { |
| | CkAssert(numElements == 0); |
| | } |
| | else { |
| | sanity_check_helper(idx, &count); |
| | CkAssert(count == numElements); |
| | } |
| | } |
| | |
| | void sanity_check_helper(int idx, int *count) { |
| | (*count)++; |
| | CkAssert((elements[idx].elID < bucketSz) && (elements[idx].elID >= 0)); |
| | CkAssert(elements[idx].len > 0.0); |
| | int leftIdx, rightIdx; |
| | leftIdx = elements[idx].leftIdx; |
| | CkAssert((leftIdx == -1) || ((leftIdx < bucketSz) && (leftIdx >=0))); |
| | rightIdx = elements[idx].rightIdx; |
| | CkAssert((rightIdx == -1) || ((rightIdx < bucketSz) && (rightIdx >=0))); |
| | if (leftIdx != -1) { |
| | sanity_check_helper(leftIdx, count); |
| | } |
| | if (rightIdx != -1) { |
| | sanity_check_helper(rightIdx, count); |
| | } |
| | } |
| }; | }; |
| | |
| | |