1 /*
2 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 * storing and accessing finite element mesh data.
4 *
5 * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 * retains certain rights in this software.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 */
15
16 /**\file RangeSeqIntersectIter.cpp
17 *\author Jason Kraftcheck (kraftche@cae.wisc.edu)
18 *\date 2006-08-11
19 */
20
21 #include "RangeSeqIntersectIter.hpp"
22 #include "SequenceManager.hpp"
23 #include "EntitySequence.hpp"
24 #include <assert.h>
25
26 namespace moab {
27
init(Range::const_iterator start,Range::const_iterator end)28 ErrorCode RangeSeqIntersectIter::init( Range::const_iterator start,
29 Range::const_iterator end )
30 {
31 mSequence = 0;
32 rangeIter = start;
33
34 // special case : nothing to iterate over
35 if (start == end) {
36 mStartHandle = mEndHandle = mLastHandle = 0;
37 return MB_FAILURE;
38 }
39
40 // normal case
41 mStartHandle = *start;
42 --end;
43 mLastHandle = *end;
44 mEndHandle = (*rangeIter).second;
45 if (mEndHandle > mLastHandle)
46 mEndHandle = mLastHandle;
47
48 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS
49 ErrorCode result = update_entity_sequence();
50 update_stats(mEndHandle - mStartHandle + 1);
51 return result;
52 #else
53 return update_entity_sequence();
54 #endif
55 }
56
57
step()58 ErrorCode RangeSeqIntersectIter::step()
59 {
60 // If at end, return MB_FAILURE
61 if (is_at_end())
62 return MB_FAILURE;
63 // If the last block was at the end of the rangeIter pair,
64 // then advance the iterator and set the next block
65 else if (mEndHandle == (*rangeIter).second) {
66 ++rangeIter;
67 mStartHandle = (*rangeIter).first;
68 }
69 // Otherwise start with next entity in the pair
70 else {
71 mStartHandle = mEndHandle + 1;
72 }
73 // Always take the remaining entities in the rangeIter pair.
74 // will trim up the end of the range in update_entity_sequence().
75 mEndHandle = (*rangeIter).second;
76 if (mEndHandle > mLastHandle)
77 mEndHandle = mLastHandle;
78
79 // Now trim up the range (decrease mEndHandle) as necessary
80 // for the corresponding EntitySquence
81 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS
82 ErrorCode result = update_entity_sequence();
83 update_stats(mEndHandle - mStartHandle + 1);
84 return result;
85 #else
86 return update_entity_sequence();
87 #endif
88 }
89
update_entity_sequence()90 ErrorCode RangeSeqIntersectIter::update_entity_sequence()
91 {
92 // mStartHandle to mEndHandle is a subset of the Range.
93 // Update sequence data as necessary and trim that subset
94 // (reduce mEndHandle) for the current EntitySequence.
95
96 // Need to update the sequence pointer?
97 if (!mSequence || mStartHandle > mSequence->end_handle()) {
98
99 // Check that the mStartHandle is valid
100 if (TYPE_FROM_HANDLE(mStartHandle) >= MBMAXTYPE)
101 return MB_TYPE_OUT_OF_RANGE;
102
103 if (MB_SUCCESS != mSequenceManager->find( mStartHandle, mSequence ))
104 return find_invalid_range();
105 }
106
107 // if mEndHandle is past end of sequence or block of used
108 // handles within sequence, shorten it.
109 if(mEndHandle > mSequence->end_handle())
110 mEndHandle = mSequence->end_handle();
111
112 return MB_SUCCESS;
113 }
114
find_invalid_range()115 ErrorCode RangeSeqIntersectIter::find_invalid_range()
116 {
117 assert(!mSequence);
118
119 // no more entities in current range
120 if (mStartHandle == mEndHandle)
121 return MB_ENTITY_NOT_FOUND;
122
123 // Find the next EntitySequence
124 EntityType type = TYPE_FROM_HANDLE(mStartHandle);
125 const TypeSequenceManager& map = mSequenceManager->entity_map( type );
126 TypeSequenceManager::const_iterator iter = map.upper_bound( mStartHandle );
127 // If no next sequence of the same type
128 if (iter == map.end()) {
129 // If end type not the same as start type, split on type
130 if (type != TYPE_FROM_HANDLE( mEndHandle )) {
131 int junk;
132 mEndHandle = CREATE_HANDLE( type, MB_END_ID, junk );
133 }
134 }
135 // otherwise invalid range ends at min(mEndHandle, sequence start handle - 1)
136 else if ((*iter)->start_handle() <= mEndHandle) {
137 mEndHandle = (*iter)->start_handle()-1;
138 }
139
140 return MB_ENTITY_NOT_FOUND;
141 }
142
143 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS
144 double RangeSeqIntersectIter::doubleNumCalls = 0;
145 double RangeSeqIntersectIter::doubleEntCount = 0;
146 unsigned long RangeSeqIntersectIter::intNumCalls = 0;
147 unsigned long RangeSeqIntersectIter::intEntCount = 0;
148
update_stats(unsigned long num_ents)149 void RangeSeqIntersectIter::update_stats( unsigned long num_ents )
150 {
151 if (std::numeric_limits<unsigned long>::max() == intNumCalls) {
152 doubleNumCalls += intNumCalls;
153 intNumCalls = 0;
154 }
155 ++intNumCalls;
156
157 if (std::numeric_limits<unsigned long>::max() - intEntCount > num_ents) {
158 doubleNumCalls += intEntCount;
159 intEntCount = num_ents;
160 }
161 else {
162 intEntCount += num_ents;
163 }
164 }
165 #endif
166
167 } // namespace moab
168
169