moab
|
00001 /* 00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating, 00003 * storing and accessing finite element mesh data. 00004 * 00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract 00006 * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government 00007 * retains certain rights in this software. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 */ 00015 00021 #include "RangeSeqIntersectIter.hpp" 00022 #include "SequenceManager.hpp" 00023 #include "EntitySequence.hpp" 00024 #include <assert.h> 00025 00026 namespace moab { 00027 00028 ErrorCode RangeSeqIntersectIter::init( Range::const_iterator start, 00029 Range::const_iterator end ) 00030 { 00031 mSequence = 0; 00032 rangeIter = start; 00033 00034 // special case : nothing to iterate over 00035 if (start == end) { 00036 mStartHandle = mEndHandle = mLastHandle = 0; 00037 return MB_FAILURE; 00038 } 00039 00040 // normal case 00041 mStartHandle = *start; 00042 --end; 00043 mLastHandle = *end; 00044 mEndHandle = (*rangeIter).second; 00045 if (mEndHandle > mLastHandle) 00046 mEndHandle = mLastHandle; 00047 00048 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS 00049 ErrorCode result = update_entity_sequence(); 00050 update_stats(mEndHandle - mStartHandle + 1); 00051 return result; 00052 #else 00053 return update_entity_sequence(); 00054 #endif 00055 } 00056 00057 00058 ErrorCode RangeSeqIntersectIter::step() 00059 { 00060 // If at end, return MB_FAILURE 00061 if (is_at_end()) 00062 return MB_FAILURE; 00063 // If the last block was at the end of the rangeIter pair, 00064 // then advance the iterator and set the next block 00065 else if (mEndHandle == (*rangeIter).second) { 00066 ++rangeIter; 00067 mStartHandle = (*rangeIter).first; 00068 } 00069 // Otherwise start with next entity in the pair 00070 else { 00071 mStartHandle = mEndHandle + 1; 00072 } 00073 // Always take the remaining entities in the rangeIter pair. 00074 // will trim up the end of the range in update_entity_sequence(). 00075 mEndHandle = (*rangeIter).second; 00076 if (mEndHandle > mLastHandle) 00077 mEndHandle = mLastHandle; 00078 00079 // Now trim up the range (decrease mEndHandle) as necessary 00080 // for the corresponding EntitySquence 00081 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS 00082 ErrorCode result = update_entity_sequence(); 00083 update_stats(mEndHandle - mStartHandle + 1); 00084 return result; 00085 #else 00086 return update_entity_sequence(); 00087 #endif 00088 } 00089 00090 ErrorCode RangeSeqIntersectIter::update_entity_sequence() 00091 { 00092 // mStartHandle to mEndHandle is a subset of the Range. 00093 // Update sequence data as necessary and trim that subset 00094 // (reduce mEndHandle) for the current EntitySequence. 00095 00096 // Need to update the sequence pointer? 00097 if (!mSequence || mStartHandle > mSequence->end_handle()) { 00098 00099 // Check that the mStartHandle is valid 00100 if (TYPE_FROM_HANDLE(mStartHandle) >= MBMAXTYPE) 00101 return MB_TYPE_OUT_OF_RANGE; 00102 00103 if (MB_SUCCESS != mSequenceManager->find( mStartHandle, mSequence )) 00104 return find_invalid_range(); 00105 } 00106 00107 // if mEndHandle is past end of sequence or block of used 00108 // handles within sequence, shorten it. 00109 if(mEndHandle > mSequence->end_handle()) 00110 mEndHandle = mSequence->end_handle(); 00111 00112 return MB_SUCCESS; 00113 } 00114 00115 ErrorCode RangeSeqIntersectIter::find_invalid_range() 00116 { 00117 assert(!mSequence); 00118 00119 // no more entities in current range 00120 if (mStartHandle == mEndHandle) 00121 return MB_ENTITY_NOT_FOUND; 00122 00123 // Find the next EntitySequence 00124 EntityType type = TYPE_FROM_HANDLE(mStartHandle); 00125 const TypeSequenceManager& map = mSequenceManager->entity_map( type ); 00126 TypeSequenceManager::const_iterator iter = map.upper_bound( mStartHandle ); 00127 // If no next sequence of the same type 00128 if (iter == map.end()) { 00129 // If end type not the same as start type, split on type 00130 if (type != TYPE_FROM_HANDLE( mEndHandle )) { 00131 int junk; 00132 mEndHandle = CREATE_HANDLE( type, MB_END_ID, junk ); 00133 } 00134 } 00135 // otherwise invalid range ends at min(mEndHandle, sequence start handle - 1) 00136 else if ((*iter)->start_handle() <= mEndHandle) { 00137 mEndHandle = (*iter)->start_handle()-1; 00138 } 00139 00140 return MB_ENTITY_NOT_FOUND; 00141 } 00142 00143 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS 00144 double RangeSeqIntersectIter::doubleNumCalls = 0; 00145 double RangeSeqIntersectIter::doubleEntCount = 0; 00146 unsigned long RangeSeqIntersectIter::intNumCalls = 0; 00147 unsigned long RangeSeqIntersectIter::intEntCount = 0; 00148 00149 void RangeSeqIntersectIter::update_stats( unsigned long num_ents ) 00150 { 00151 if (std::numeric_limits<unsigned long>::max() == intNumCalls) { 00152 doubleNumCalls += intNumCalls; 00153 intNumCalls = 0; 00154 } 00155 ++intNumCalls; 00156 00157 if (std::numeric_limits<unsigned long>::max() - intEntCount > num_ents) { 00158 doubleNumCalls += intEntCount; 00159 intEntCount = num_ents; 00160 } 00161 else { 00162 intEntCount += num_ents; 00163 } 00164 } 00165 #endif 00166 00167 } // namespace moab 00168