MOAB: Mesh Oriented datABase  (version 5.4.1)
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 Corporation, 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 
00016 /**\file RangeSeqIntersectIter.cpp
00017  *\author Jason Kraftcheck ([email protected])
00018  *\date 2006-08-11
00019  */
00020 
00021 #include "RangeSeqIntersectIter.hpp"
00022 #include "SequenceManager.hpp"
00023 #include "EntitySequence.hpp"
00024 #include <cassert>
00025 
00026 namespace moab
00027 {
00028 
00029 ErrorCode RangeSeqIntersectIter::init( Range::const_iterator start, Range::const_iterator end )
00030 {
00031     mSequence = 0;
00032     rangeIter = start;
00033 
00034     // special case : nothing to iterate over
00035     if( start == end )
00036     {
00037         mStartHandle = mEndHandle = mLastHandle = 0;
00038         return MB_FAILURE;
00039     }
00040 
00041     // normal case
00042     mStartHandle = *start;
00043     --end;
00044     mLastHandle = *end;
00045     mEndHandle  = ( *rangeIter ).second;
00046     if( mEndHandle > mLastHandle ) 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 ErrorCode RangeSeqIntersectIter::step()
00058 {
00059     // If at end, return MB_FAILURE
00060     if( is_at_end() ) return MB_FAILURE;
00061     // If the last block was at the end of the rangeIter pair,
00062     // then advance the iterator and set the next block
00063     else if( mEndHandle == ( *rangeIter ).second )
00064     {
00065         ++rangeIter;
00066         mStartHandle = ( *rangeIter ).first;
00067     }
00068     // Otherwise start with next entity in the pair
00069     else
00070     {
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 ) mEndHandle = mLastHandle;
00077 
00078         // Now trim up the range (decrease mEndHandle) as necessary
00079         // for the corresponding EntitySquence
00080 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS
00081     ErrorCode result = update_entity_sequence();
00082     update_stats( mEndHandle - mStartHandle + 1 );
00083     return result;
00084 #else
00085     return update_entity_sequence();
00086 #endif
00087 }
00088 
00089 ErrorCode RangeSeqIntersectIter::update_entity_sequence()
00090 {
00091     // mStartHandle to mEndHandle is a subset of the Range.
00092     // Update sequence data as necessary and trim that subset
00093     // (reduce mEndHandle) for the current EntitySequence.
00094 
00095     // Need to update the sequence pointer?
00096     if( !mSequence || mStartHandle > mSequence->end_handle() )
00097     {
00098 
00099         // Check that the mStartHandle is valid
00100         if( TYPE_FROM_HANDLE( mStartHandle ) >= MBMAXTYPE ) return MB_TYPE_OUT_OF_RANGE;
00101 
00102         if( MB_SUCCESS != mSequenceManager->find( mStartHandle, mSequence ) ) return find_invalid_range();
00103     }
00104 
00105     // if mEndHandle is past end of sequence or block of used
00106     // handles within sequence, shorten it.
00107     if( mEndHandle > mSequence->end_handle() ) mEndHandle = mSequence->end_handle();
00108 
00109     return MB_SUCCESS;
00110 }
00111 
00112 ErrorCode RangeSeqIntersectIter::find_invalid_range()
00113 {
00114     assert( !mSequence );
00115 
00116     // no more entities in current range
00117     if( mStartHandle == mEndHandle ) return MB_ENTITY_NOT_FOUND;
00118 
00119     // Find the next EntitySequence
00120     EntityType type                          = TYPE_FROM_HANDLE( mStartHandle );
00121     const TypeSequenceManager& map           = mSequenceManager->entity_map( type );
00122     TypeSequenceManager::const_iterator iter = map.upper_bound( mStartHandle );
00123     // If no next sequence of the same type
00124     if( iter == map.end() )
00125     {
00126         // If end type not the same as start type, split on type
00127         if( type != TYPE_FROM_HANDLE( mEndHandle ) )
00128         {
00129             int junk;
00130             mEndHandle = CREATE_HANDLE( type, MB_END_ID, junk );
00131         }
00132     }
00133     // otherwise invalid range ends at min(mEndHandle, sequence start handle - 1)
00134     else if( ( *iter )->start_handle() <= mEndHandle )
00135     {
00136         mEndHandle = ( *iter )->start_handle() - 1;
00137     }
00138 
00139     return MB_ENTITY_NOT_FOUND;
00140 }
00141 
00142 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS
00143 double RangeSeqIntersectIter::doubleNumCalls     = 0;
00144 double RangeSeqIntersectIter::doubleEntCount     = 0;
00145 unsigned long RangeSeqIntersectIter::intNumCalls = 0;
00146 unsigned long RangeSeqIntersectIter::intEntCount = 0;
00147 
00148 void RangeSeqIntersectIter::update_stats( unsigned long num_ents )
00149 {
00150     if( std::numeric_limits< unsigned long >::max() == intNumCalls )
00151     {
00152         doubleNumCalls += intNumCalls;
00153         intNumCalls = 0;
00154     }
00155     ++intNumCalls;
00156 
00157     if( std::numeric_limits< unsigned long >::max() - intEntCount > num_ents )
00158     {
00159         doubleNumCalls += intEntCount;
00160         intEntCount = num_ents;
00161     }
00162     else
00163     {
00164         intEntCount += num_ents;
00165     }
00166 }
00167 #endif
00168 
00169 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines