[MOAB-dev] r1731 - MOAB/trunk

kraftche at mcs.anl.gov kraftche at mcs.anl.gov
Tue Apr 1 10:49:58 CDT 2008


Author: kraftche
Date: 2008-04-01 10:49:58 -0500 (Tue, 01 Apr 2008)
New Revision: 1731

Added:
   MOAB/trunk/Test_MBMeshSet.cpp
Modified:
   MOAB/trunk/MBInternals.hpp
   MOAB/trunk/MBMeshSet.cpp
   MOAB/trunk/MBMeshSet.hpp
   MOAB/trunk/Makefile.am
   MOAB/trunk/MeshSetSequence.hpp
Log:
o Rewrite storage of entity set contents:
  - use array-based representation of ranged sets
  - embed small contents arrays directly into MBMeshSet struct
  - reduces memory for empty sets by 22%
  - reduces memory for large kd-tree by 33%
o Add some more unit tests for entity sets
o Change set unite behavior when the destination set is list-based
   to a simple append (do not skip duplicates.)




Modified: MOAB/trunk/MBInternals.hpp
===================================================================
--- MOAB/trunk/MBInternals.hpp	2008-03-31 20:29:26 UTC (rev 1730)
+++ MOAB/trunk/MBInternals.hpp	2008-04-01 15:49:58 UTC (rev 1731)
@@ -62,6 +62,12 @@
   return (((MBEntityHandle)type) << MB_ID_WIDTH)|id;
 }
 
+inline MBEntityHandle FIRST_HANDLE( unsigned type )
+  { return (((MBEntityHandle)type) << MB_ID_WIDTH)|MB_START_ID; }
+
+inline MBEntityHandle LAST_HANDLE( unsigned type )
+  { return ((MBEntityHandle)(type+1) << MB_ID_WIDTH) - 1; }
+
 //! Get the entity id out of the handle.
 inline MBEntityID ID_FROM_HANDLE (MBEntityHandle handle)
 {

Modified: MOAB/trunk/MBMeshSet.cpp
===================================================================
--- MOAB/trunk/MBMeshSet.cpp	2008-03-31 20:29:26 UTC (rev 1730)
+++ MOAB/trunk/MBMeshSet.cpp	2008-04-01 15:49:58 UTC (rev 1731)
@@ -1,30 +1,3 @@
-/**
- * MOAB, a Mesh-Oriented datABase, is a software component for creating,
- * storing and accessing finite element mesh data.
- * 
- * Copyright 2004 Sandia Corporation.  Under the terms of Contract
- * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
- * retains certain rights in this software.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- */
-
-//
-//-------------------------------------------------------------------------
-// Filename      : MBMeshSet.cpp 
-// Creator       : Tim Tautges
-//
-// Date          : 02/01/02
-//
-// Owner         : Tim Tautges
-//
-// Description   : MBMeshSet is the MB implementation of MBSet
-//-------------------------------------------------------------------------
-
 #ifdef WIN32
 #ifdef _DEBUG
 // turn off warnings that say they debugging identifier has been truncated
@@ -33,77 +6,104 @@
 #endif
 #endif
 
-
-
-#include <algorithm>
-#include <utility>
-#include <set>
-#include "assert.h"
-#include "MBInternals.hpp"
 #include "MBMeshSet.hpp"
 #include "AEntityFactory.hpp"
-#include "MBCN.hpp"
 
-using namespace std;
 
-#ifndef MB_MESH_SET_COMPACT_PARENT_CHILD_LISTS
+/*****************************************************************************************
+ *                          Helper Function Declarations                                 *
+ *****************************************************************************************/
 
-MBMeshSet::MBMeshSet( unsigned flags ) 
-  : mFlags(flags)
-  {}
+/**\brief Insert into parent/child list */
+static inline 
+MBMeshSet::Count insert_in_vector( const MBMeshSet::Count count, 
+                                   MBMeshSet::CompactList& list,
+                                   const MBEntityHandle h,
+                                   int &result );
 
-MBMeshSet::~MBMeshSet() 
-{
-}
+/**\brief Remvoe from parent/child list */
+static inline
+MBMeshSet::Count remove_from_vector( const MBMeshSet::Count count, 
+                                     MBMeshSet::CompactList& list,
+                                     const MBEntityHandle h,
+                                     int &result );
 
-static inline int insert_in_vector( MBMeshSet::LinkSet& s, MBEntityHandle h )
-{
-  MBMeshSet::LinkSet::iterator i = find( s.begin(), s.end(), h );
-  if (i != s.end())
-    return 0;
-  s.push_back( h );
-  return 1;
-}
-int MBMeshSet::add_parent( MBEntityHandle parent )
-  { return insert_in_vector( parentMeshSets, parent ); }
-int MBMeshSet::add_child( MBEntityHandle child )
-  { return insert_in_vector( childMeshSets, child ); }
 
-static inline int remove_from_vector( MBMeshSet::LinkSet& s, MBEntityHandle h )
+/**\brief Resize MBMeshSet::CompactList.  Returns pointer to storage */
+static MBEntityHandle* resize_compact_list( MBMeshSet::Count& count,
+                                            MBMeshSet::CompactList& clist,
+                                            size_t new_list_size );
+/**\brief Methods to insert/remove range-based data from contents list.
+ *        Templatized to operate on both MBRange and set-based MBMeshSets.
+ */
+template <typename pair_iter_t> class range_tool
 {
-  MBMeshSet::LinkSet::iterator i = find( s.begin(), s.end(), h );
-  if (i == s.end())
-    return 0;
-  s.erase( i );
-  return 1;
-}
-int MBMeshSet::remove_parent( MBEntityHandle parent )
-  { return remove_from_vector( parentMeshSets, parent ); }
-int MBMeshSet::remove_child( MBEntityHandle child )
-  { return remove_from_vector( childMeshSets, child ); }
+public:
+  /** Insert range-based data into range-based MBMeshSet */
+  inline static MBErrorCode ranged_insert_entities( MBMeshSet::Count& count, 
+                                                    MBMeshSet::CompactList& clist, 
+                                                    pair_iter_t begin, 
+                                                    pair_iter_t end, 
+                                                    MBEntityHandle my_handle, 
+                                                    AEntityFactory* adj );
+  
+  /** Remove range-based data from range-based MBMeshSet */
+  inline static MBErrorCode ranged_remove_entities( MBMeshSet::Count& count, 
+                                                    MBMeshSet::CompactList& clist, 
+                                                    pair_iter_t begin, 
+                                                    pair_iter_t end, 
+                                                    MBEntityHandle my_handle, 
+                                                    AEntityFactory* adj );
 
-unsigned long MBMeshSet::parent_child_memory_use() const
-{
-  return (parentMeshSets.capacity() + childMeshSets.capacity())
-       * sizeof(MBEntityHandle);
-}
+  /** Insert range-based data into list-based MBMeshSet */
+  inline static MBErrorCode vector_insert_entities( MBMeshSet::Count& count, 
+                                                    MBMeshSet::CompactList& clist, 
+                                                    pair_iter_t begin, 
+                                                    pair_iter_t end, 
+                                                    MBEntityHandle my_handle, 
+                                                    AEntityFactory* adj );
+};
 
-#else 
+/** Remove MBRange of handles fromr vector-based MBMeshSet */
+static MBErrorCode vector_remove_range( MBMeshSet::Count& count, 
+                                        MBMeshSet::CompactList& clist, 
+                                        const MBRange& range, 
+                                        MBEntityHandle my_handle, 
+                                        AEntityFactory* adj );
 
-MBMeshSet::MBMeshSet( unsigned flags ) 
-  : mFlags(flags),
-    mParentCount(ZERO),
-    mChildCount(ZERO)
-  {}
+/** Remove range-based MBMeshSet contents from vector-based MBMeshSet */
+static MBErrorCode vector_remove_ranges( MBMeshSet::Count& count, 
+                                         MBMeshSet::CompactList& clist, 
+                                         const MBEntityHandle* pair_list,
+                                         size_t num_pairs,
+                                         MBEntityHandle my_handle, 
+                                         AEntityFactory* adj );
 
-MBMeshSet::~MBMeshSet() 
-{
-  if (mParentCount > 2)
-    free( parentMeshSets.ptr[0] );
-  if (mChildCount > 2)
-    free( childMeshSets.ptr[0] );
-}
+/** Remove unsorted array of handles from vector-based MBMeshSet */
+static MBErrorCode vector_remove_vector( MBMeshSet::Count& count, 
+                                         MBMeshSet::CompactList& clist, 
+                                         const MBEntityHandle* vect,
+                                         size_t vect_size,
+                                         MBEntityHandle my_handle, 
+                                         AEntityFactory* adj );
 
+/** Insert unsorted array of handles into vector-based MBMeshSet */
+static MBErrorCode vector_insert_vector( MBMeshSet::Count& count, 
+                                         MBMeshSet::CompactList& clist, 
+                                         const MBEntityHandle* vect,
+                                         size_t vect_size,
+                                         MBEntityHandle my_handle, 
+                                         AEntityFactory* adj );
+
+/** Convert unsorted array of handles into array of ranged [begin,end] pairs */
+static void convert_to_ranges( const MBEntityHandle* vect_in, size_t vect_in_len,
+                               std::vector<MBEntityHandle>& vect_out );
+
+
+/*****************************************************************************************
+ *                             Parent/Child Operations                                   *
+ *****************************************************************************************/
+
 static inline 
 MBMeshSet::Count insert_in_vector( const MBMeshSet::Count count, 
                                 MBMeshSet::CompactList& list,
@@ -141,7 +141,7 @@
         return MBMeshSet::MANY;
       }
     case MBMeshSet::MANY:
-      if (find( list.ptr[0], list.ptr[1], h ) != list.ptr[1]) {
+      if (std::find( list.ptr[0], list.ptr[1], h ) != list.ptr[1]) {
         result = false;
       }
       else {
@@ -157,19 +157,6 @@
   return MBMeshSet::ZERO;
 }
 
-int MBMeshSet::add_parent( MBEntityHandle parent )
-{ 
-  int result;
-  mParentCount = insert_in_vector( (Count)mParentCount, parentMeshSets, parent, result );
-  return result;
-}
-int MBMeshSet::add_child( MBEntityHandle child )
-{ 
-  int result;
-  mChildCount = insert_in_vector( (Count)mChildCount, childMeshSets, child, result );
-  return result;
-}
-
 static inline
 MBMeshSet::Count remove_from_vector( const MBMeshSet::Count count, 
                                   MBMeshSet::CompactList& list,
@@ -237,6 +224,20 @@
   return MBMeshSet::ZERO;
 }
 
+
+int MBMeshSet::add_parent( MBEntityHandle parent )
+{ 
+  int result;
+  mParentCount = insert_in_vector( (Count)mParentCount, parentMeshSets, parent, result );
+  return result;
+}
+int MBMeshSet::add_child( MBEntityHandle child )
+{ 
+  int result;
+  mChildCount = insert_in_vector( (Count)mChildCount, childMeshSets, child, result );
+  return result;
+}
+
 int MBMeshSet::remove_parent( MBEntityHandle parent )
 { 
   int result;
@@ -250,390 +251,902 @@
   return result;
 }
 
-unsigned long MBMeshSet::parent_child_memory_use() const
-{
-  unsigned long result = 0;
-  if (num_children() > 2)
-    result += sizeof(MBEntityHandle) * num_children();
-  if (num_parents() > 2)
-    result += sizeof(MBEntityHandle) * num_parents();
-  return result;
-}
 
-#endif
-  
+/*****************************************************************************************
+ *                          Flag Conversion Operations                                   *
+ *****************************************************************************************/
 
-MBErrorCode MBMeshSet_MBRange::clear( MBEntityHandle mEntityHandle,
-                                      AEntityFactory* mAdjFact )
+MBErrorCode MBMeshSet::convert( unsigned flags, MBEntityHandle my_handle, AEntityFactory* adj )
 {
-  if(tracking() && mAdjFact)
-  {
-    for(MBRange::iterator iter = mRange.begin();
-        iter != mRange.end(); ++iter)
-    {
-      mAdjFact->remove_adjacency(*iter, mEntityHandle);
+  MBErrorCode rval = MB_SUCCESS;
+  if ((mFlags & MESHSET_TRACK_OWNER) && !(flags & MESHSET_TRACK_OWNER))
+    rval = remove_adjacencies( my_handle, adj );
+  else if (!(mFlags & MESHSET_TRACK_OWNER) && (flags & MESHSET_TRACK_OWNER))
+    rval = create_adjacencies( my_handle, adj );
+  if (MB_SUCCESS != rval)
+    return rval;
+
+  if ((mFlags & MESHSET_ORDERED) && !(flags & MESHSET_ORDERED)) {
+    size_t datalen;
+    MBEntityHandle* data = get_contents(datalen);
+    if (datalen) {
+      std::vector<MBEntityHandle> list( datalen );
+      memcpy( &list[0], data, datalen*sizeof(MBEntityHandle) );
+      int num_ents = num_entities();
+      Count count = (Count)mContentCount;
+      data = resize_compact_list( count, contentList, num_ents );
+      mContentCount = count;
+      assert( list.size() % 2 == 0 );
+      std::vector<MBEntityHandle>::iterator i = list.begin();
+      while (i != list.end()) {
+        MBEntityHandle h = *i; ++i;
+        MBEntityHandle e = *i; ++i;
+        for (; h <= e; ++h) {
+          *data = h; 
+          ++data;
+        }
+      }
     }
   }
-  mRange.clear();
+  else if (!(mFlags & MESHSET_ORDERED) && (flags & MESHSET_ORDERED)) {
+    size_t datalen;
+    MBEntityHandle* data = get_contents(datalen);
+    if (datalen) {
+      std::vector<MBEntityHandle> ranges;
+      convert_to_ranges( data, datalen, ranges );
+      Count count = (Count)mContentCount;
+      data = resize_compact_list( count, contentList, ranges.size() );
+      mContentCount = count;
+      memcpy( data, &ranges[0], ranges.size()*sizeof(MBEntityHandle) );
+    }
+  }
+
   return MB_SUCCESS;
 }
 
-
-bool MBMeshSet_MBRange::replace_entities(MBEntityHandle set_handle,
-                                         MBEntityHandle *entities,
-                                         int num_entities,
-                                         AEntityFactory* mAdjFact)
+MBErrorCode MBMeshSet::create_adjacencies( MBEntityHandle my_handle, AEntityFactory* adj )
 {
-  bool was_contained = false;
-  MBRange::iterator rit;
-  for (int i = 0; i < num_entities; i += 2) {
-    if ((rit = mRange.find(entities[i])) != mRange.end()) {
-      mRange.erase(rit);
-      mRange.insert(entities[i+1]);
-      was_contained = true;
-
-      if (tracking() && mAdjFact)
-        mAdjFact->remove_adjacency(entities[i], set_handle),
-          mAdjFact->add_adjacency(entities[i+1], set_handle);
+  MBErrorCode rval = MB_SUCCESS;;
+  size_t count;
+  const MBEntityHandle *const ptr = get_contents( count );
+  const MBEntityHandle *const end = ptr + count;
+  if (vector_based()) {
+    for (const MBEntityHandle* i = ptr; i != end; ++i) {
+      rval = adj->add_adjacency( *i, my_handle, false );
+      if (MB_SUCCESS != rval) {
+        for (const MBEntityHandle* j = ptr; j != i; ++j) 
+          adj->remove_adjacency( *j, my_handle );
+        return rval;
+      }
     }
-    
-    if (remove_parent(entities[i]))
-      add_parent(entities[i+1]), was_contained = true;
-
-    if (remove_child(entities[i]))
-      add_child(entities[i+1]), was_contained = true;
   }
-  
-  return was_contained;
+  else {
+    assert( 0 == count % 2 );
+    for (const MBEntityHandle* i = ptr; i != end; i += 2) {
+      for (MBEntityHandle h = i[0]; h <= i[1]; ++h) {
+        rval = adj->add_adjacency( h, my_handle, false );
+        if (MB_SUCCESS != rval) {
+          for (MBEntityHandle j = i[0]; j < h; ++j)
+            adj->remove_adjacency( j, my_handle );
+          for (const MBEntityHandle* j = ptr; j != i; j += 2)
+            for (MBEntityHandle k = j[0]; k <= j[1]; ++k)
+              adj->remove_adjacency( k, my_handle );
+          return rval;
+        }
+      }
+    }
+  }
+  return MB_SUCCESS;
 }
 
-
-MBErrorCode MBMeshSet_MBRange::add_entities( const MBEntityHandle *entities,
-                                             const int num_entities,
-                                             MBEntityHandle mEntityHandle,
-                                             AEntityFactory* mAdjFact )
+MBErrorCode MBMeshSet::remove_adjacencies( MBEntityHandle my_handle, AEntityFactory* adj )
 {
-  int i;
-  for(i = 0; i < num_entities; i++)
-    mRange.insert(entities[i]);
-
-  if(tracking() && mAdjFact)
-  {
-    for(i = 0; i < num_entities; i++)
-      mAdjFact->add_adjacency(entities[i], mEntityHandle);
+  size_t count;
+  const MBEntityHandle *const ptr = get_contents( count );
+  const MBEntityHandle *const end = ptr + count;
+  if (vector_based()) {
+    for (const MBEntityHandle* i = ptr; i != end; ++i)
+      adj->remove_adjacency( *i, my_handle );
   }
+  else {
+    assert( 0 == count % 2 );
+    for (const MBEntityHandle* i = ptr; i != end; i += 2)
+      for (MBEntityHandle h = i[0]; h <= i[1]; ++h)
+        adj->remove_adjacency( h, my_handle );
+  }
   return MB_SUCCESS;
 }
 
 
-MBErrorCode MBMeshSet_MBRange::add_entities( const MBRange& entities,
-                                             MBEntityHandle mEntityHandle,
-                                             AEntityFactory* mAdjFact )
+/*****************************************************************************************
+ *                          Contents Modifiction Methods                                 *
+ *****************************************************************************************/
+
+static MBEntityHandle* resize_compact_list( MBMeshSet::Count& count,
+                                            MBMeshSet::CompactList& clist,
+                                            size_t new_list_size )
 {
-
-  mRange.merge(entities);
-  
-  if(tracking() && mAdjFact)
-  {
-    for(MBRange::const_iterator iter = entities.begin();
-        iter != entities.end(); ++iter)
-      mAdjFact->add_adjacency(*iter, mEntityHandle);
+  if (count <= 2) {
+    if (new_list_size <= 2) {
+      count = (MBMeshSet::Count)new_list_size;
+      return clist.hnd;
+    }
+    else {
+      MBEntityHandle* list = (MBEntityHandle*)malloc( new_list_size*sizeof(MBEntityHandle) );
+      list[0] = clist.hnd[0];
+      list[1] = clist.hnd[1];
+      clist.ptr[0] = list;
+      clist.ptr[1] = list + new_list_size;
+      count = MBMeshSet::MANY;
+      return list;
+    }
   }
-
-  return MB_SUCCESS;
+  else if (new_list_size > 2) {
+    if (new_list_size > (size_t)(clist.ptr[1] - clist.ptr[0]))
+      clist.ptr[0] = (MBEntityHandle*)realloc( clist.ptr[0], new_list_size*sizeof(MBEntityHandle) );
+    clist.ptr[1] = clist.ptr[0] + new_list_size;
+    count = MBMeshSet::MANY;
+    return clist.ptr[0];
+  }
+  else {
+    MBEntityHandle* list = clist.ptr[0];
+    clist.hnd[0] = list[0];
+    clist.hnd[1] = list[1];
+    free(list);
+    count = (MBMeshSet::Count)new_list_size;
+    return clist.hnd;
+  }
 }
 
-MBErrorCode MBMeshSet_MBRange::remove_entities( const MBRange& entities,
-                                                MBEntityHandle mEntityHandle,
-                                                AEntityFactory* mAdjFact )
+template <typename pair_iter_t> inline MBErrorCode
+range_tool<pair_iter_t>::ranged_insert_entities( MBMeshSet::Count& count, 
+                                                 MBMeshSet::CompactList& clist, 
+                                                 pair_iter_t begin, 
+                                                 pair_iter_t end, 
+                                                 MBEntityHandle my_handle, 
+                                                 AEntityFactory* adj )
 {
-  MBRange common_ents = mRange.intersect(entities);
-  MBRange tmp_range = mRange.subtract(common_ents);
-  mRange.swap(tmp_range);
+    //first pass:
+    // 1) merge existing ranges 
+    // 2) count number of new ranges that must be inserted
+  ptrdiff_t insert_count = 0;
+  MBEntityHandle *list;
+  size_t list_size;
+  if (count < MBMeshSet::MANY) {
+    list = clist.hnd;
+    list_size = count;
+  }
+  else {
+    list = clist.ptr[0];
+    list_size = clist.ptr[1] - clist.ptr[0];
+  }
+
+  MBEntityHandle* list_write = list;
+  MBEntityHandle *const list_end = list + list_size, *list_read = list;
+  pair_iter_t i = begin;
   
-  if(tracking() && mAdjFact) {
-    for(MBRange::const_iterator iter = common_ents.begin();
-        iter != common_ents.end(); iter++) {
-      mAdjFact->remove_adjacency(*iter, mEntityHandle);
+  while(i != end) {
+    
+      // if there are holes in the current array, shuffle blocks 
+      // down until we find the next block to merge with or insert before
+    if (list_read != list_write) {
+      while (list_read != list_end && i->second + 1 < list_read[0]) {
+      	list_write[0] = list_read[0];
+        list_write[1] = list_read[1];
+        list_write += 2;
+        list_read += 2;
+      }
     }
+      // otherwise do a binary search
+    else {
+      list_write = std::lower_bound( list_write, list_end, i->first - 1 );
+      	// if in middle of range block (odd index), back up to start of block
+      list_write -= (list_write - list)%2;
+      list_read = list_write;
+    }
+    
+      // handle any straight insertions of range blocks
+    for ( ; i != end && (list_read == list_end || i->second+1 < list_read[0]); ++i) {
+        // If we haven't removed any range pairs, we don't have space to
+        // insert here.  Defer the insertion until later.
+      if (list_read == list_write) {
+        ++insert_count;
+      }
+      else {
+        if (adj) 
+          for (MBEntityHandle j = i->first; j <= i->second; ++j)
+            adj->add_adjacency( j, my_handle, false );
+
+        list_write[0] = i->first;
+        list_write[1] = i->second;
+        list_write += 2;
+      }
+    }
+    if (i == end)
+      break;
+    
+      // check if we need to prepend to the current range block
+    if (i->first >= list_read[0]) 
+      list_write[0] = list_read[0];
+    else {
+      if (adj)
+        for (MBEntityHandle h = i->first; h < list_read[0]; ++h)
+          adj->add_adjacency( h, my_handle, false );
+      list_write[0] = i->first;
+    }
+    list_write[1] = list_read[1];
+    list_read += 2;
+    
+      // discard any input blocks already in the set
+    for (; i != end && i->second <= list_write[1]; ++i);
+    if (i == end) {
+      list_write += 2;
+      break;
+    }
+    
+      // merge subsequent blocks in meshset
+    for (;list_read != list_end && list_read[0]+1 <= i->second; list_read += 2) {
+      if (adj)
+      	for (MBEntityHandle h = list_write[1]+1; h < list_read[0]; ++h)
+      	  adj->add_adjacency( h, my_handle, false );
+      list_write[1] = list_read[1];
+    }
+    
+      // check if we need to append to current meshset block
+    if (i->second > list_write[1]) {
+      if (adj)
+      	for (MBEntityHandle h = list_write[1]+1; h <= i->second; ++h)
+      	  adj->add_adjacency( h, my_handle, false );
+      list_write[1] = i->second;
+    }
+    
+    ++i;
+    list_write += 2;
   }
 
-  return MB_SUCCESS;
-}
+    // shuffle down entries to fill holes
+  if (list_read == list_write) 
+    list_read = list_write = list_end;
+  else while(list_read < list_end) {
+    list_write[0] = list_read[0];
+    list_write[1] = list_read[1];
+    list_read += 2;
+    list_write += 2;
+  }
 
-MBErrorCode MBMeshSet_MBRange::remove_entities( const MBEntityHandle *entities,
-                                                const int num_entities,
-                                                MBEntityHandle mEntityHandle,
-                                                AEntityFactory* mAdjFact )
-{
-  for(int i = 0; i < num_entities; i++)
-  {
-    MBRange::iterator found = mRange.find(entities[i]);
-    if(found != mRange.end())
-    {
-      mRange.erase(found);
-      if(tracking() && mAdjFact)
-        mAdjFact->remove_adjacency(entities[i], mEntityHandle);
+    // adjust allocated array size
+  const size_t occupied_size = list_write - list;
+  const size_t new_list_size = occupied_size + 2*insert_count;
+  list = resize_compact_list( count, clist, new_list_size );
+    // done?
+  if (!insert_count)
+    return MB_SUCCESS;
+
+    // Second pass: insert non-mergable range pairs
+    // All range pairs in the input are either completely disjoint from
+    // the ones in the mesh set and must be inserted or are entirely contained
+    // within range pair in the mesh set.
+  assert( begin != end ); // can't have items to insert if given empty input list
+  pair_iter_t ri = end; --ri;
+  list_write = list + new_list_size - 2;
+  list_read = list + occupied_size - 2;
+  for ( ; list_write >= list; list_write -= 2 ) {
+    if (list_read >= list) {
+      while (ri->first >= list_read[0] && ri->second <= list_read[1]) {
+        assert(ri != begin);
+        --ri;
+      }
+    
+      if (list_read[0] > ri->second) {
+        list_write[0] = list_read[0];
+        list_write[1] = list_read[1];
+        list_read -= 2;
+        continue;
+      }
     }
+    
+    assert( insert_count > 0 );
+    if (adj) 
+      for (MBEntityHandle j = ri->first; j <= ri->second; ++j) 
+        adj->add_adjacency( j, my_handle, false );
+    list_write[0] = ri->first;
+    list_write[1] = ri->second;
+
+      // don't have reverse iterator, so check before decrement
+      // if insert_count isn't zero, must be more in range
+    if (0 == --insert_count) {
+      assert( list_read == list_write-2 );
+      break;
+    }
+    else {
+      --ri;
+    }
   }
 
+  assert(!insert_count);
   return MB_SUCCESS;
-
 }
-
-MBErrorCode MBMeshSet_MBRange::subtract( const MBMeshSet *meshset_2,
-                                         MBEntityHandle handle,
-                                         AEntityFactory* adj_fact )
+  
+template <typename pair_iter_t> inline MBErrorCode
+range_tool<pair_iter_t>::ranged_remove_entities( MBMeshSet::Count& count, 
+                                                 MBMeshSet::CompactList& clist, 
+                                                 pair_iter_t begin, 
+                                                 pair_iter_t end, 
+                                                 MBEntityHandle my_handle, 
+                                                 AEntityFactory* adj )
 {
-  MBRange other_range;
-  meshset_2->get_entities(other_range);
+    //first pass:
+    // 1) remove (from) existing ranges 
+    // 2) count number of ranges that must be split
+  ptrdiff_t split_count = 0;
+  MBEntityHandle *list;
+  size_t list_size;
+  if (count < MBMeshSet::MANY) {
+    list = clist.hnd;
+    list_size = count;
+  }
+  else {
+    list = clist.ptr[0];
+    list_size = clist.ptr[1] - clist.ptr[0];
+  }
 
-  return remove_entities( other_range, handle, adj_fact );
-}
+  MBEntityHandle* list_write = list;
+  MBEntityHandle *const list_end = list + list_size, *list_read = list;
+  pair_iter_t i = begin;
+  
+  while(list_read != list_end && i != end) {
+    
+    while (i != end && i->second < list_read[0])
+      ++i;
+    if (i == end)
+      break;
+    
+      // if there are holes in the current array, shuffle blocks 
+      // down until we find the next block to remove
+    if (list_read != list_write) {
+      while (list_read != list_end && i->second < list_read[0]) {
+      	list_write[0] = list_read[0];
+        list_write[1] = list_read[1];
+        list_write += 2;
+        list_read += 2;
+      }
+    }
+      // otherwise do a binary search
+    else {
+      list_write = std::lower_bound( list_write, list_end, i->first );
+      	// if in middle of range block (odd index), back up to start of block
+      list_write -= (list_write - list)%2;
+      list_read = list_write;
+    }
+    
+      // if everything remaning is past end of set contents...
+    if (list_read == list_end) 
+      break;
+      
+      // skip any remove pairs that aren't in the list
+    if (i->second < list_read[0]) {
+      ++i;
+      continue;
+    }
+    
+      // Begin by assuming that we will keep the entire block
+    list_write[0] = list_read[0];
+    list_write[1] = list_read[1];
+    list_read += 2;
+    
+    for (; i != end && i->first <= list_write[1]; ++i) {
+      if (i->first <= list_write[0]) {
+          // remove whole block
+        if (i->second >= list_write[1]) {
+          if (adj)
+            for (MBEntityHandle h = list_write[0]; h <= list_write[1]; ++h)
+              adj->remove_adjacency( h, my_handle );
+          list_write -= 2;
+          break;
+        }
+          // remove from start of block
+        else if (i->second >= list_write[0]) {
+          if (adj)
+            for (MBEntityHandle h = list_write[0]; h <= i->second; ++h)
+              adj->remove_adjacency( h, my_handle );
+          list_write[0] = i->second + 1;
+        }
+      }
+      else if (i->first <= list_write[1]) {
+          // remove from end of block
+        if (i->second >= list_write[1]) {
+          if (adj)
+            for (MBEntityHandle h = i->first; h <= list_write[1]; ++h)
+              adj->remove_adjacency( h, my_handle );
+          list_write[1] = i->first - 1;
+          //list_write += 2;
+          break;
+        }
+          // split block
+        else {
+          if (adj)
+            for (MBEntityHandle h = i->first; h <= i->second; ++h)
+              adj->remove_adjacency( h, my_handle );
 
-MBErrorCode MBMeshSet_MBRange::intersect( const MBMeshSet *meshset_2,
-                                          MBEntityHandle mEntityHandle,
-                                          AEntityFactory* mAdjFact )
-{
-  MBRange other_range;
-  meshset_2->get_entities(other_range);
+          if (list_read - list_write <= 2) {
+            ++split_count;
+            continue;
+          }
+          else {
+            list_write[3] = list_write[1];
+            list_write[1] = i->first - 1;
+            list_write[2] = i->second + 1;
+            list_write += 2;
+          }
+        }
+      }
+    }
+    list_write += 2;
+  }
 
-  std::set<MBEntityHandle> tmp;
+    // shuffle down entries to fill holes
+  if (list_read == list_write) 
+    list_read = list_write = list_end;
+  else 
+    while(list_read < list_end) {
+      list_write[0] = list_read[0];
+      list_write[1] = list_read[1];
+      list_read += 2;
+      list_write += 2;
+    }
 
-  std::set_intersection(mRange.begin(), mRange.end(), other_range.begin(), other_range.end(), 
-      std::inserter< std::set<MBEntityHandle> >(tmp, tmp.end()));
+    // adjust allocated array size
+  const size_t occupied_size = list_write - list;
+  const size_t new_list_size = occupied_size + 2*split_count;
+  list = resize_compact_list( count, clist, new_list_size );
+    // done?
+  if (!split_count)
+    return MB_SUCCESS;
 
-  mRange.clear();
+    // Second pass: split range pairs
+    // All range pairs in the input are either already removed or
+    // require one of the existing range pairs to be split
+  assert( begin != end ); // can't have ranges to split if given empty input list
+  pair_iter_t ri = end; --ri;
+  list_write = list + new_list_size - 2;
+  list_read = list + occupied_size - 2;
+  for ( ; list_write >= list; list_write -= 2 ) {
+    if (list_read >= list) {
+      while (ri->second > list_read[1]) {
+        assert(ri != begin);
+        --ri;
+      }
+    
+      if (list_read[0] > ri->second) {
+        list_write[0] = list_read[0];
+        list_write[1] = list_read[1];
+        list_read -= 2;
+        continue;
+      }
+    }
+    
+    assert( split_count > 0 );
+    list_write[0] = ri->second + 1;
+    list_write[1] = list_read[1];
+    list_read[1] = ri->first - 1;
 
-  for(std::set<MBEntityHandle>::reverse_iterator iter = tmp.rbegin();
-      iter != tmp.rend(); ++iter)
-  {
-    mRange.insert(*iter);
+      // don't have reverse iterator, so check before decrement
+      // if insert_count isn't zero, must be more in range
+    if (0 == --split_count) {
+      assert( list_read == list_write-2 );
+      break;
+    }
+    else {
+      --ri;
+    }
   }
 
-  //track owner
-  if(tracking() && mAdjFact)
-  {
-    tmp.clear();
-    std::set_difference(mRange.begin(), mRange.end(), other_range.begin(), other_range.end(),
-        std::inserter< std::set<MBEntityHandle> >(tmp, tmp.end()));
-
-    for(std::set<MBEntityHandle>::iterator iter = tmp.begin();
-        iter != tmp.end(); ++iter)
-      mAdjFact->remove_adjacency(*iter, mEntityHandle);
-  }
-
+  assert(!split_count);
   return MB_SUCCESS;
 }
 
-MBErrorCode MBMeshSet_MBRange::unite( const MBMeshSet *meshset_2,
-                                      MBEntityHandle handle,
-                                      AEntityFactory* adj_fact )
-{
-  MBRange other_range;
-  meshset_2->get_entities(other_range);
-  return add_entities( other_range, handle, adj_fact );
-}
 
-unsigned long MBMeshSet_MBRange::get_memory_use() const
+template <typename pair_iter_t> inline MBErrorCode
+range_tool<pair_iter_t>::vector_insert_entities( MBMeshSet::Count& count, 
+                                                 MBMeshSet::CompactList& clist, 
+                                                 pair_iter_t begin, 
+                                                 pair_iter_t end, 
+                                                 MBEntityHandle my_handle, 
+                                                 AEntityFactory* adj )
 {
-  return parent_child_memory_use() + mRange.get_memory_use();
-}
+  const size_t init_size = count < MBMeshSet::MANY ? count : clist.ptr[1] - clist.ptr[0];
+  size_t add_size = 0;
+  for (pair_iter_t i = begin; i != end; ++i)
+    add_size += i->second - i->first + 1;
+  MBEntityHandle* list = resize_compact_list( count, clist, init_size + add_size );
+  MBEntityHandle* li = list + init_size;
 
-
-MBErrorCode MBMeshSet_Vector::clear( MBEntityHandle mEntityHandle, 
-                                     AEntityFactory* mAdjFact)
-{
-  if(tracking() && mAdjFact)
-  {
-    for(std::vector<MBEntityHandle>::iterator iter = mVector.begin();
-        iter != mVector.end(); ++iter)
-    {
-      mAdjFact->remove_adjacency(*iter, mEntityHandle);
+  for (pair_iter_t i = begin; i != end; ++i) {
+    for (MBEntityHandle h = i->first; h <= i->second; ++h) {
+      if (adj)
+        adj->add_adjacency( h, my_handle, false );
+      *li = h;
+      ++li;
     }
   }
-  mVector.clear();
-  mVector.reserve(0);
+
   return MB_SUCCESS;
 }
 
-bool MBMeshSet_Vector::replace_entities(MBEntityHandle set_handle,
-                                        MBEntityHandle *entities,
-                                        int num_entities,
-                                        AEntityFactory* mAdjFact)
+static MBErrorCode vector_remove_range( MBMeshSet::Count& count, 
+                                        MBMeshSet::CompactList& clist, 
+                                        const MBRange& range, 
+                                        MBEntityHandle my_handle, 
+                                        AEntityFactory* adj )
 {
-  bool was_contained = false;
-  std::vector<MBEntityHandle>::iterator vit;
-  for (int i = 0; i < num_entities; i += 2) {
-    if ((vit = std::find(mVector.begin(), mVector.end(), entities[i])) 
-        != mVector.end()) {
-      *vit = entities[i+1];
-      was_contained = true;
+  MBEntityHandle *list;
+  size_t list_size;
+  if (count < MBMeshSet::MANY) {
+    list = clist.hnd;
+    list_size = count;
+  }
+  else {
+    list = clist.ptr[0];
+    list_size = clist.ptr[1] - clist.ptr[0];
+  }
 
-      if(tracking() && mAdjFact)
-        mAdjFact->remove_adjacency(entities[i], set_handle),
-          mAdjFact->add_adjacency(entities[i+1], set_handle);
+  const MBEntityHandle * const list_end = list + list_size;
+  MBEntityHandle* list_write = list;
+  for (const MBEntityHandle* list_read = list; list_read != list_end; ++list_read) {
+    if (range.find(*list_read) == range.end()) { // keep
+      *list_write = *list_read;
+      ++list_write;
     }
-    
-    if (remove_parent(entities[i]))
-      add_parent(entities[i+1]), was_contained = true;
+    else if (adj) {    
+      adj->remove_adjacency( *list_read, my_handle );
+    }
+  }
 
-    if (remove_child(entities[i]))
-      add_child(entities[i+1]), was_contained = true;
-  }
-  
-  return was_contained;
+  resize_compact_list( count, clist, list_write - list );
+  return MB_SUCCESS;
 }
 
-
-void MBMeshSet_Vector::vector_to_range( std::vector<MBEntityHandle>& vect, MBRange& range )
+static MBErrorCode vector_remove_ranges( MBMeshSet::Count& count, 
+                                         MBMeshSet::CompactList& clist, 
+                                         const MBEntityHandle* pair_list,
+                                         size_t num_pairs,
+                                         MBEntityHandle my_handle, 
+                                         AEntityFactory* adj )
 {
-  std::sort( vect.begin(), vect.end() );
-  MBRange::iterator insert_iter = range.begin();
-  std::vector<MBEntityHandle>::iterator iter = vect.begin();
-  while (iter != vect.end()) {
-    MBEntityHandle beg, end;
-    beg = end = *iter;
-    for (++iter; iter != vect.end() && *iter - end < 2; ++iter)
-      end = *iter;
-    insert_iter = range.insert( insert_iter, beg, end );
+  MBEntityHandle *list;
+  size_t list_size;
+  if (count < MBMeshSet::MANY) {
+    list = clist.hnd;
+    list_size = count;
   }
+  else {
+    list = clist.ptr[0];
+    list_size = clist.ptr[1] - clist.ptr[0];
+  }
+
+  const MBEntityHandle *const list_end = list + list_size, 
+                       *const input_end = pair_list + 2*num_pairs;
+  MBEntityHandle* list_write = list;
+  for (const MBEntityHandle* list_read = list; list_read != list_end; ++list_read) {
+    const MBEntityHandle* ptr = std::lower_bound( pair_list, input_end, *list_read );
+    if ((ptr != input_end && (*ptr == *list_read || (ptr - pair_list)%2)) && // if in delete list
+        std::find(list_read+1, list_end, *list_read) == list_end) { // and is last occurance in list 
+        // only remove adj if no previous occurance
+      if (adj && std::find(list, list_write, *list_read) == list_write)
+        adj->remove_adjacency( *list_read, my_handle );
+    }
+    else {
+      *list_write = *list_read;
+      ++list_write;
+    }
+  }
+
+  resize_compact_list( count, clist, list_write - list );
+  return MB_SUCCESS;
 }
 
-MBErrorCode MBMeshSet_Vector::add_entities( const MBEntityHandle *entities,
-                                            const int num_entities,
-                                            MBEntityHandle mEntityHandle,
-                                            AEntityFactory* mAdjFact )
+static MBErrorCode vector_remove_vector( MBMeshSet::Count& count, 
+                                         MBMeshSet::CompactList& clist, 
+                                         const MBEntityHandle* vect,
+                                         size_t vect_size,
+                                         MBEntityHandle my_handle, 
+                                         AEntityFactory* adj )
 {
-  unsigned int prev_size = mVector.size();
-  mVector.resize(prev_size + num_entities);
-  std::copy(entities, entities+num_entities, &mVector[prev_size]);
+  MBEntityHandle *list;
+  size_t list_size;
+  if (count < MBMeshSet::MANY) {
+    list = clist.hnd;
+    list_size = count;
+  }
+  else {
+    list = clist.ptr[0];
+    list_size = clist.ptr[1] - clist.ptr[0];
+  }
 
-  if(tracking() && mAdjFact)
-  {
-    for(int i = 0; i < num_entities; i++)
-      mAdjFact->add_adjacency(entities[i], mEntityHandle);
+  const MBEntityHandle *const list_end = list + list_size, 
+                       *const input_end = vect + vect_size;
+  MBEntityHandle* list_write = list;
+  for (const MBEntityHandle* list_read = list; list_read != list_end; ++list_read) {
+    if (std::find(vect, input_end, *list_read) != input_end && // if in delete list
+        std::find(list_read+1, list_end, *list_read) == list_end) { // and is last occurance in list 
+        // only remove adj if no previous occurance?
+      if (adj ) // && std::find(list, list_write, *list_read) == list_write)
+        adj->remove_adjacency( *list_read, my_handle );
+    }
+    else {
+      *list_write = *list_read;
+      ++list_write;
+    }
   }
 
+  resize_compact_list( count, clist, list_write - list );
   return MB_SUCCESS;
 }
 
+static MBErrorCode vector_insert_vector( MBMeshSet::Count& count, 
+                                         MBMeshSet::CompactList& clist, 
+                                         const MBEntityHandle* vect,
+                                         size_t vect_size,
+                                         MBEntityHandle my_handle, 
+                                         AEntityFactory* adj )
+{
+  const size_t orig_size = count < MBMeshSet::MANY ? count : clist.ptr[1] - clist.ptr[0];
+  MBEntityHandle* list = resize_compact_list( count, clist, orig_size + vect_size );
+  if (adj) 
+    for (size_t i = 0; i < vect_size; ++i)
+      adj->add_adjacency( vect[i], my_handle, false );
+  memcpy( list+orig_size, vect, sizeof(MBEntityHandle)*vect_size );
+  return MB_SUCCESS;
+}
 
-MBErrorCode MBMeshSet_Vector::add_entities( const MBRange& entities,
-                                            MBEntityHandle mEntityHandle,
-                                            AEntityFactory* mAdjFact )
+MBErrorCode MBMeshSet::insert_entity_ranges( const MBEntityHandle* range_vect, size_t len, MBEntityHandle my_h, AEntityFactory* adj )
 {
+  typedef const std::pair<MBEntityHandle,MBEntityHandle>* pair_vect_t;
+  pair_vect_t pair_vect = reinterpret_cast<pair_vect_t>(range_vect);
+  MBMeshSet::Count count = static_cast<MBMeshSet::Count>(mContentCount);
+  MBErrorCode rval;
+  if (!vector_based())
+    rval = range_tool<pair_vect_t>::ranged_insert_entities( count, contentList,  pair_vect, 
+                                             pair_vect + len/2, my_h, tracking() ? adj : 0 );
+  else
+    rval = range_tool<pair_vect_t>::vector_insert_entities( count, contentList,  pair_vect, 
+                                             pair_vect + len/2, my_h, tracking() ? adj : 0 );
+  mContentCount = count;
+  return rval;
+}
 
-  unsigned int prev_size = mVector.size();
-  mVector.resize(prev_size + entities.size());
-  std::copy(entities.begin(), entities.end(), &mVector[prev_size]);
-  
-  if(tracking() && mAdjFact)
-  {
-    for(MBRange::const_iterator iter = entities.begin();
-        iter != entities.end(); ++iter)
-      mAdjFact->add_adjacency(*iter, mEntityHandle);
+MBErrorCode MBMeshSet::insert_entity_ranges( const MBRange& range, MBEntityHandle my_h, AEntityFactory* adj )
+{
+  MBErrorCode rval;
+  MBMeshSet::Count count = static_cast<MBMeshSet::Count>(mContentCount);
+  if (!vector_based())
+    rval = range_tool<MBRange::const_pair_iterator>::ranged_insert_entities( count, 
+                             contentList, range.const_pair_begin(), range.const_pair_end(), 
+                             my_h, tracking() ? adj : 0 );
+  else
+    rval = range_tool<MBRange::const_pair_iterator>::vector_insert_entities( count, 
+                             contentList, range.const_pair_begin(), range.const_pair_end(), 
+                             my_h, tracking() ? adj : 0 );
+  mContentCount = count;
+  return rval;
+}
+
+MBErrorCode MBMeshSet::remove_entity_ranges( const MBEntityHandle* range_vect, size_t len, MBEntityHandle my_h, AEntityFactory* adj )
+{
+  MBErrorCode rval;
+  MBMeshSet::Count count = static_cast<MBMeshSet::Count>(mContentCount);
+  if (vector_based()) 
+    rval = vector_remove_ranges( count, contentList, range_vect, len/2, my_h, 
+                                 tracking() ? adj : 0 );
+  else {
+    typedef const std::pair<MBEntityHandle,MBEntityHandle>* pair_vect_t;
+    pair_vect_t pair_vect = reinterpret_cast<pair_vect_t>(range_vect);
+    rval = range_tool<pair_vect_t>::ranged_remove_entities( count, contentList, pair_vect, 
+                                           pair_vect + len/2, my_h, tracking() ? adj : 0 );
   }
+  mContentCount = count;
+  return rval;
+}
 
-  return MB_SUCCESS;
+MBErrorCode MBMeshSet::remove_entity_ranges( const MBRange& range, MBEntityHandle my_h, AEntityFactory* adj )
+{
+  MBErrorCode rval;
+  MBMeshSet::Count count = static_cast<MBMeshSet::Count>(mContentCount);
+  if (vector_based()) 
+    rval = vector_remove_range( count, contentList, range, my_h, tracking() ? adj : 0 );
+  else 
+    rval = range_tool<MBRange::const_pair_iterator>::ranged_remove_entities( count, 
+                         contentList, range.const_pair_begin(), range.const_pair_end(), 
+                         my_h, tracking() ? adj : 0 );
+  mContentCount = count;
+  return rval;
 }
 
 
-MBErrorCode MBMeshSet_Vector::remove_entities( const MBRange& entities,
-                                               MBEntityHandle mEntityHandle,
-                                               AEntityFactory* mAdjFact )
+MBErrorCode MBMeshSet::intersect( const MBMeshSet* other, MBEntityHandle my_handle, AEntityFactory* adj )
 {
-  std::vector<MBEntityHandle>::iterator iter = mVector.begin();
-  for(; iter < mVector.end(); )
-  {
-    if(entities.find(*iter) != entities.end())
-    {
-      if(tracking() && mAdjFact)
-        mAdjFact->remove_adjacency(*iter, mEntityHandle);
-      iter = mVector.erase(iter);
+  MBErrorCode rval;
+  if (!vector_based() && !other->vector_based()) {
+    size_t other_count = 0;
+    const MBEntityHandle* other_vect = other->get_contents( other_count );
+    if (!other_count)
+      return clear( my_handle, adj );
+    assert(0 == other_count%2);
+    
+    std::vector<MBEntityHandle> compliment;
+    compliment.reserve( other_count + 4 );
+    if (*other_vect > 0) {
+      compliment.push_back( 0 );
+      compliment.push_back( *other_vect - 1 );
     }
-    else
-      ++iter;
+    ++other_vect;
+    const MBEntityHandle *const other_end = other_vect + other_count - 2;
+    for (; other_vect < other_end; other_vect += 2) {
+      compliment.push_back( other_vect[0] + 1 );
+      compliment.push_back( other_vect[1] - 1 );
+    }
+    if (*other_vect < ~(MBEntityHandle)0) {
+      compliment.push_back( *other_vect + 1 );
+      compliment.push_back( ~(MBEntityHandle)0 );
+    }
+    
+    return remove_entity_ranges( &compliment[0], compliment.size(), my_handle, adj );
   }
-
-  return MB_SUCCESS;
-
+  else {
+    MBRange my_ents, other_ents;
+    rval = get_entities(my_ents);
+    if (MB_SUCCESS != rval)
+      return rval;
+    rval = other->get_entities(other_ents);
+    return remove_entities( my_ents.subtract(other_ents), my_handle, adj );
+  }
 }
 
-MBErrorCode MBMeshSet_Vector::remove_entities( const MBEntityHandle *entities, 
-                                               const int num_entities,
-                                               MBEntityHandle mEntityHandle,
-                                               AEntityFactory* mAdjFact )
+static void convert_to_ranges( const MBEntityHandle* vect_in, size_t vect_in_len,
+                               std::vector<MBEntityHandle>& vect_out )
 {
-  std::vector<MBEntityHandle>::iterator temp_iter;
-  for(int i = 0; i != num_entities; i++ )
-  {
-    temp_iter = std::find( mVector.begin(), mVector.end(), entities[i]); 
-    if( temp_iter != mVector.end() )
-    {
-      if(tracking() && mAdjFact)
-        mAdjFact->remove_adjacency(entities[i], mEntityHandle);
-      mVector.erase(temp_iter);
+  vect_out.reserve( 2*vect_in_len );
+  vect_out.resize( vect_in_len );
+  std::copy( vect_in, vect_in+vect_in_len, vect_out.begin() );
+  std::sort( vect_out.begin(), vect_out.end() );
+
+    // duplicate all entries
+  vect_out.resize( vect_out.size() * 2 );
+  for (long i = vect_out.size() - 1; i >= 0; --i) 
+    vect_out[i] = vect_out[i/2];
+   
+    // compact adjacent ranges
+  std::vector<MBEntityHandle>::iterator r = vect_out.begin(), w = vect_out.begin();
+  while (r != vect_out.end()) {
+    *w = *r;
+    ++w; 
+    ++r;
+    *w = *r;
+    ++r;
+    
+    while (r != vect_out.end() && *w + 1 == *r) {
+      ++r;
+      *w = *r;
+      ++r;
     }
+    ++w;
   }
-  return MB_SUCCESS;
+  
+    // remove extra space
+  vect_out.erase( w, vect_out.end() );
 }
 
-MBErrorCode MBMeshSet_Vector::subtract( const MBMeshSet *meshset_2,
-                                        MBEntityHandle my_handle,
-                                        AEntityFactory* adj_fact )
+MBErrorCode MBMeshSet::insert_entity_vector( const MBEntityHandle* vect, size_t len, MBEntityHandle my_h, AEntityFactory* adj )
 {
-  std::vector<MBEntityHandle> other_vector;
-  meshset_2->get_entities(other_vector);
-
-  return remove_entities(&other_vector[0], other_vector.size(), my_handle, adj_fact);
+  MBMeshSet::Count count = static_cast<MBMeshSet::Count>(mContentCount);
+  MBErrorCode rval;
+  if (vector_based())
+    rval = vector_insert_vector( count, contentList, vect, len, my_h, tracking() ? adj : 0 );
+  else {
+    std::vector<MBEntityHandle> rangevect;
+    convert_to_ranges( vect, len, rangevect );
+    typedef const std::pair<MBEntityHandle,MBEntityHandle>* pair_vect_t;
+    pair_vect_t pair_vect = reinterpret_cast<pair_vect_t>(&rangevect[0]);
+    rval = range_tool<pair_vect_t>::ranged_insert_entities( count, contentList, pair_vect, 
+                                 pair_vect + rangevect.size()/2, my_h, tracking() ? adj : 0 );
+  }
+  mContentCount = count;
+  return rval;
 }
 
-MBErrorCode MBMeshSet_Vector::intersect( const MBMeshSet *meshset_2,
-                                         MBEntityHandle mEntityHandle,
-                                         AEntityFactory* mAdjFact )
+MBErrorCode MBMeshSet::remove_entity_vector( const MBEntityHandle* vect, size_t len, MBEntityHandle my_h, AEntityFactory* adj )
 {
-  MBRange other_range;
-  meshset_2->get_entities(other_range);
+  MBMeshSet::Count count = static_cast<MBMeshSet::Count>(mContentCount);
+  MBErrorCode rval;
+  if (vector_based())
+    rval = vector_remove_vector( count, contentList, vect, len, my_h, tracking() ? adj : 0 );
+  else {
+    std::vector<MBEntityHandle> rangevect;
+    convert_to_ranges( vect, len, rangevect );
+    typedef const std::pair<MBEntityHandle,MBEntityHandle>* pair_vect_t;
+    pair_vect_t pair_vect = reinterpret_cast<pair_vect_t>(&rangevect[0]);
+    rval = range_tool<pair_vect_t>::ranged_remove_entities( count, contentList, pair_vect, 
+                                pair_vect + rangevect.size()/2, my_h, tracking() ? adj : 0 );
+  }
+  mContentCount = count;
+  return rval;
+}
 
-  std::sort(mVector.begin(), mVector.end());
 
-  std::set<MBEntityHandle> tmp;
 
-  std::set_intersection(mVector.begin(), mVector.end(), other_range.begin(), other_range.end(), 
-      std::inserter< std::set<MBEntityHandle> >(tmp, tmp.end()));
+bool MBMeshSet::replace_entities( MBEntityHandle my_handle,
+                                  const MBEntityHandle* entities,
+                                  size_t num_entities,
+                                  AEntityFactory* adjfact )
+{
+  assert(0 == num_entities%2);
+  if (vector_based()) {
+    bool was_contained = false;
+    size_t count;
+    MBEntityHandle* vect = get_contents( count );
+    MBEntityHandle* const vect_end = vect+count;
+    for (size_t i = 0; i < num_entities; i+=2) {
+      for (MBEntityHandle* p = vect; p != vect_end; ++p ) {
+        if (*p == entities[i]) {
+          if (tracking()) {
+            adjfact->remove_adjacency( *p, my_handle );
+            adjfact->add_adjacency( entities[i+1], my_handle, false );
+          }
+          *p = entities[i+1];
+          was_contained = true;
+        }
+      }
+    }
+    return was_contained;
+  }
+  else {
+    std::vector<MBEntityHandle> swap_list;
+    swap_list.reserve( num_entities / 2 );
 
-  mVector.resize(tmp.size());
-
-  std::copy(tmp.begin(), tmp.end(), mVector.begin());
-
-  //track owner
-  tmp.clear();
-  std::set_difference(mVector.begin(), mVector.end(), other_range.begin(), other_range.end(),
-      std::inserter< std::set<MBEntityHandle> >(tmp, tmp.end()));
-
-  if(tracking() && mAdjFact)
-  {
-    for(std::set<MBEntityHandle>::iterator iter = tmp.begin();
-        iter != tmp.end(); ++iter)
-      mAdjFact->remove_adjacency(*iter, mEntityHandle);
+      // get list of handles to remove
+    size_t count;
+    MBEntityHandle* vect = get_contents( count );
+    MBEntityHandle* const vect_end = vect+count;
+    for (size_t i = 0; i < num_entities; i+=2) {
+      MBEntityHandle* p = std::lower_bound(vect, vect_end, entities[i]);
+      if (p != vect_end && (*p == entities[i] || (p-vect)%2 == 1))
+        swap_list.push_back(entities[i]);
+    }
+    if (swap_list.empty())
+      return false;
+    
+      // remove entities
+    remove_entities( &swap_list[0], swap_list.size(), my_handle, adjfact );
+    
+      // get list of handles to add
+    std::vector<MBEntityHandle>::iterator si = swap_list.begin();
+    for (size_t i = 0; i < num_entities; ++i) {
+      if (entities[i] == *si) {
+        *si = entities[i+1];
+        if (++si == swap_list.end())
+          break;
+      }
+    }
+    
+      // add entities
+    add_entities( &swap_list[0], swap_list.size(), my_handle, adjfact );
+    return true;
   }
-
-  return MB_SUCCESS;
 }
 
-MBErrorCode MBMeshSet_Vector::unite( const MBMeshSet *meshset_2,
-                                     MBEntityHandle my_handle,
-                                     AEntityFactory* adj_fact )
-{
-  std::vector<MBEntityHandle> other_vector;
-  meshset_2->get_entities(other_vector);
-  return add_entities(&other_vector[0], other_vector.size(), my_handle, adj_fact);
-}
 
-unsigned long MBMeshSet_Vector::get_memory_use() const
+/*****************************************************************************************
+ *                                  Misc. Methods                                        *
+ *****************************************************************************************/
+
+unsigned long MBMeshSet::get_memory_use() const
 {
-  return parent_child_memory_use() 
-       + mVector.capacity()*sizeof(MBEntityHandle);
+  unsigned long result = 0;
+  if (mParentCount == MANY)
+    result += parentMeshSets.ptr[1] - parentMeshSets.ptr[0];
+  if (mChildCount == MANY)
+    result += childMeshSets.ptr[1] - childMeshSets.ptr[0];
+  if (mContentCount == MANY)
+    result += contentList.ptr[1] - contentList.ptr[0];
+  return sizeof(MBEntityHandle)*result;
 }
-

Modified: MOAB/trunk/MBMeshSet.hpp
===================================================================
--- MOAB/trunk/MBMeshSet.hpp	2008-03-31 20:29:26 UTC (rev 1730)
+++ MOAB/trunk/MBMeshSet.hpp	2008-04-01 15:49:58 UTC (rev 1731)
@@ -1,30 +1,3 @@
-/**
- * MOAB, a Mesh-Oriented datABase, is a software component for creating,
- * storing and accessing finite element mesh data.
- * 
- * Copyright 2004 Sandia Corporation.  Under the terms of Contract
- * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
- * retains certain rights in this software.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- */
-
-//
-//-------------------------------------------------------------------------
-// Filename      : MB_MeshSet.hpp 
-// Creator       : Tim Tautges
-//
-// Date          : 02/01/02
-//
-// Owner         : Tim Tautges
-//
-// Description   : MB_MeshSet is the MB implementation of MeshSet
-//-------------------------------------------------------------------------
-
 #ifndef MB_MESHSET_HPP
 #define MB_MESHSET_HPP
 
@@ -32,88 +5,46 @@
 #error "MB_MeshSet.hpp isn't supposed to be included into an application"
 #endif
 
-#include "MBTypes.h"
+#include "MBInterface.hpp"
+#include "MBInternals.hpp"
 #include "MBRange.hpp"
-#include "MBInterface.hpp"
 #include "MBCN.hpp"
 
+#include <assert.h>
 #include <vector>
 #include <algorithm>
+#include <iterator>
 
-#define MB_MESH_SET_COMPACT_PARENT_CHILD_LISTS
-
-
 class AEntityFactory;
 
+/** \brief Class to implement entity set functionality 
+  * \author Jason Kraftcheck <kraftche at cae.wisc.edu>
+  */
 class MBMeshSet
 {
-protected:
+public:
 
   //! create an empty meshset
-  MBMeshSet( unsigned flags );
+  inline MBMeshSet();
+  inline MBMeshSet(unsigned flags);
 
   //! destructor
-  ~MBMeshSet();
-
-public:
-
-#ifndef MB_MESH_SET_COMPACT_PARENT_CHILD_LISTS
-    //! get all children pointed to by this meshset
-  const MBEntityHandle* get_children( int& count_out ) const 
-    { count_out = childMeshSets.size(); return &childMeshSets[0]; }
-
-    //! get all parents pointed to by this meshset
-  const MBEntityHandle* get_parents( int& count_out ) const
-    { count_out = parentMeshSets.size(); return &parentMeshSets[0]; }
-
-    //! return the number of children pointed to by this meshset
-  int num_children() const { return childMeshSets.size(); }
+  inline ~MBMeshSet();
+  
+  inline MBErrorCode set_flags( unsigned flags, MBEntityHandle my_handle, AEntityFactory* adjacencies );
     
-    //! return the number of parents pointed to by this meshset
-  int num_parents() const { return parentMeshSets.size(); }
 
-#else
     //! get all children pointed to by this meshset
-  const MBEntityHandle* get_children( int& count_out ) const 
-    { 
-      count_out = mChildCount;
-      if (count_out < MANY)
-        return childMeshSets.hnd;
-      
-      count_out = childMeshSets.ptr[1] - childMeshSets.ptr[0];
-      return childMeshSets.ptr[0];
-    }
+  inline const MBEntityHandle* get_children( int& count_out ) const ;
 
     //! get all parents pointed to by this meshset
-  const MBEntityHandle* get_parents( int& count_out ) const
-    { 
-      count_out = mParentCount;
-      if (count_out < MANY)
-        return parentMeshSets.hnd;
-        
-      count_out = parentMeshSets.ptr[1] - parentMeshSets.ptr[0];
-      return parentMeshSets.ptr[0];
-    }
+  inline const MBEntityHandle* get_parents( int& count_out ) const;
 
     //! return the number of children pointed to by this meshset
-  int num_children() const 
-    {
-      if (mChildCount < MANY)
-        return mChildCount;
-      else
-        return childMeshSets.ptr[1] - childMeshSets.ptr[0];
-    }
+  inline int num_children() const ;
     
     //! return the number of parents pointed to by this meshset
-  int num_parents() const
-    {
-      if (mParentCount < MANY)
-        return mParentCount;
-      else
-        return parentMeshSets.ptr[1] - parentMeshSets.ptr[0];
-    }
-#endif
-  
+  inline int num_parents() const;
 
     //! add a parent to this meshset; returns true if parent was added, 0 if it was
     //! already a parent of this meshset
@@ -138,45 +69,63 @@
   int ordered()      const { return mFlags & MESHSET_ORDERED; }
   int vector_based() const { return ordered(); }
 
-   //!  PURE VIRTUAL FUNCTIONS overwritten by derived classes  *******************
-
     //! replace one entity with another in the set (contents and parent/child
     //! lists); returns whether it was replaced or not
-  inline bool replace_entities(MBEntityHandle my_handle, 
-                               MBEntityHandle *entities, int num_entities,
-                               AEntityFactory* mAdjFact);
+  bool replace_entities(MBEntityHandle my_handle, 
+                        const MBEntityHandle *entities, 
+                        size_t num_entities,
+                        AEntityFactory* mAdjFact);
   
+    /** Clear *contents* of set (not parents or children) */
   inline MBErrorCode clear( MBEntityHandle myhandle, AEntityFactory* adjacencies );
+  
+    /** Clear all set lists (contents, parents, and children) */
+  inline MBErrorCode clear_all( MBEntityHandle myhandle, AEntityFactory* adjacencies );
 
+    /** Get contents data array.  NOTE: this may not contain what you expect if not vector_based */
+  inline const MBEntityHandle* get_contents( size_t& count_out ) const;
+    /** Get contents data array.  NOTE: this may not contain what you expect if not vector_based */
+  inline MBEntityHandle* get_contents( size_t& count_out );
+
+    /** Get entities contained in set */
   inline MBErrorCode get_entities(std::vector<MBEntityHandle>& entities) const;
+
+    /** Get entities contained in set */
+  inline MBErrorCode get_entities( MBRange& entities ) const;
   
-  inline MBErrorCode get_entities(MBRange& entities) const;
-  
     //! get all entities in this MeshSet with the specified type
-  inline MBErrorCode get_entities_by_type(MBEntityType entity_type,
-      std::vector<MBEntityHandle> &entity_list) const;
+  inline MBErrorCode get_entities_by_type(MBEntityType entity_type, std::vector<MBEntityHandle> &entity_list) const;
   
-  inline MBErrorCode get_entities_by_type(MBEntityType type,
-      MBRange& entity_list) const;
+  inline MBErrorCode get_entities_by_type( MBEntityType type, MBRange& entity_list) const;
+    
+    //! return the number of entities with the given type contained in this meshset
+  inline unsigned int num_entities_by_type(MBEntityType type) const;
       
-  inline MBErrorCode get_entities_by_dimension( int dimension,
-      std::vector<MBEntityHandle> &entity_list) const;
+  inline MBErrorCode get_entities_by_dimension( int dimension, std::vector<MBEntityHandle> &entity_list) const;
 
-  inline MBErrorCode get_entities_by_dimension( int dimension,
-      MBRange& entity_list) const;
+  inline MBErrorCode get_entities_by_dimension( int dimension, MBRange& entity_list) const;
+  
+    //! return the number of entities with the given type contained in this meshset
+  inline unsigned int num_entities_by_dimension(int dimension) const;
       
   inline MBErrorCode get_non_set_entities( MBRange& range ) const;
 
-  inline bool contains_entities(MBEntityHandle *entities, 
-                                int num_entities,
-                                const int operation_type) const;
+  /** Test of meshset contains some or all of passed entities
+   *
+   *\param entities Array of entities
+   *\param num_entities Length of array of entities.
+   *\param op - MBInterface::UNION     : Test if set contains any of the input entities
+   *          - MBInterface::INTERSECT : Test if set contains all of the input entities
+   */
+  inline bool contains_entities(const MBEntityHandle *entities, int num_entities, const int op) const;
+
   
   //! subtract/intersect/unite meshset_2 from/with/into meshset_1; modifies meshset_1
   inline MBErrorCode subtract(const MBMeshSet *meshset_2,
                                MBEntityHandle my_handle,
                                AEntityFactory* adjacencies);
 
-  inline MBErrorCode intersect(const MBMeshSet *meshset_2,
+  MBErrorCode intersect(const MBMeshSet *meshset_2,
                                 MBEntityHandle my_handle,
                                 AEntityFactory* adjacencies);
 
@@ -199,6 +148,7 @@
   inline MBErrorCode remove_entities(const MBRange& entities,
                                       MBEntityHandle my_handle,
                                       AEntityFactory* adjacencies);
+    
    
     //! remove these entities from this meshset
   inline MBErrorCode remove_entities(const MBEntityHandle *entities,
@@ -208,32 +158,40 @@
 
     //! return the number of entities contained in this meshset
   inline unsigned int num_entities() const;
-    
-    //! return the number of entities with the given type contained in this meshset
-  inline unsigned int num_entities_by_type(MBEntityType entity_type) const;
-    
-    //! return the number of entities with the given type contained in this meshset
-  inline unsigned int num_entities_by_dimension(int dimension) const;
-
-  typedef std::vector<MBEntityHandle> LinkSet;
   
-  inline unsigned long get_memory_use() const;
+  inline bool empty() const { return mContentCount == ZERO; }
+  
+  unsigned long get_memory_use() const;
 
 protected:
+  
+  /** Convert for changing flag values */
+  MBErrorCode convert( unsigned flags, MBEntityHandle my_handle, AEntityFactory* adj );
 
-  unsigned long parent_child_memory_use() const;
+  /** Add explicit adjacencies from all contained entities to this (i.e. convert to tracking) */
+  MBErrorCode create_adjacencies( MBEntityHandle myhandle, AEntityFactory* adjacencies );
 
-#ifndef MB_MESH_SET_COMPACT_PARENT_CHILD_LISTS
-  //!Meshset propery flags
-  unsigned char mFlags;
-    //! links to parents/children
-  LinkSet parentMeshSets, childMeshSets;
-  
-  //!flag to indicate whether 'tracking' is occuring on this meshset
-  //ie. all entities of the meshset know they belong to this meshset 
-  bool mTracking;
-#else
+  /** Remvoe explicit adjacencies from all contained entities to this (i.e. convert from tracking) */
+  MBErrorCode remove_adjacencies( MBEntityHandle myhandle, AEntityFactory* adjacencies );
 
+  /** Insert vector of handles into MBMeshSet */
+  MBErrorCode insert_entity_vector( const MBEntityHandle* vect, size_t len, MBEntityHandle my_h, AEntityFactory* adj );
+ 
+  /** Insert vector of handle range pairs into MBMeshSet */
+  MBErrorCode insert_entity_ranges( const MBEntityHandle* range_vect, size_t len, MBEntityHandle my_h, AEntityFactory* adj );
+
+  /** Insert MBRange of handles into MBMeshSet */
+  MBErrorCode insert_entity_ranges( const MBRange& range, MBEntityHandle my_h, AEntityFactory* adj );
+
+  /** Remove vector of handles from MBMeshSet */
+  MBErrorCode remove_entity_vector( const MBEntityHandle* vect, size_t len, MBEntityHandle my_h, AEntityFactory* adj );
+
+  /** Remove vector of handle range pairs from MBMeshSet */
+  MBErrorCode remove_entity_ranges( const MBEntityHandle* range_vect, size_t len, MBEntityHandle my_h, AEntityFactory* adj );
+
+  /** Remove MBRange of handles from MBMeshSet */
+  MBErrorCode remove_entity_ranges( const MBRange& range, MBEntityHandle my_h, AEntityFactory* adj );
+
 public:  
     //! Possible values of mParentCount and mChildCount
   enum Count { ZERO=0, ONE=1, TWO=2, MANY=3 };
@@ -245,7 +203,8 @@
     MBEntityHandle hnd[2];  //!< Two handles
     MBEntityHandle* ptr[2]; //!< begin and end pointers for array
   };
-protected:
+
+private:
   //!Meshset propery flags
   unsigned char mFlags;
   //! If less than MANY, the number of parents stored inline in
@@ -258,110 +217,27 @@
   //! array begin and end pointers for a dynamically allocated array
   //! of child handles.
   unsigned mChildCount : 2;
-private:
-  //! Storage for parent and child lists
-  CompactList parentMeshSets, childMeshSets;
-#endif
-};
+  //! If less than MANY, the number of children stored inline in
+  //! contentList.hnd.  If MANY, then contentList.ptr contains
+  //! array begin and end pointers for a dynamically allocated array..
+  unsigned mContentCount : 2;
+  //! Storage for data lists
+  CompactList parentMeshSets, childMeshSets, contentList;
 
-#define MESH_SET_VIRTUAL_FUNCTIONS      \
-  MBErrorCode clear( MBEntityHandle my_handle, AEntityFactory* adjacencies); \
-  \
-  bool replace_entities(MBEntityHandle my_handle, MBEntityHandle *entities, \
-                                       int num_entities, AEntityFactory* mAdjFact); \
-  \
-  inline MBErrorCode get_entities(std::vector<MBEntityHandle>& entities) const;       \
-  \
-  inline MBErrorCode get_entities(MBRange& entities) const;                           \
-  \
-  inline MBErrorCode get_entities_by_type(MBEntityType type,                          \
-      std::vector<MBEntityHandle>& entity_list) const;                                  \
-  \
-  inline MBErrorCode get_entities_by_type(MBEntityType type,                          \
-      MBRange& entity_list) const;                                                      \
-  \
-  inline MBErrorCode get_entities_by_dimension(int dimension,                          \
-      std::vector<MBEntityHandle>& entity_list) const;                                  \
-  \
-  inline MBErrorCode get_entities_by_dimension(int dimension,                          \
-      MBRange& entity_list) const;                                                      \
-  \
-  inline bool contains_entities(MBEntityHandle *entities, \
-                                int num_entities, \
-                                const int operation_type) const; \
-  \
-  inline MBErrorCode get_non_set_entities( MBRange& range ) const; \
-  \
-  MBErrorCode subtract(const MBMeshSet*,                          \
-                               MBEntityHandle my_handle,                  \
-                               AEntityFactory* adjacencies);              \
-  \
-  MBErrorCode intersect(const MBMeshSet *meshset_2,               \
-                                MBEntityHandle my_handle,                 \
-                                AEntityFactory* adjacencies);             \
-  \
-  MBErrorCode unite(const MBMeshSet *meshset_2,                   \
-                            MBEntityHandle my_handle,                     \
-                            AEntityFactory* adjacencies);                 \
-  \
-  MBErrorCode add_entities(const MBEntityHandle *entity_handles,  \
-                                   const int num_entities,                \
-                                   MBEntityHandle my_handle,              \
-                                   AEntityFactory* adjacencies);          \
-  \
-  MBErrorCode add_entities(const MBRange &entities,               \
-                                   MBEntityHandle my_handle,              \
-                                   AEntityFactory* adjacencies);          \
-  \
-  MBErrorCode remove_entities(const MBRange& entities,            \
-                                      MBEntityHandle my_handle,           \
-                                      AEntityFactory* adjacencies);       \
-  \
-  MBErrorCode remove_entities(const MBEntityHandle *entities,     \
-                                      const int num_entities,             \
-                                      MBEntityHandle my_handle,           \
-                                      AEntityFactory* adjacencies);       \
-  \
-  inline unsigned int num_entities() const;                                        \
-  \
-  inline unsigned int num_entities_by_type(MBEntityType entity_type) const;            \
-  \
-  inline unsigned int num_entities_by_dimension(int dimesion) const; \
-  \
-  unsigned long get_memory_use() const;
-
-
-
-class MBMeshSet_MBRange : public MBMeshSet
-{
 public:
+    /** get dimension of enity */
+  static inline int DIM_FROM_HANDLE( MBEntityHandle h )
+    { return MBCN::Dimension( TYPE_FROM_HANDLE( h ) ); }
+  
+    /** Get smallest possible handle with specified dimension (first handle for first type of dimension) */
+  static inline MBEntityHandle FIRST_OF_DIM( int dim )
+    { return FIRST_HANDLE( MBCN::TypeDimensionMap[dim].first ); }
+  
+    /** Get largest possible handle with specified dimension (largest handle for last type of dimension) */
+  static inline MBEntityHandle LAST_OF_DIM( int dim )
+    { return LAST_HANDLE( MBCN::TypeDimensionMap[dim].second ); }
 
-  MBMeshSet_MBRange(bool track_ownership) 
-    : MBMeshSet(track_ownership ? 
-                MESHSET_SET|MESHSET_TRACK_OWNER :
-                MESHSET_SET) {}
-
-  MESH_SET_VIRTUAL_FUNCTIONS
-
-private:
-  MBRange mRange;
-
-};
-
-class MBMeshSet_Vector : public MBMeshSet
-{
-public:
-
-  MBMeshSet_Vector(bool track_ownership) 
-    : MBMeshSet(track_ownership ?
-                MESHSET_ORDERED|MESHSET_TRACK_OWNER :
-                MESHSET_ORDERED) {}
-
-  MESH_SET_VIRTUAL_FUNCTIONS
-
-private:
-  static void vector_to_range( std::vector<MBEntityHandle>& vect, MBRange& range );
-
+    /** functor: test if handle is not of type */
   struct not_type_test {
       inline not_type_test( MBEntityType type ) : mType(type) {}
       inline bool operator()( MBEntityHandle handle )
@@ -369,6 +245,7 @@
       MBEntityType mType;
   };
 
+    /** functor: test if handle is of type */
   struct type_test {
       inline type_test( MBEntityType type ) : mType(type) {}
       inline bool operator()( MBEntityHandle handle )
@@ -376,409 +253,538 @@
       MBEntityType mType;
   };
 
+    /** functor: test if handle is not of dimension */
   struct not_dim_test {
       inline not_dim_test( int dimension ) : mDim(dimension) {}
       inline bool operator()( MBEntityHandle handle ) const
-        { return MBCN::Dimension(TYPE_FROM_HANDLE(handle)) != mDim; }
+        { return DIM_FROM_HANDLE(handle) != mDim; }
       int mDim;
   };
 
+    /** functor: test if handle is of dimension */
   struct dim_test {
       inline dim_test( int dimension ) : mDim(dimension) {}
       inline bool operator()( MBEntityHandle handle ) const
-        { return MBCN::Dimension(TYPE_FROM_HANDLE(handle)) == mDim; }
+        { return DIM_FROM_HANDLE(handle) == mDim; }
       int mDim;
   };
-
-
-    std::vector<MBEntityHandle> mVector;
+  
+    /** Iterate over range of handles.  That is, given [first_handle,last_handle],
+     *  step through all contained values.
+     */
+  struct hdl_iter {
+    MBEntityHandle h;
+    hdl_iter( MBEntityHandle val ) : h(val) {}
+    hdl_iter& operator++() { ++h; return *this; }
+    hdl_iter& operator--() { --h; return *this; }
+    hdl_iter operator++(int) { return hdl_iter(h++); }
+    hdl_iter operator--(int) { return hdl_iter(h--); }
+    hdl_iter& operator+=(size_t s) { h += s; return *this; }
+    hdl_iter& operator-=(size_t s) { h -= s; return *this; }
+    MBEntityHandle operator*() const { return h; }
+    bool operator==(hdl_iter other) const { return h == other.h; }
+    bool operator!=(hdl_iter other) const { return h != other.h; }
+    bool operator< (hdl_iter other) const { return h <  other.h; }
+    bool operator> (hdl_iter other) const { return h >  other.h; }
+    bool operator<=(hdl_iter other) const { return h <= other.h; }
+    bool operator>=(hdl_iter other) const { return h >= other.h; }
+    
+    struct iterator_category : public std::random_access_iterator_tag { };
+    typedef MBEntityID difference_type;
+    typedef MBEntityHandle value_type;
+    typedef MBEntityHandle* pointer;
+    typedef MBEntityHandle& reference;
+  };
+  
 };
 
-inline bool
-MBMeshSet::replace_entities( MBEntityHandle my_handle, 
-                             MBEntityHandle *entities, int num_entities,
-                             AEntityFactory* mAdjFact)
-{ 
-  return vector_based() ?
-    reinterpret_cast<MBMeshSet_Vector* >(this)->replace_entities(my_handle, entities, num_entities,
-                                                                 mAdjFact) :
-    reinterpret_cast<MBMeshSet_MBRange*>(this)->replace_entities(my_handle, entities, num_entities,
-                                                                 mAdjFact);
-}
 
-inline MBErrorCode 
-MBMeshSet::clear( MBEntityHandle myhandle, AEntityFactory* adjacencies )
-{ 
-  return vector_based() ?
-    reinterpret_cast<MBMeshSet_Vector* >(this)->clear( myhandle, adjacencies ) :
-    reinterpret_cast<MBMeshSet_MBRange*>(this)->clear( myhandle, adjacencies ) ;
-}
+  //! create an empty meshset
+MBMeshSet::MBMeshSet()
+  : mFlags(0), mParentCount(ZERO), mChildCount(ZERO), mContentCount(ZERO)
+{ }
 
-inline MBErrorCode
-MBMeshSet::get_entities(std::vector<MBEntityHandle>& entities) const
-{ 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->get_entities( entities ) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->get_entities( entities ) ;
-}
+  //! create an empty meshset
+MBMeshSet::MBMeshSet(unsigned flags)
+  : mFlags(flags), mParentCount(ZERO), mChildCount(ZERO), mContentCount(ZERO)
+{ }
 
-inline MBErrorCode
-MBMeshSet::get_entities(MBRange& entities) const
-{ 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->get_entities( entities ) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->get_entities( entities ) ;
+  //! destructor
+MBMeshSet::~MBMeshSet() 
+{
+  if (mChildCount == MANY)
+    free( childMeshSets.ptr[0] );
+  if (mParentCount == MANY)
+    free( parentMeshSets.ptr[0] );
+  if (mContentCount == MANY)
+    free( contentList.ptr[0] );
+  mChildCount = mParentCount = mContentCount = ZERO;
 }
-
-  //! get all entities in this MeshSet with the specified type
-inline MBErrorCode
-MBMeshSet::get_entities_by_type(MBEntityType type, std::vector<MBEntityHandle> &entities) const
-{ 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->get_entities_by_type( type, entities ) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->get_entities_by_type( type, entities ) ;
+  
+MBErrorCode MBMeshSet::set_flags( unsigned flags, MBEntityHandle my_handle, AEntityFactory* adjacencies ) 
+{
+  if (mContentCount == 0) {
+    mFlags = flags;
+    return MB_SUCCESS;
+  }
+  else 
+    return convert( flags, my_handle, adjacencies );
 }
+    
 
-inline MBErrorCode
-MBMeshSet::get_entities_by_type(MBEntityType type, MBRange& entities) const
+//! get all children pointed to by this meshset
+const MBEntityHandle* MBMeshSet::get_children( int& count_out ) const 
 { 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->get_entities_by_type( type, entities ) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->get_entities_by_type( type, entities ) ;
-}
-    
-inline MBErrorCode
-MBMeshSet::get_entities_by_dimension( int dim, std::vector<MBEntityHandle> &entities) const
-{ 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->get_entities_by_dimension( dim, entities ) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->get_entities_by_dimension( dim, entities ) ;
-}
+  count_out = mChildCount;
+  if (count_out < MANY)
+    return childMeshSets.hnd;
 
-inline MBErrorCode
-MBMeshSet::get_entities_by_dimension( int dim, MBRange& entities) const
-{ 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->get_entities_by_dimension( dim, entities ) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->get_entities_by_dimension( dim, entities ) ;
+  count_out = childMeshSets.ptr[1] - childMeshSets.ptr[0];
+  return childMeshSets.ptr[0];
 }
-    
-inline MBErrorCode
-MBMeshSet::get_non_set_entities( MBRange& entities ) const
-{ 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->get_non_set_entities( entities ) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->get_non_set_entities( entities ) ;
-}
-  
-inline bool
-MBMeshSet::contains_entities(MBEntityHandle *entities, int num_entities,
-                             const int operation_type) const
-{ 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->contains_entities(entities, num_entities, operation_type) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->contains_entities(entities, num_entities, operation_type) ;
-}
-  
-//! subtract/intersect/unite meshset_2 from/with/into meshset_1; modifies meshset_1
-inline MBErrorCode
-MBMeshSet::subtract( const MBMeshSet *meshset_2,
-                     MBEntityHandle my_handle,
-                     AEntityFactory* adjacencies)
-{ 
-  return vector_based() ?
-    reinterpret_cast<MBMeshSet_Vector* >(this)->subtract( meshset_2, my_handle, adjacencies ) :
-    reinterpret_cast<MBMeshSet_MBRange*>(this)->subtract( meshset_2, my_handle, adjacencies ) ;
-}
 
-inline MBErrorCode
-MBMeshSet::intersect( const MBMeshSet *meshset_2,
-                      MBEntityHandle my_handle,
-                      AEntityFactory* adjacencies)
+//! get all parents pointed to by this meshset
+const MBEntityHandle* MBMeshSet::get_parents( int& count_out ) const
 { 
-  return vector_based() ?
-    reinterpret_cast<MBMeshSet_Vector* >(this)->intersect( meshset_2, my_handle, adjacencies ) :
-    reinterpret_cast<MBMeshSet_MBRange*>(this)->intersect( meshset_2, my_handle, adjacencies ) ;
-}
+  count_out = mParentCount;
+  if (count_out < MANY)
+    return parentMeshSets.hnd;
 
-inline MBErrorCode
-MBMeshSet::unite( const MBMeshSet *meshset_2,
-                  MBEntityHandle my_handle,
-                  AEntityFactory* adjacencies)
-{ 
-  return vector_based() ?
-    reinterpret_cast<MBMeshSet_Vector* >(this)->unite( meshset_2, my_handle, adjacencies ) :
-    reinterpret_cast<MBMeshSet_MBRange*>(this)->unite( meshset_2, my_handle, adjacencies ) ;
+  count_out = parentMeshSets.ptr[1] - parentMeshSets.ptr[0];
+  return parentMeshSets.ptr[0];
 }
 
-//! add these entities to this meshset
-inline MBErrorCode
-MBMeshSet::add_entities( const MBEntityHandle *entities,
-                         const int num_entities,
-                         MBEntityHandle my_handle,
-                         AEntityFactory* adjacencies)
-{ 
-  return vector_based() ?
-    reinterpret_cast<MBMeshSet_Vector* >(this)->add_entities( entities, num_entities, my_handle, adjacencies ) :
-    reinterpret_cast<MBMeshSet_MBRange*>(this)->add_entities( entities, num_entities, my_handle, adjacencies ) ;
+//! return the number of children pointed to by this meshset
+int MBMeshSet::num_children() const 
+{
+  if (mChildCount < MANY)
+    return mChildCount;
+  else
+    return childMeshSets.ptr[1] - childMeshSets.ptr[0];
 }
-  
-  //! add these entities to this meshset
-inline MBErrorCode
-MBMeshSet::add_entities( const MBRange &entities,
-                         MBEntityHandle my_handle,
-                         AEntityFactory* adjacencies)
-{ 
-  return vector_based() ?
-    reinterpret_cast<MBMeshSet_Vector* >(this)->add_entities( entities, my_handle, adjacencies ) :
-    reinterpret_cast<MBMeshSet_MBRange*>(this)->add_entities( entities, my_handle, adjacencies ) ;
-}
-  
-  //! add these entities to this meshset
-inline MBErrorCode
-MBMeshSet::remove_entities( const MBRange& entities,
-                            MBEntityHandle my_handle,
-                            AEntityFactory* adjacencies)
-{ 
-  return vector_based() ?
-    reinterpret_cast<MBMeshSet_Vector* >(this)->remove_entities( entities, my_handle, adjacencies ) :
-    reinterpret_cast<MBMeshSet_MBRange*>(this)->remove_entities( entities, my_handle, adjacencies ) ;
-}
- 
-  //! remove these entities from this meshset
-inline MBErrorCode
-MBMeshSet::remove_entities( const MBEntityHandle *entities,
-                            const int num_entities,
-                            MBEntityHandle my_handle,
-                            AEntityFactory* adjacencies)
-{ 
-  return vector_based() ?
-    reinterpret_cast<MBMeshSet_Vector* >(this)->remove_entities( entities, num_entities, my_handle, adjacencies ) :
-    reinterpret_cast<MBMeshSet_MBRange*>(this)->remove_entities( entities, num_entities, my_handle, adjacencies ) ;
-}
 
-  //! return the number of entities contained in this meshset
-inline unsigned int MBMeshSet::num_entities() const
-{ 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->num_entities() :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->num_entities() ;
+//! return the number of parents pointed to by this meshset
+int MBMeshSet::num_parents() const
+{
+  if (mParentCount < MANY)
+    return mParentCount;
+  else
+    return parentMeshSets.ptr[1] - parentMeshSets.ptr[0];
 }
   
-  //! return the number of entities with the given type contained in this meshset
-inline unsigned int
-MBMeshSet::num_entities_by_type(MBEntityType type) const
+inline MBErrorCode MBMeshSet::clear( MBEntityHandle myhandle, AEntityFactory* adjacencies )
 { 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->num_entities_by_type(type) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->num_entities_by_type(type) ;
+  if (tracking())
+    remove_adjacencies( myhandle, adjacencies );
+  if (mContentCount == MANY)
+    free( contentList.ptr[0] );
+  mContentCount = ZERO;
+  return MB_SUCCESS;
 }
   
-  //! return the number of entities with the given type contained in this meshset
-inline unsigned int
-MBMeshSet::num_entities_by_dimension(int dim) const
+inline MBErrorCode MBMeshSet::clear_all( MBEntityHandle myhandle, AEntityFactory* adjacencies )
 { 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->num_entities_by_dimension(dim) :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->num_entities_by_dimension(dim) ;
+  MBErrorCode rval = clear( myhandle, adjacencies );
+  if (mChildCount == MANY)
+    free( childMeshSets.ptr[0] );
+  mChildCount = ZERO;
+  if (mParentCount == MANY)
+    free( parentMeshSets.ptr[0] );
+  mParentCount = ZERO;
+  return rval;
 }
 
-inline unsigned long MBMeshSet::get_memory_use() const
-{ 
-  return vector_based() ?
-    reinterpret_cast<const MBMeshSet_Vector* >(this)->get_memory_use() :
-    reinterpret_cast<const MBMeshSet_MBRange*>(this)->get_memory_use() ;
+inline const MBEntityHandle* MBMeshSet::get_contents( size_t& count_out ) const
+{
+  if (mContentCount == MANY) {
+    count_out = contentList.ptr[1] - contentList.ptr[0];
+    return contentList.ptr[0];
+  }
+  else {
+    count_out = mContentCount;
+    return contentList.hnd;
+  }
 }
 
-inline MBErrorCode MBMeshSet_MBRange::get_entities(std::vector<MBEntityHandle>& entity_list) const
+inline MBEntityHandle* MBMeshSet::get_contents( size_t& count_out )
 {
-  size_t old_size = entity_list.size();
-  entity_list.resize(old_size + mRange.size());
-  std::copy( mRange.begin(), mRange.end(), entity_list.begin()+old_size );
-  return MB_SUCCESS;
+  if (mContentCount == MANY) {
+    count_out = contentList.ptr[1] - contentList.ptr[0];
+    return contentList.ptr[0];
+  }
+  else {
+    count_out = mContentCount;
+    return contentList.hnd;
+  }
 }
 
-inline MBErrorCode MBMeshSet_MBRange::get_entities(MBRange& entity_list) const
+inline MBErrorCode MBMeshSet::get_entities(std::vector<MBEntityHandle>& entities) const
 {
-  entity_list.merge( mRange );
+  size_t count;
+  const MBEntityHandle* ptr = get_contents( count );
+  if (vector_based()) {
+    size_t old_size = entities.size();
+    entities.resize( count+old_size );
+    std::copy( ptr, ptr+count, entities.begin()+old_size );
+  }
+  else {
+    assert(count%2 == 0);
+    for (size_t i = 0; i < count; i += 2) 
+      std::copy( hdl_iter(ptr[i]), hdl_iter(ptr[i+1]+1), std::back_inserter(entities) );
+  }
   return MB_SUCCESS;
-}
+} 
 
-inline MBErrorCode MBMeshSet_MBRange::get_entities_by_type(MBEntityType type,
-    std::vector<MBEntityHandle>& entity_list) const
+inline MBErrorCode MBMeshSet::get_entities(MBRange& entities) const
 {
-  std::pair<MBRange::const_iterator,MBRange::const_iterator> its;
-  its = mRange.equal_range( type );
-  std::copy( its.first, its.second, std::back_inserter( entity_list ) );
+  size_t count;
+  const MBEntityHandle* ptr = get_contents( count );
+  if (vector_based()) {
+    std::copy( ptr, ptr+count, mb_range_inserter(entities) );
+  }
+  else {
+    assert(count%2 == 0);
+    entities.clear();
+    MBRange::iterator in = entities.begin();
+    for (size_t i = 0; i < count; i += 2) 
+      in = entities.insert( in, ptr[i], ptr[i+1] );
+  }
   return MB_SUCCESS;
-}
+} 
 
-inline MBErrorCode MBMeshSet_MBRange::get_entities_by_type(MBEntityType type,
-    MBRange& entity_list) const
+
+  //! get all entities in this MeshSet with the specified type
+inline MBErrorCode MBMeshSet::get_entities_by_type(MBEntityType type,
+                                                   std::vector<MBEntityHandle> &entity_list
+                                                   ) const
 {
-  std::pair<MBRange::const_iterator,MBRange::const_iterator> its;
-  its = mRange.equal_range( type );
-  entity_list.merge( its.first, its.second );
-  return MB_SUCCESS;
-}
+  size_t count;
+  const MBEntityHandle* ptr = get_contents( count );
+  if (vector_based()) {
+    std::remove_copy_if( ptr, ptr+count, 
+                         std::back_inserter( entity_list ),
+                         not_type_test(type) );
+  }
+  else {
+    size_t idx = std::lower_bound( ptr, ptr+count, FIRST_HANDLE(type) ) - ptr;
+    if (idx < count && TYPE_FROM_HANDLE(ptr[idx]) == type) {
+      if (idx % 2) { // only part of first block is of type
+        std::copy( hdl_iter(FIRST_HANDLE(type)), hdl_iter(ptr[idx]+1), std::back_inserter( entity_list ) );
+        ++idx;
+      }
+      for (; idx < count; idx += 2) {
+        if (TYPE_FROM_HANDLE(ptr[idx+1]) == type) // whole block is of type
+          std::copy( hdl_iter(ptr[idx]), hdl_iter(ptr[idx+1]+1), std::back_inserter( entity_list ) );
+        else {
+          if (TYPE_FROM_HANDLE(ptr[idx]) == type) // part of last block is of type
+            std::copy( hdl_iter(ptr[idx]), hdl_iter(LAST_HANDLE(type)), std::back_inserter( entity_list ) );
+          break;
+        }
+      }
+    }
+  }
 
-inline MBErrorCode MBMeshSet_MBRange::get_entities_by_dimension(int dim,
-    std::vector<MBEntityHandle>& entity_list) const
-{
-  MBRange::const_iterator beg = mRange.lower_bound(MBCN::TypeDimensionMap[dim].first);
-  MBRange::const_iterator end = mRange.lower_bound(MBCN::TypeDimensionMap[dim+1].first);
-  std::copy( beg, end, std::back_inserter( entity_list ) );
   return MB_SUCCESS;
 }
 
-inline MBErrorCode MBMeshSet_MBRange::get_entities_by_dimension(int dim,
-    MBRange& entity_list) const
+
+inline MBErrorCode MBMeshSet::get_entities_by_type( MBEntityType type,
+                                                    MBRange& entity_list) const
 {
-  MBRange::const_iterator beg = mRange.lower_bound(MBCN::TypeDimensionMap[dim].first);
-  MBRange::const_iterator end = mRange.lower_bound(MBCN::TypeDimensionMap[dim+1].first);
-  entity_list.merge( beg, end );
-  return MB_SUCCESS;
-}
+  size_t count;
+  const MBEntityHandle* ptr = get_contents( count );
+  if (vector_based()) {
+    std::remove_copy_if( ptr, ptr+count, 
+                         mb_range_inserter( entity_list ),
+                         not_type_test(type) );
+  }
+  else {
+    size_t idx = std::lower_bound( ptr, ptr+count, FIRST_HANDLE(type) ) - ptr;
+    MBRange::iterator in = entity_list.begin();
+    if (idx < count && TYPE_FROM_HANDLE(ptr[idx]) == type) {
+      if (idx % 2) { // only part of first block is of type
+        in = entity_list.insert( in, FIRST_HANDLE(type), ptr[idx] );
+        ++idx;
+      }
+      for (; idx < count; idx += 2) {
+        if (TYPE_FROM_HANDLE(ptr[idx+1]) == type) // whole block is of type
+          in = entity_list.insert( in, ptr[idx], ptr[idx+1] );
+        else {
+          if (TYPE_FROM_HANDLE(ptr[idx]) == type) // part of last block is of type
+            entity_list.insert( in, ptr[idx], LAST_HANDLE(type) );
+          break;
+        }
+      }
+    }
+  }
 
-inline MBErrorCode MBMeshSet_MBRange::get_non_set_entities( MBRange& range ) const
-{
-  range.merge( mRange.begin(), mRange.lower_bound( MBENTITYSET ) );
   return MB_SUCCESS;
 }
 
-inline bool MBMeshSet_MBRange::contains_entities(MBEntityHandle *entities,
-                                                 int num_entities,
-                                                 const int op_type) const
+  //! return the number of entities with the given type contained in this meshset
+inline unsigned int MBMeshSet::num_entities_by_type(MBEntityType type) const
 {
-  unsigned int num_in = 0;
-  for (int i = 0; i < num_entities; i++) {
-    if (mRange.find(entities[i]) != mRange.end()) num_in++;
-    else if (MBInterface::INTERSECT == op_type) break;
+  unsigned int result;
+  size_t count;
+  const MBEntityHandle* ptr = get_contents( count );
+  if (vector_based()) {
+    #ifndef __SUNPRO_CC
+      result = std::count_if( ptr, ptr+count, type_test(type) );
+    #else
+      std::count_if( ptr, ptr+count, type_test(type), result );
+    #endif
   }
+  else {
+    result = 0;
+    size_t idx = std::lower_bound( ptr, ptr+count, FIRST_HANDLE(type) ) - ptr;
+    if (idx < count && TYPE_FROM_HANDLE(ptr[idx]) == type) {
+      if (idx % 2) { // only part of first block is of type
+        result += ptr[idx] - FIRST_HANDLE(type) + 1;
+        ++idx;
+      }
+      for (; idx < count; idx += 2) {
+        if (TYPE_FROM_HANDLE(ptr[idx+1]) == type) // whole block is of type
+          result += ptr[idx+1] - ptr[idx] + 1;
+        else {
+          if (TYPE_FROM_HANDLE(ptr[idx]) == type) // part of last block is of type
+            result += LAST_HANDLE(type) - ptr[idx] + 1;
+          break;
+        }
+      }
+    }
+  }
 
-  return ((MBInterface::INTERSECT == op_type && num_in == (unsigned int) num_entities) ||
-          MBInterface::UNION == op_type && 0 < num_in);
+  return result;
 }
 
-inline unsigned int MBMeshSet_MBRange::num_entities() const
+inline MBErrorCode MBMeshSet::get_entities_by_dimension( int dimension,
+                                                         std::vector<MBEntityHandle> &entity_list
+                                                         ) const
 {
-  return mRange.size();
-}
+  size_t count;
+  const MBEntityHandle* ptr = get_contents( count );
+  if (vector_based()) {
+    std::remove_copy_if( ptr, ptr+count, 
+                         std::back_inserter( entity_list ),
+                         not_dim_test(dimension) );
+  }
+  else {
+    size_t idx = std::lower_bound( ptr, ptr+count, FIRST_OF_DIM(dimension) ) - ptr;
+    if (idx < count && DIM_FROM_HANDLE(ptr[idx]) == dimension) {
+      if (idx % 2) { // only part of first block is of type
+        std::copy( hdl_iter(FIRST_OF_DIM(dimension)), hdl_iter(ptr[idx]+1), std::back_inserter( entity_list ) );
+        ++idx;
+      }
+      for (; idx < count; idx += 2) {
+        if (DIM_FROM_HANDLE(ptr[idx+1]) == dimension) // whole block is of type
+          std::copy( hdl_iter(ptr[idx]), hdl_iter(ptr[idx+1]+1), std::back_inserter( entity_list ) );
+        else {
+          if (DIM_FROM_HANDLE(ptr[idx]) == dimension) // part of last block is of type
+            std::copy( hdl_iter(ptr[idx]), hdl_iter(LAST_OF_DIM(dimension)), std::back_inserter( entity_list ) );
+          break;
+        }
+      }
+    }
+  }
 
-inline unsigned int MBMeshSet_MBRange::num_entities_by_type(MBEntityType type) const
-{
-  return mRange.num_of_type( type );
+  return MB_SUCCESS;
 }
 
-inline unsigned int MBMeshSet_MBRange::num_entities_by_dimension(int dimension) const
+
+inline MBErrorCode MBMeshSet::get_entities_by_dimension( int dimension,
+                                                         MBRange& entity_list) const
 {
-  return mRange.num_of_dimension( dimension );
-}
+  size_t count;
+  const MBEntityHandle* ptr = get_contents( count );
+  if (vector_based()) {
+    std::remove_copy_if( ptr, ptr+count, 
+                         mb_range_inserter( entity_list ),
+                         not_dim_test(dimension) );
+  }
+  else {
+    size_t idx = std::lower_bound( ptr, ptr+count, FIRST_OF_DIM(dimension) ) - ptr;
+    MBRange::iterator in = entity_list.begin();
+    if (idx < count && DIM_FROM_HANDLE(ptr[idx]) == dimension) {
+      if (idx % 2) { // only part of first block is of type
+        in = entity_list.insert( in, FIRST_OF_DIM(dimension), ptr[idx] );
+        ++idx;
+      }
+      for (; idx < count; idx += 2) {
+        if (DIM_FROM_HANDLE(ptr[idx+1]) == dimension) // whole block is of type
+          in = entity_list.insert( in, ptr[idx], ptr[idx+1] );
+        else {
+          if (DIM_FROM_HANDLE(ptr[idx]) == dimension) // part of last block is of type
+            entity_list.insert( in, ptr[idx], LAST_OF_DIM(dimension) );
+          break;
+        }
+      }
+    }
+  }
 
-inline MBErrorCode MBMeshSet_Vector::get_entities(std::vector<MBEntityHandle>& entity_list) const
-{
-  size_t old_size = entity_list.size();
-  entity_list.resize( mVector.size() + old_size );
-  std::copy( mVector.begin(), mVector.end(), entity_list.begin()+old_size );
   return MB_SUCCESS;
 }
 
-inline MBErrorCode MBMeshSet_Vector::get_entities(MBRange& entity_list) const
+  //! return the number of entities with the given type contained in this meshset
+inline unsigned int MBMeshSet::num_entities_by_dimension(int dimension) const
 {
-  std::vector<MBEntityHandle> tmp_vect( mVector );
-  vector_to_range( tmp_vect, entity_list );
-  return MB_SUCCESS;
+  unsigned int result;
+  size_t count;
+  const MBEntityHandle* ptr = get_contents( count );
+  if (vector_based()) {
+    #ifndef __SUNPRO_CC
+      result = std::count_if( ptr, ptr+count, dim_test(dimension) );
+    #else
+      std::count_if( ptr, ptr+count, dim_test(dimension), result );
+    #endif
+  }
+  else {
+    result = 0;
+    size_t idx = std::lower_bound( ptr, ptr+count, FIRST_OF_DIM(dimension) ) - ptr;
+    if (idx < count && DIM_FROM_HANDLE(ptr[idx]) == dimension) {
+      if (idx % 2) { // only part of first block is of type
+        result += ptr[idx] - FIRST_OF_DIM(dimension) + 1;
+        ++idx;
+      }
+      for (; idx < count; idx += 2) {
+        if (DIM_FROM_HANDLE(ptr[idx+1]) == dimension) // whole block is of type
+          result += ptr[idx+1] - ptr[idx] + 1;
+        else {
+          if (DIM_FROM_HANDLE(ptr[idx]) == dimension) // part of last block is of type
+            result += LAST_OF_DIM(dimension) - ptr[idx] + 1;
+          break;
+        }
+      }
+    }
+  }
+
+  return result;
 }
 
-inline MBErrorCode MBMeshSet_Vector::get_entities_by_type(MBEntityType type,
-    std::vector<MBEntityHandle>& entity_list) const
+inline MBErrorCode MBMeshSet::get_non_set_entities( MBRange& range ) const
 {
-  std::remove_copy_if( mVector.begin(), mVector.end(), 
-                       std::back_inserter( entity_list ),
-                       not_type_test(type) );
+  size_t count;
+  const MBEntityHandle* ptr = get_contents( count );
+  if (vector_based()) {
+    std::remove_copy_if( ptr, ptr+count, 
+                         mb_range_inserter( range ),
+                         type_test(MBENTITYSET) );
+  }
+  else {
+    MBRange::iterator in = range.begin();
+    for (size_t idx = 0; idx < count; idx += 2) {
+      if (TYPE_FROM_HANDLE(ptr[idx+1]) != MBENTITYSET)
+        in = range.insert( ptr[idx], ptr[idx+1] );
+      else {
+        if (TYPE_FROM_HANDLE(ptr[idx]) != MBENTITYSET)
+          range.insert( ptr[idx], LAST_HANDLE( MBENTITYSET - 1 ) );
+        break;
+      }
+    }
+  }
+
   return MB_SUCCESS;
 }
 
-inline MBErrorCode MBMeshSet_Vector::get_entities_by_type(MBEntityType type,
-    MBRange& entity_list) const
+inline bool MBMeshSet::contains_entities(const MBEntityHandle *entities, 
+                                         int num_entities,
+                                         const int op) const
 {
-  std::vector<MBEntityHandle> tmp_vect;
-  get_entities_by_type( type, tmp_vect );
-  vector_to_range( tmp_vect, entity_list );
-  return MB_SUCCESS;
+  size_t count;
+  const MBEntityHandle* const ptr = get_contents( count );
+  const MBEntityHandle* const end = ptr + count;
+  size_t found_count = 0;
+  if (vector_based()) {
+    for (int i = 0; i < num_entities; ++i)
+      if (std::find( ptr, end, entities[i] ) < end)
+        ++found_count; 
+  }
+  else {
+    assert(0 == count % 2);
+    for (int i = 0; i < num_entities; ++i) {
+      const unsigned long idx = std::lower_bound( ptr, end, entities[i] ) - ptr;
+      if (idx < count && (idx%2 != 0 || ptr[idx] == entities[i]))
+        ++found_count;
+    }
+  }
+
+  return found_count >= ((MBInterface::INTERSECT == op) ? (unsigned)num_entities : 1u);
 }
 
-inline MBErrorCode MBMeshSet_Vector::get_entities_by_dimension( int dimension, 
-    std::vector<MBEntityHandle>& entity_list) const
+
+
+//! subtract/intersect/unite meshset_2 from/with/into meshset_1; modifies meshset_1
+inline MBErrorCode MBMeshSet::subtract(const MBMeshSet *meshset_2,
+                                       MBEntityHandle my_handle,
+                                       AEntityFactory* adjacencies)
 {
-  std::remove_copy_if( mVector.begin(), mVector.end(), 
-                       std::back_inserter( entity_list ),
-                       not_dim_test(dimension) );
-  return MB_SUCCESS;
+  size_t count;
+  const MBEntityHandle* const ptr = meshset_2->get_contents( count );
+  if (meshset_2->vector_based()) 
+    return remove_entity_vector( ptr, count, my_handle, adjacencies );
+  else
+    return remove_entity_ranges( ptr, count, my_handle, adjacencies );
 }
 
-inline MBErrorCode MBMeshSet_Vector::get_entities_by_dimension( int dimension, 
-    MBRange& entity_list) const
+inline MBErrorCode MBMeshSet::unite(const MBMeshSet *meshset_2,
+                                    MBEntityHandle my_handle,
+                                    AEntityFactory* adjacencies)
 {
-  std::vector<MBEntityHandle> tmp_vect;
-  get_entities_by_dimension( dimension, tmp_vect );
-  vector_to_range( tmp_vect, entity_list );
-  return MB_SUCCESS;
+  size_t count;
+  const MBEntityHandle* const ptr = meshset_2->get_contents( count );
+  if (meshset_2->vector_based()) 
+    return insert_entity_vector( ptr, count, my_handle, adjacencies );
+  else
+    return insert_entity_ranges( ptr, count, my_handle, adjacencies );
 }
 
-inline MBErrorCode MBMeshSet_Vector::get_non_set_entities( MBRange& entities ) const
+//! add these entities to this meshset
+inline MBErrorCode MBMeshSet::add_entities(const MBEntityHandle *entity_handles,
+                                           const int num_entities,
+                                           MBEntityHandle my_handle,
+                                           AEntityFactory* adjacencies)
 {
-  std::vector<MBEntityHandle> tmp_vect;
-  std::remove_copy_if( mVector.begin(), mVector.end(), 
-                       std::back_inserter( tmp_vect ),
-                       type_test(MBENTITYSET) );
-  vector_to_range( tmp_vect, entities );
-  return MB_SUCCESS;
+  return insert_entity_vector( entity_handles, num_entities, my_handle, adjacencies );
 }
 
-inline bool MBMeshSet_Vector::contains_entities(MBEntityHandle *entities,
-                                                int num_entities,
-                                                const int op_type) const
+  //! add these entities to this meshset
+inline MBErrorCode MBMeshSet::add_entities(const MBRange &entities,
+                                           MBEntityHandle my_handle,
+                                           AEntityFactory* adjacencies)
 {
-  unsigned int num_in = 0;
-  for (int i = 0; i < num_entities; i++) {
-    if (std::find(mVector.begin(), mVector.end(), entities[i]) != 
-        mVector.end()) num_in++;
-    else if (MBInterface::INTERSECT == op_type) break;
-  }
-
-  return ((MBInterface::INTERSECT == op_type && 
-           num_in == (unsigned int) num_entities) ||
-          MBInterface::UNION == op_type && 0 < num_in);
+  return insert_entity_ranges( entities, my_handle, adjacencies );
 }
 
-inline unsigned int MBMeshSet_Vector::num_entities() const
+  //! add these entities to this meshset
+inline MBErrorCode MBMeshSet::remove_entities(const MBRange& entities,
+                                              MBEntityHandle my_handle,
+                                              AEntityFactory* adjacencies)
 {
-  return mVector.size();
+  return remove_entity_ranges(  entities, my_handle, adjacencies );
 }
 
-inline unsigned int MBMeshSet_Vector::num_entities_by_type(MBEntityType type) const
+
+  //! remove these entities from this meshset
+inline MBErrorCode MBMeshSet::remove_entities(const MBEntityHandle *entities,
+                                              const int num_entities,
+                                              MBEntityHandle my_handle,
+                                              AEntityFactory* adjacencies)
 {
-#ifndef __SUNPRO_CC
-  return std::count_if( mVector.begin(), mVector.end(), type_test(type) );
-#else
-  unsigned int result = 0;
-  std::count_if( mVector.begin(), mVector.end(), type_test(type), result );
-  return result;
-#endif
+  return remove_entity_vector( entities, num_entities, my_handle, adjacencies );
 }
 
-inline unsigned int MBMeshSet_Vector::num_entities_by_dimension( int dim ) const
+  //! return the number of entities contained in this meshset
+unsigned int MBMeshSet::num_entities() const
 {
-#ifndef __SUNPRO_CC
-  return std::count_if( mVector.begin(), mVector.end(), dim_test(dim) );
-#else
-  unsigned int result = 0;
-  std::count_if( mVector.begin(), mVector.end(), dim_test(dim), result );
+  size_t count;
+  const MBEntityHandle* list = get_contents( count );
+  if (vector_based())
+    return count;
+  
+  int result = 0;
+  const MBEntityHandle *const end = list + count;
+  for (; list < end; list += 2)
+    result += list[1] - list[0] + 1;
   return result;
-#endif
 }
 
-
-
 #endif

Modified: MOAB/trunk/Makefile.am
===================================================================
--- MOAB/trunk/Makefile.am	2008-03-31 20:29:26 UTC (rev 1730)
+++ MOAB/trunk/Makefile.am	2008-04-01 15:49:58 UTC (rev 1731)
@@ -31,7 +31,8 @@
 	file_options_test \
         kd_tree_test \
         var_len_test var_len_test_no_template \
-	tag_test
+	tag_test \
+	mesh_set_test
 #                 merge_test \         # input files no longer exist?
 #                 test_tag_server \    # fails
 
@@ -290,8 +291,10 @@
 
 seq_man_test_SOURCES = TestUtil.hpp TestTypeSequenceManager.cpp 
 seq_man_test_LDADD = $(top_builddir)/libMOAB.la
-seq_man_test_CXXFLAGS = -DTEST $(CXXFLAGS)
 
+mesh_set_test_SOURCES = Test_MBMeshSet.cpp TestUtil.hpp
+mesh_set_test_LDADD = $(top_builddir)/libMOAB.la
+
 geom_util_test_SOURCES = TestUtil.hpp GeomUtilTests.cpp 
 geom_util_test_LDADD = $(top_builddir)/libMOAB.la
 geom_util_test_DEPENDENCIES = $(geom_util_test_LDADD)

Modified: MOAB/trunk/MeshSetSequence.hpp
===================================================================
--- MOAB/trunk/MeshSetSequence.hpp	2008-03-31 20:29:26 UTC (rev 1730)
+++ MOAB/trunk/MeshSetSequence.hpp	2008-04-01 15:49:58 UTC (rev 1731)
@@ -106,10 +106,7 @@
                             SequenceManager* set_sequences,
                             std::vector<MBMeshSet*>& sets_out );
   
-  enum {
-    SET_SIZE = (sizeof(MBMeshSet_MBRange) > sizeof(MBMeshSet_Vector)) ?
-                sizeof(MBMeshSet_MBRange) : sizeof(MBMeshSet_Vector)
-  };
+  enum { SET_SIZE = sizeof(MBMeshSet) };
 
   inline const unsigned char* array() const
     { return reinterpret_cast<const unsigned char*>(data()->get_sequence_data(0)); }
@@ -119,21 +116,14 @@
     
   inline void allocate_set( unsigned flags, MBEntityID index )
   {
-    const bool tracking = (0 != (flags&MESHSET_TRACK_OWNER));
     unsigned char* const ptr = array() + index * SET_SIZE;
-    if (flags & MESHSET_ORDERED)
-      new (ptr) MBMeshSet_Vector(tracking);
-    else
-      new (ptr) MBMeshSet_MBRange(tracking);
+    new (ptr) MBMeshSet(flags);
   }
     
   inline void deallocate_set( MBEntityID index ) 
   {
     MBMeshSet* set = reinterpret_cast<MBMeshSet*>(array() + SET_SIZE * index );
-    if (set->vector_based())
-      reinterpret_cast<MBMeshSet_Vector*>(set)->~MBMeshSet_Vector();
-    else
-      reinterpret_cast<MBMeshSet_MBRange*>(set)->~MBMeshSet_MBRange();
+    set->~MBMeshSet();
   }
 };
 

Added: MOAB/trunk/Test_MBMeshSet.cpp
===================================================================
--- MOAB/trunk/Test_MBMeshSet.cpp	                        (rev 0)
+++ MOAB/trunk/Test_MBMeshSet.cpp	2008-04-01 15:49:58 UTC (rev 1731)
@@ -0,0 +1,1099 @@
+#include "MBMeshSet.hpp"
+#include "AEntityFactory.hpp"
+#include "TestUtil.hpp"
+#include "MBCore.hpp"
+
+#include <iostream>
+
+//! test add_entities, get_entities, num_entities
+void test_add_entities( unsigned flags );
+//! test remove_entities, get_entities, num_entities
+void test_remove_entities( unsigned flags );
+//! test get_entities_by_type, num_entities_by_type
+void test_entities_by_type( unsigned flags );
+//! test get_entities_by_dimension, num_entities_by_dimension
+void test_entities_by_dimension( unsigned flags );
+//! test subtract_meshset
+void test_subtract( unsigned flags1, unsigned flags2 );
+//! test intersect_meshset
+void test_intersect( unsigned flags1, unsigned flags2 );
+//! test unite_meshset
+void test_unite( unsigned flags1, unsigned flags2 );
+//! test MBMeshSet::contains_entities
+void test_contains_entities( unsigned flags );
+//! test clear_meshset
+void test_clear( unsigned flags );
+
+//! Create 10x10x10 hex mesh
+void make_mesh( MBInterface& iface );
+//! Create 10x10x10 hex mesh, return ranges of handles
+void make_mesh( MBInterface& iface, MBEntityHandle& vstart, MBEntityHandle& vend, MBEntityHandle& hstart, MBEntityHandle& hend );
+//! Print std::vector<MBEntityHandle>
+void print_handle_vect( const char* prefix, const std::vector<MBEntityHandle>& vect );
+//! Print MBRange
+void print_mbrange( const char* prefix, const MBRange& range );
+//! Compare set contents against passed vector, and if MESHSET_TRACK_OWNER then check adjacencies
+bool check_set_contents( MBCore& mb, MBEntityHandle set, const std::vector<MBEntityHandle>& expected );
+//! Compare result of get_entities_by_type to result of get_entities_by_handle
+bool check_set_contents( MBCore& mb, MBEntityType type, MBEntityHandle set, unsigned flags );
+//! Compare result of get_entities_by_dimension to result of get_entities_by_handle
+bool check_set_contents( MBCore& mb, int dim, MBEntityHandle set, unsigned flags );
+//! For each entry in range, if one or more occurances in vect, remove last occurance from vect.
+void remove_from_back( std::vector<MBEntityHandle>& vect, const MBRange& range );
+enum BoolOp { UNITE, INTERSECT, SUBTRACT };
+//! Perform boolean op on two entity sets and verify result
+bool test_boolean( MBCore& mb, BoolOp op, 
+                   unsigned flags1, const MBRange& set1_ents, 
+                   unsigned flags2, const MBRange& set2_ents );
+
+void test_add_entities_ordered()          { test_add_entities( MESHSET_ORDERED ); }
+void test_add_entities_set()              { test_add_entities( MESHSET_SET     ); }
+void test_add_entities_ordered_tracking() { test_add_entities( MESHSET_TRACK_OWNER|MESHSET_ORDERED ); }
+void test_add_entities_set_tracking()     { test_add_entities( MESHSET_TRACK_OWNER|MESHSET_SET     ); }
+
+void test_remove_entities_ordered()          { test_remove_entities( MESHSET_ORDERED ); }
+void test_remove_entities_set()              { test_remove_entities( MESHSET_SET     ); }
+void test_remove_entities_ordered_tracking() { test_remove_entities( MESHSET_TRACK_OWNER|MESHSET_ORDERED ); }
+void test_remove_entities_set_tracking()     { test_remove_entities( MESHSET_TRACK_OWNER|MESHSET_SET     ); }
+
+void test_entities_by_type_ordered()  { test_entities_by_type     ( MESHSET_ORDERED ); }
+void test_entities_by_type_set()      { test_entities_by_type     ( MESHSET_SET     ); }
+void test_entities_by_dim_ordered()   { test_entities_by_dimension( MESHSET_ORDERED ); }
+void test_entities_by_dim_set()       { test_entities_by_dimension( MESHSET_SET     ); }
+
+void test_subtract_set_set()                  { test_subtract( MESHSET_SET    , MESHSET_SET     ); }
+void test_subtract_set_ordered()              { test_subtract( MESHSET_SET    , MESHSET_ORDERED ); }
+void test_subtract_ordered_set()              { test_subtract( MESHSET_ORDERED, MESHSET_SET     ); }
+void test_subtract_ordered_ordered()          { test_subtract( MESHSET_ORDERED, MESHSET_ORDERED ); }
+void test_subtract_set_set_tracking()         { test_subtract( MESHSET_TRACK_OWNER|MESHSET_SET    , MESHSET_TRACK_OWNER|MESHSET_SET     ); }
+void test_subtract_set_ordered_tracking()     { test_subtract( MESHSET_TRACK_OWNER|MESHSET_SET    , MESHSET_TRACK_OWNER|MESHSET_ORDERED ); }
+void test_subtract_ordered_set_tracking()     { test_subtract( MESHSET_TRACK_OWNER|MESHSET_ORDERED, MESHSET_TRACK_OWNER|MESHSET_SET     ); }
+void test_subtract_ordered_ordered_tracking() { test_subtract( MESHSET_TRACK_OWNER|MESHSET_ORDERED, MESHSET_TRACK_OWNER|MESHSET_ORDERED ); }
+
+void test_itersect_set_set()                  { test_intersect( MESHSET_SET    , MESHSET_SET     ); }
+void test_itersect_set_ordered()              { test_intersect( MESHSET_SET    , MESHSET_ORDERED ); }
+void test_itersect_ordered_set()              { test_intersect( MESHSET_ORDERED, MESHSET_SET     ); }
+void test_itersect_ordered_ordered()          { test_intersect( MESHSET_ORDERED, MESHSET_ORDERED ); }
+void test_itersect_set_set_tracking()         { test_intersect( MESHSET_TRACK_OWNER|MESHSET_SET    , MESHSET_TRACK_OWNER|MESHSET_SET     ); }
+void test_itersect_set_ordered_tracking()     { test_intersect( MESHSET_TRACK_OWNER|MESHSET_SET    , MESHSET_TRACK_OWNER|MESHSET_ORDERED ); }
+void test_itersect_ordered_set_tracking()     { test_intersect( MESHSET_TRACK_OWNER|MESHSET_ORDERED, MESHSET_TRACK_OWNER|MESHSET_SET     ); }
+void test_itersect_ordered_ordered_tracking() { test_intersect( MESHSET_TRACK_OWNER|MESHSET_ORDERED, MESHSET_TRACK_OWNER|MESHSET_ORDERED ); }
+
+void test_unite_set_set()                  { test_unite( MESHSET_SET    , MESHSET_SET     ); }
+void test_unite_set_ordered()              { test_unite( MESHSET_SET    , MESHSET_ORDERED ); }
+void test_unite_ordered_set()              { test_unite( MESHSET_ORDERED, MESHSET_SET     ); }
+void test_unite_ordered_ordered()          { test_unite( MESHSET_ORDERED, MESHSET_ORDERED ); }
+void test_unite_set_set_tracking()         { test_unite( MESHSET_TRACK_OWNER|MESHSET_SET    , MESHSET_TRACK_OWNER|MESHSET_SET     ); }
+void test_unite_set_ordered_tracking()     { test_unite( MESHSET_TRACK_OWNER|MESHSET_SET    , MESHSET_TRACK_OWNER|MESHSET_ORDERED ); }
+void test_unite_ordered_set_tracking()     { test_unite( MESHSET_TRACK_OWNER|MESHSET_ORDERED, MESHSET_TRACK_OWNER|MESHSET_SET     ); }
+void test_unite_ordered_ordered_tracking() { test_unite( MESHSET_TRACK_OWNER|MESHSET_ORDERED, MESHSET_TRACK_OWNER|MESHSET_ORDERED ); }
+
+void test_contains_entities_ordered() { test_contains_entities( MESHSET_ORDERED ); }
+void test_contains_entities_set()     { test_contains_entities( MESHSET_SET    ); }
+
+void test_clear_ordered()             { test_clear(                     MESHSET_ORDERED ); }
+void test_clear_set()                 { test_clear(                     MESHSET_SET     ); }
+void test_clear_ordered_tracking()    { test_clear( MESHSET_TRACK_OWNER|MESHSET_ORDERED ); }
+void test_clear_set_tracking()        { test_clear( MESHSET_TRACK_OWNER|MESHSET_SET     ); }
+
+int main()
+{
+  int err = 0;
+  
+  err += RUN_TEST(test_add_entities_ordered);
+  err += RUN_TEST(test_add_entities_set);
+  err += RUN_TEST(test_add_entities_ordered_tracking);
+  err += RUN_TEST(test_add_entities_set_tracking);
+
+  err += RUN_TEST(test_remove_entities_ordered);
+  err += RUN_TEST(test_remove_entities_set);
+  err += RUN_TEST(test_remove_entities_ordered_tracking);
+  err += RUN_TEST(test_remove_entities_set_tracking);
+
+  err += RUN_TEST(test_entities_by_type_ordered);
+  err += RUN_TEST(test_entities_by_type_set);
+  err += RUN_TEST(test_entities_by_dim_ordered);
+  err += RUN_TEST(test_entities_by_dim_set);
+
+  err += RUN_TEST(test_subtract_set_set);
+  err += RUN_TEST(test_subtract_set_ordered);
+  err += RUN_TEST(test_subtract_ordered_set);
+  err += RUN_TEST(test_subtract_ordered_ordered);
+  err += RUN_TEST(test_subtract_set_set_tracking);
+  err += RUN_TEST(test_subtract_set_ordered_tracking);
+  err += RUN_TEST(test_subtract_ordered_set_tracking);
+  err += RUN_TEST(test_subtract_ordered_ordered_tracking);
+
+  err += RUN_TEST(test_itersect_set_set);
+  err += RUN_TEST(test_itersect_set_ordered);
+  err += RUN_TEST(test_itersect_ordered_set);
+  err += RUN_TEST(test_itersect_ordered_ordered);
+  err += RUN_TEST(test_itersect_set_set_tracking);
+  err += RUN_TEST(test_itersect_set_ordered_tracking);
+  err += RUN_TEST(test_itersect_ordered_set_tracking);
+  err += RUN_TEST(test_itersect_ordered_ordered_tracking);
+
+  err += RUN_TEST(test_unite_set_set);
+  err += RUN_TEST(test_unite_set_ordered);
+  err += RUN_TEST(test_unite_ordered_set);
+  err += RUN_TEST(test_unite_ordered_ordered);
+  err += RUN_TEST(test_unite_set_set_tracking);
+  err += RUN_TEST(test_unite_set_ordered_tracking);
+  err += RUN_TEST(test_unite_ordered_set_tracking);
+  err += RUN_TEST(test_unite_ordered_ordered_tracking);
+
+  err += RUN_TEST(test_contains_entities_ordered);
+  err += RUN_TEST(test_contains_entities_set);
+  
+  err += RUN_TEST(test_clear_ordered);
+  err += RUN_TEST(test_clear_set);
+  err += RUN_TEST(test_clear_ordered_tracking);
+  err += RUN_TEST(test_clear_set_tracking);
+  
+  if (!err) 
+    printf("ALL TESTS PASSED\n");
+  else
+    printf("%d TESTS FAILED\n",err);
+  
+  return err;
+}
+
+// Create 100x100x100 hex mesh
+void make_mesh( MBInterface& iface )
+{
+  const int dim = 10;
+
+    // create vertices
+  MBEntityHandle prev_handle = 0;
+  for (int z = 0; z <= dim; ++z) {
+    for (int y = 0; y <= dim; ++y) {
+      for (int x = 0; x <= dim; ++x) {
+        const double coords[] = {x, y, z};
+        MBEntityHandle new_handle = 0;
+        MBErrorCode rval = iface.create_vertex( coords, new_handle );
+        CHECK_ERR(rval);
+        CHECK_EQUAL( ++prev_handle, new_handle );
+      }
+    }
+  }
+  
+    // create hexes
+  const int dim1 = dim + 1;
+  const int dimq = dim1 * dim1;
+  prev_handle = FIRST_HANDLE(MBHEX);
+  for (int z = 0; z < dim; ++z) {
+    for (int y = 0; y < dim; ++y) {
+      for (int x = 0; x < dim; ++x) {
+        const MBEntityHandle off = 1 + x + dim1*y + dimq*z;
+        const MBEntityHandle conn[] = { off,      off+1,      off+1+dim1,      off+dim1,
+                                        off+dimq, off+1+dimq, off+1+dim1+dimq, off+dim1+dimq };
+        MBEntityHandle new_handle = 0;
+        MBErrorCode rval = iface.create_element( MBHEX, conn, 8, new_handle );
+        CHECK_ERR(rval);
+        CHECK_EQUAL( prev_handle++, new_handle );
+      }
+    }
+  }
+  
+}
+
+void make_mesh( MBInterface& mb, MBEntityHandle& first_vert, MBEntityHandle& last_vert, MBEntityHandle& first_hex, MBEntityHandle& last_hex )
+{
+  make_mesh( mb );
+  
+    // Get handle ranges, and validate assumption that handles
+    // are contiguous.
+  MBRange range;
+  MBErrorCode rval = mb.get_entities_by_type( 0, MBVERTEX, range );
+  CHECK_ERR(rval);
+  first_vert = range.front();
+  last_vert = range.back();
+  CHECK_EQUAL( 1331ul, last_vert - first_vert + 1 );
+  range.clear();
+  rval = mb.get_entities_by_type( 0, MBHEX, range );
+  CHECK_ERR(rval);
+  first_hex = range.front();
+  last_hex = range.back();
+  CHECK_EQUAL( 1000ul, last_hex - first_hex + 1 );
+}
+
+
+template <typename iter_type>
+void print_handles( std::ostream& str, const char* prefix, iter_type begin, iter_type end )
+{
+  if (prefix)
+    str << prefix << ':';
+  if (begin == end) {
+    str << " (empty)" << std::endl;
+    return;
+  }
+  
+  iter_type i = begin;
+  MBEntityType prev_type = TYPE_FROM_HANDLE(*i);
+  MBEntityHandle prev_ent = *i;
+  str << ' ' << MBCN::EntityTypeName(prev_type) << ' ' << ID_FROM_HANDLE(*i);
+  for (;;) {
+    iter_type j = i;
+    for (++j, ++prev_ent; j != end && *j == prev_ent; ++j, ++prev_ent);
+    --prev_ent;
+    if (prev_ent - *i > 1) 
+      str << "-" << ID_FROM_HANDLE(prev_ent);
+    else if (prev_ent - *i == 1)
+      str << ", " << ID_FROM_HANDLE(prev_ent);
+    
+    i = j;
+    if (i == end)
+      break;
+    
+    str << ',';
+    if (TYPE_FROM_HANDLE(*i) != prev_type) 
+      str << ' ' << MBCN::EntityTypeName(prev_type = TYPE_FROM_HANDLE(*i));
+    str << ' ' << ID_FROM_HANDLE(*i);
+    prev_ent = *i;
+  }
+  str << std::endl;
+}
+
+void print_handle_vect( const char* prefix, const std::vector<MBEntityHandle>& vect )
+{
+  print_handles(std::cout, prefix, vect.begin(), vect.end());
+}
+
+void print_mbrange( const char* prefix, const MBRange& range )
+{
+  print_handles(std::cout, prefix, range.begin(), range.end());
+}
+
+bool compare_set_contents( unsigned flags, 
+                           const std::vector<MBEntityHandle>& expected,
+                           int set_count,
+                           std::vector<MBEntityHandle>& vect,
+                           const MBRange& range )
+{
+  
+  std::vector<MBEntityHandle> sorted( expected );
+  std::sort( sorted.begin(), sorted.end() );
+  sorted.erase( std::unique( sorted.begin(), sorted.end() ), sorted.end() );
+  
+  int expected_size = 0;
+  if (flags&MESHSET_ORDERED) {
+    if (expected != vect) {
+      std::cout << "Incorrect set contents from vector-based query" << std::endl;
+      print_handle_vect( "Expected", expected );
+      print_handle_vect( "Actual", vect );
+      return false;
+    }
+    expected_size = expected.size();
+  }
+  else {
+    if (sorted != vect) {
+      std::cout << "Incorrect set contents from vector-based query" << std::endl;
+      print_handle_vect( "Expected", sorted );
+      print_handle_vect( "Actual", vect );
+      return false;
+    }
+    expected_size = sorted.size();
+  }
+  
+  if (expected_size != set_count) {
+    std::cout << "Incorrect size for entity set" << std::endl;
+    std::cout << "Expected: " << expected_size << std::endl;
+    std::cout << "Actual:   " << set_count     << std::endl;
+    return false;
+  }
+
+  vect.clear();
+  vect.resize( range.size() );
+  std::copy( range.begin(), range.end(), vect.begin() );
+  if (sorted != vect) {
+    std::cout << "Incorrect set contents from mbrange-based query" << std::endl;
+    print_handle_vect( "Expected", vect );
+    print_mbrange( "Actual", range );
+    return false;
+  }
+  
+  return true;
+}     
+
+bool check_set_contents( MBCore& mb, MBEntityHandle set, const std::vector<MBEntityHandle>& expected )
+{
+  unsigned flags;
+  MBErrorCode rval = mb.get_meshset_options( set, flags );
+  CHECK_ERR(rval);
+  
+  int count;
+  std::vector<MBEntityHandle> vect;
+  MBRange range;
+  rval = mb.get_entities_by_handle( set, vect, false );
+  CHECK_ERR(rval);
+  rval = mb.get_entities_by_handle( set, range, false );
+  CHECK_ERR(rval);
+  rval = mb.get_number_entities_by_handle( set, count, false );
+  CHECK_ERR(rval);
+  
+  if (!compare_set_contents( flags, expected, count, vect, range ))
+    return false;
+ 
+  if (!(flags&MESHSET_TRACK_OWNER))
+    return true;
+  
+    // get all entitites with an adjacency to the set
+  std::vector<MBEntityHandle> adj;
+  MBRange all, adjacent;
+  MBRange::iterator in = adjacent.begin();
+  mb.get_entities_by_handle( 0, all );
+  for (MBRange::iterator i = all.begin(); i != all.end(); ++i) {
+    adj.clear();
+    rval = mb.a_entity_factory()->get_adjacencies( *i, adj );
+    CHECK_ERR(rval);
+    std::vector<MBEntityHandle>::iterator j = std::lower_bound( adj.begin(), adj.end(), set );
+    if (j != adj.end() && *j == set)
+      in = adjacent.insert( in, *i, *i );
+  }
+  
+  if (range != adjacent) {
+    std::cout << "Incorrect adjacent entities for tracking set" << std::endl;
+    print_mbrange( "Expected", range );
+    print_mbrange( "Actual", adjacent );
+    return false;
+  }
+  
+  return true;
+}  
+
+bool check_set_contents( MBCore& mb, MBEntityType type, MBEntityHandle set, unsigned flags )
+{
+  MBErrorCode rval;
+  int count;
+  std::vector<MBEntityHandle> vect, expected;
+  MBRange range;
+  
+  rval = mb.get_entities_by_handle( set, expected, false );
+  CHECK_ERR(rval);
+  std::vector<MBEntityHandle>::iterator i = expected.begin();
+  while (i != expected.end()) {
+    if (TYPE_FROM_HANDLE(*i) != type)
+      i = expected.erase( i );
+    else
+      ++i;
+  }
+  
+  rval = mb.get_entities_by_type( set, type, range, false );
+  CHECK_ERR(rval);
+  rval = mb.get_number_entities_by_type( set, type, count, false );
+  CHECK_ERR(rval);
+  
+  std::copy( range.begin(), range.end(), std::back_inserter(vect) );
+  return compare_set_contents( flags, expected, count, vect, range );
+}  
+
+bool check_set_contents( MBCore& mb, int dim, MBEntityHandle set, unsigned flags )
+{
+  MBErrorCode rval;
+  int count;
+  std::vector<MBEntityHandle> vect, expected;
+  MBRange range;
+  
+  rval = mb.get_entities_by_handle( set, expected, false );
+  CHECK_ERR(rval);
+  std::vector<MBEntityHandle>::iterator i = expected.begin();
+  while (i != expected.end()) {
+    if (MBCN::Dimension(TYPE_FROM_HANDLE(*i)) != dim)
+      i = expected.erase( i );
+    else
+      ++i;
+  }
+  
+  rval = mb.get_entities_by_dimension( set, dim, range, false );
+  CHECK_ERR(rval);
+  rval = mb.get_number_entities_by_dimension( set, dim, count, false );
+  CHECK_ERR(rval);
+  
+  std::copy( range.begin(), range.end(), std::back_inserter(vect) );
+  return compare_set_contents( flags, expected, count, vect, range );
+}  
+
+void test_add_entities( unsigned flags )
+{
+  MBCore mb; make_mesh( mb );
+  
+  MBEntityHandle set;
+  MBErrorCode rval = mb.create_meshset( flags, set );
+  CHECK_ERR(rval);
+  
+  std::vector<MBEntityHandle> contents, vect;
+  MBRange range;
+  
+  range.clear();
+  range.insert( 11, 20 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [11,20]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 31, 40 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [11,20],[31,40]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 51, 60 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [11,20],[31,40],[51,60]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 71, 80 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [11,20],[31,40],[51,60],[71,80]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 91, 100 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [11,20],[31,40],[51,60],[71,80],[91,100]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 111, 120 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [11,20],[31,40],[51,60],[71,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 6, 12 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [6,20],[31,40],[51,60],[71,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 1, 3 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,3],[6,20],[31,40],[51,60],[71,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 25, 25 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,3],[6,20],[25,25],[31,40],[51,60],[71,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 30, 30 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,3],[6,20],[25,25],[30,40],[51,60],[71,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 29, 31 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,3],[6,20],[25,25],[29,40],[51,60],[71,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 41, 41 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,3],[6,20],[25,25],[29,41],[51,60],[71,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 41, 45 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,3],[6,20],[25,25],[29,45],[51,60],[71,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 47, 47 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,3],[6,20],[25,25],[29,45],[47,47],[51,60],[71,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 51, 80 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,3],[6,20],[25,25],[29,45],[47,47],[51,80],[91,100],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 49, 105 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,3],[6,20],[25,25],[29,45],[47,47],[49,105],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  vect.clear();
+  for (MBEntityHandle h = 1; h < 100; ++h) {
+    vect.push_back(h);
+    contents.push_back(h);
+  }
+  rval = mb.add_entities( set, &vect[0], vect.size() );
+  CHECK_ERR(rval);
+  // [1,105],[111,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  vect.clear();
+  vect.push_back( 106 );
+  vect.push_back( 108 );
+  vect.push_back( 110 );
+  std::copy( vect.begin(), vect.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, &vect[0], vect.size() );
+  CHECK_ERR(rval);
+  // [1,106],[108,108],[110,120]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 107, 200 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,200]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 1, 1 );
+  range.insert( 5, 6 );
+  range.insert( 199, 200 );
+  range.insert( 201, 202 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,202]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 300, 301 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,202],[300,301]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 203,203 );
+  range.insert( 205,205 );
+  range.insert( 207,207 );
+  range.insert( 299,299 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,203],[205,205],[207,207],[299,301]
+  CHECK( check_set_contents( mb, set, contents ) );
+}
+
+void remove_from_back( std::vector<MBEntityHandle>& vect, const MBRange& range )
+{
+  for (MBRange::const_iterator r = range.begin(); r != range.end(); ++r) {
+    std::vector<MBEntityHandle>::reverse_iterator i = find( vect.rbegin(), vect.rend(), *r );
+    if (i != vect.rend())
+      *i = 0;
+  }
+  std::vector<MBEntityHandle>::iterator j = vect.begin(); 
+  while (j != vect.end()) {
+    if (*j == 0)
+      j = vect.erase(j);
+    else
+      ++j;
+  }
+}   
+
+void test_remove_entities( unsigned flags )
+{
+  MBCore mb; make_mesh( mb );
+  
+  MBEntityHandle set;
+  MBErrorCode rval = mb.create_meshset( flags, set );
+  CHECK_ERR(rval);
+  
+  std::vector<MBEntityHandle> contents;
+  MBRange range;
+  
+  range.clear();
+  range.insert( 1, 1000 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1,1000]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 1, 5 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [6,1000]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 6, 6 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [7,1000]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 7, 10 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [11,1000]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 1, 20 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,1000]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 1, 5 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,1000]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 22, 30 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[31,1000]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 1000, 1000 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[31,999]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 901, 999 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[31,900]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 900, 999 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[31,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 1000, 1001 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[31,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 890, 898 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[31,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 100, 149 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[31,99],[150,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 31, 99 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[150,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 200, 249 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[150,199],[250,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 300, 349 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[150,199],[250,299],[350,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 159, 399 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[150,158],[400,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 450, 499 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[150,158],[400,449],[500,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 550, 599 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[150,158],[400,449],[500,549],[600,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  range.clear();
+  range.insert( 150, 549 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[600,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  range.clear();
+  range.insert( 650, 699 );
+  remove_from_back( contents, range );
+  rval = mb.remove_entities( set, range );
+  CHECK_ERR(rval);
+  // [21,21],[600,649],[700,889],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  
+  // test vector-based remove
+  assert(contents.size() == 242);
+  std::vector<MBEntityHandle> remlist(5);
+  remlist[0] = contents[240]; contents.erase( contents.begin() + 240 );
+  remlist[1] = contents[200]; contents.erase( contents.begin() + 200 );
+  remlist[2] = contents[100]; contents.erase( contents.begin() + 100 );
+  remlist[3] = contents[ 25]; contents.erase( contents.begin() +  25 );
+  remlist[4] = contents[  0]; contents.erase( contents.begin() +   0 );
+  rval = mb.remove_entities( set, &remlist[0], remlist.size() );
+  CHECK_ERR(rval);
+  // [600,623],[625,649],[700,748],[750,848],[850,888],[899,899]
+  CHECK( check_set_contents( mb, set, contents ) );
+
+  // remove everything
+  std::reverse( contents.begin(), contents.begin() + contents.size()/2 ); // mix up a bit
+  rval = mb.remove_entities( set, &contents[0], contents.size() );
+  CHECK_ERR(rval);
+  contents.clear();
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  // try complicated range-based remove
+  range.clear();
+  contents.clear();
+  range.insert( 100, 200 );
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  // [1000,2000]
+  CHECK( check_set_contents( mb, set, contents ) );
+  
+  MBRange remove;
+  remove.insert( 1, 3 );
+  remove.insert( 10, 100 );
+  remove.insert( 110, 120 );
+  remove.insert( 130, 140 );
+  remove.insert( 150, 160 );
+  remove.insert( 190, 200 );
+  remove.insert( 210, 220 );
+  remove.insert( 230, 240 );
+  range = range.subtract( remove );
+  
+  contents.clear();
+  std::copy( range.begin(), range.end(), std::back_inserter(contents) );
+  rval = mb.remove_entities( set, remove );
+  CHECK_ERR(rval);
+  CHECK( check_set_contents( mb, set, contents ) );  
+}
+
+void test_entities_by_type( unsigned flags )
+{
+  MBEntityHandle first_vert, last_vert, first_hex, last_hex;
+  MBCore mb; make_mesh( mb, first_vert, last_vert, first_hex, last_hex );
+  
+    // Create an entity set
+  MBEntityHandle set;
+  MBErrorCode rval = mb.create_meshset( flags, set );
+  CHECK_ERR(rval);
+
+    // Test empty set
+  CHECK( check_set_contents( mb, MBVERTEX, set, flags ) );
+  CHECK( check_set_contents( mb, MBEDGE  , set, flags ) );
+  CHECK( check_set_contents( mb, MBHEX   , set, flags ) );
+  
+    // Add stuff to set
+  MBRange range;
+  range.insert( first_vert      , first_vert +  10 );
+  range.insert( first_vert + 100, first_vert + 110 );
+  range.insert( first_hex  + 200, first_hex  + 299 );
+  range.insert( last_hex        , last_hex   -  99 );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  
+    // Test 
+  CHECK( check_set_contents( mb, MBVERTEX, set, flags ) );
+  CHECK( check_set_contents( mb, MBEDGE  , set, flags ) );
+  CHECK( check_set_contents( mb, MBHEX   , set, flags ) );
+}
+
+void test_entities_by_dimension( unsigned flags )
+{
+  MBEntityHandle first_vert, last_vert, first_hex, last_hex;
+  MBCore mb; make_mesh( mb, first_vert, last_vert, first_hex, last_hex );
+  
+    // Create an entity set
+  MBEntityHandle set;
+  MBErrorCode rval = mb.create_meshset( flags, set );
+  CHECK_ERR(rval);
+
+    // Test empty set
+  CHECK( check_set_contents( mb, 0, set, flags ) );
+  CHECK( check_set_contents( mb, 1, set, flags ) );
+  CHECK( check_set_contents( mb, 2, set, flags ) );
+  CHECK( check_set_contents( mb, 3, set, flags ) );
+  
+    // Add stuff to set
+  MBRange range;
+  range.insert( first_vert      , first_vert +  10 );
+  range.insert( first_vert + 100, first_vert + 110 );
+  range.insert( first_hex  + 200, first_hex  + 299 );
+  range.insert( last_hex        , last_hex   -  99 );
+  rval = mb.add_entities( set, range );
+  CHECK_ERR(rval);
+  
+    // Test 
+  CHECK( check_set_contents( mb, 0, set, flags ) );
+  CHECK( check_set_contents( mb, 1, set, flags ) );
+  CHECK( check_set_contents( mb, 2, set, flags ) );
+  CHECK( check_set_contents( mb, 3, set, flags ) );
+}
+
+bool test_boolean( MBCore& mb, BoolOp op, 
+                   unsigned flags1, const MBRange& set1_ents, 
+                   unsigned flags2, const MBRange& set2_ents )
+{
+  MBErrorCode rval;
+   
+  // make sets
+  MBEntityHandle set1, set2;
+  rval = mb.create_meshset( flags1, set1 );
+  CHECK_ERR(rval);
+  rval = mb.create_meshset( flags2, set2 );
+  CHECK_ERR(rval);
+  rval = mb.add_entities( set1, set1_ents );
+  CHECK_ERR(rval);
+  rval = mb.add_entities( set2, set2_ents );
+  CHECK_ERR(rval);
+  
+  MBRange tmp_range;
+  std::vector<MBEntityHandle> expected;
+  rval = MB_INDEX_OUT_OF_RANGE;
+  switch (op) {
+    case UNITE:
+      if (flags1 & MESHSET_SET) {
+        tmp_range = set1_ents;
+        tmp_range.merge( set2_ents );
+        expected.resize( tmp_range.size() );
+        std::copy( tmp_range.begin(), tmp_range.end(), expected.begin() );
+      }
+      else {
+        expected.clear();
+        std::copy( set1_ents.begin(), set1_ents.end(), std::back_inserter(expected) );
+        std::copy( set2_ents.begin(), set2_ents.end(), std::back_inserter(expected) );
+      }
+      rval = mb.unite_meshset( set1, set2 );
+      break;
+    case INTERSECT:
+      tmp_range = set1_ents.intersect( set2_ents );
+      expected.resize(tmp_range.size());
+      std::copy( tmp_range.begin(), tmp_range.end(), expected.begin() );
+      rval = mb.intersect_meshset( set1, set2 );
+      break;
+    case SUBTRACT:
+      tmp_range = set1_ents.subtract( set2_ents );
+      expected.resize(tmp_range.size());
+      std::copy( tmp_range.begin(), tmp_range.end(), expected.begin() );
+      rval = mb.subtract_meshset( set1, set2 );
+      break;
+  }
+  CHECK_ERR(rval);
+  
+  return check_set_contents( mb, set1, expected );
+}
+  
+
+void test_intersect( unsigned flags1, unsigned flags2 )
+{
+  MBRange empty, set1_ents, set2_ents;
+  MBEntityHandle first_vert, last_vert, first_hex, last_hex;
+  MBCore mb; make_mesh( mb, first_vert, last_vert, first_hex, last_hex );
+
+    // define contents of first set
+  set1_ents.insert( first_vert, first_vert + 10 );
+  set1_ents.insert( first_vert+100, first_vert+199 );
+  set1_ents.insert( first_hex+100, first_hex+200 );
+  
+    // define contents of second set
+  set2_ents.insert( first_vert, first_vert );
+  set2_ents.insert( first_vert+10, first_vert+10 );
+  set2_ents.insert( first_vert+90, first_vert+209 );
+  set2_ents.insert( first_hex+50, first_hex+300 );
+
+    // check empty sets
+  CHECK( test_boolean( mb, INTERSECT, flags1, empty, flags2, empty ) );
+    // check intersection with 1 empty
+  CHECK( test_boolean( mb, INTERSECT, flags1, empty, flags2, set2_ents ) );
+  CHECK( test_boolean( mb, INTERSECT, flags1, set1_ents, flags2, empty ) );
+    // check intersection of non-empty sets
+  CHECK( test_boolean( mb, INTERSECT, flags1, set1_ents, flags2, set2_ents ) );
+}
+
+void test_unite( unsigned flags1, unsigned flags2 )
+{
+  MBRange empty, set1_ents, set2_ents;
+  MBEntityHandle first_vert, last_vert, first_hex, last_hex;
+  MBCore mb; make_mesh( mb, first_vert, last_vert, first_hex, last_hex );
+
+    // define contents of first set
+  set1_ents.insert( first_vert, first_vert + 10 );
+  set1_ents.insert( first_vert+100, first_vert+199 );
+  set1_ents.insert( first_hex+100, first_hex+200 );
+  
+    // define contents of second set
+  set2_ents.insert( first_vert, first_vert );
+  set2_ents.insert( first_vert+11, first_vert+99 );
+  set2_ents.insert( first_vert+150, first_vert+209 );
+  set2_ents.insert( first_vert+211, first_vert+211 );
+  set2_ents.insert( first_hex+50, first_hex+99 );
+
+    // check empty sets
+  CHECK( test_boolean( mb, UNITE, flags1, empty, flags2, empty ) );
+    // check union with 1 empty
+  CHECK( test_boolean( mb, UNITE, flags1, empty, flags2, set2_ents ) );
+  CHECK( test_boolean( mb, UNITE, flags1, set1_ents, flags2, empty ) );
+    // check union of non-empty sets
+  CHECK( test_boolean( mb, UNITE, flags1, set1_ents, flags2, set2_ents ) );
+}
+
+void test_subtract( unsigned flags1, unsigned flags2 )
+{
+  MBRange empty, set1_ents, set2_ents;
+  MBEntityHandle first_vert, last_vert, first_hex, last_hex;
+  MBCore mb; make_mesh( mb, first_vert, last_vert, first_hex, last_hex );
+
+    // define contents of first set
+  set1_ents.insert( first_vert, first_vert + 10 );
+  set1_ents.insert( first_vert+100, first_vert+199 );
+  set1_ents.insert( first_hex+100, first_hex+200 );
+  
+    // define contents of second set
+  set2_ents.insert( first_vert, first_vert );
+  set2_ents.insert( first_vert+9, first_vert+9 );
+  set2_ents.insert( first_vert+11, first_vert+99 );
+  set2_ents.insert( first_vert+150, first_vert+199 );
+  set2_ents.insert( first_hex+50, first_hex+60 );
+  set2_ents.insert( first_hex+90, first_hex+220 );
+
+    // check empty sets
+  CHECK( test_boolean( mb, SUBTRACT, flags1, empty, flags2, empty ) );
+    // check union with 1 empty
+  CHECK( test_boolean( mb, SUBTRACT, flags1, empty, flags2, set2_ents ) );
+  CHECK( test_boolean( mb, SUBTRACT, flags1, set1_ents, flags2, empty ) );
+    // check union of non-empty sets
+  CHECK( test_boolean( mb, SUBTRACT, flags1, set1_ents, flags2, set2_ents ) );
+}
+
+void test_contains_entities( unsigned flags )
+{
+  CHECK( !(flags&MESHSET_TRACK_OWNER) );
+  MBMeshSet set(flags);
+  bool result;
+  
+  const MBEntityHandle entities[] = { 1,2,3,6,10,11,25,100 };
+  const int num_ents = sizeof(entities)/sizeof(MBEntityHandle);
+  MBErrorCode rval = set.add_entities( entities, num_ents, 0, 0 );
+  CHECK_ERR(rval);
+  
+  result = set.contains_entities( entities, num_ents, MBInterface::UNION );
+  CHECK(result);
+  result = set.contains_entities( entities, num_ents, MBInterface::INTERSECT );
+  CHECK(result);
+  
+  result = set.contains_entities( entities, 1, MBInterface::UNION );
+  CHECK(result);
+  result = set.contains_entities( entities, 1, MBInterface::INTERSECT );
+  CHECK(result);
+  
+  const MBEntityHandle entities2[] = { 3,4,5 };
+  const int num_ents2 = sizeof(entities2)/sizeof(MBEntityHandle);
+  result = set.contains_entities( entities2, num_ents2, MBInterface::UNION );
+  CHECK(result);
+  result = set.contains_entities( entities2, num_ents2, MBInterface::INTERSECT );
+  CHECK(!result);
+}
+
+void test_clear( unsigned flags )
+{
+  std::vector<MBEntityHandle> contents(4);
+  MBCore mb; make_mesh( mb, contents[0], contents[1], contents[2], contents[3] );
+  MBEntityHandle set;
+  MBErrorCode rval = mb.create_meshset( flags, set );
+  CHECK_ERR(rval);
+  rval = mb.add_entities( set, &contents[0], contents.size() );
+  CHECK_ERR(rval);
+  CHECK( check_set_contents( mb, set, contents ) );
+  rval = mb.clear_meshset( &set, 1 );
+  CHECK_ERR(rval);
+  contents.clear();
+  CHECK( check_set_contents( mb, set, contents ) );
+}
+




More information about the moab-dev mailing list