moab
RangeSeqIntersectIter.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines