[MOAB-dev] r3379 - MOAB/trunk

kraftche at cae.wisc.edu kraftche at cae.wisc.edu
Fri Nov 20 13:00:50 CST 2009


Author: kraftche
Date: 2009-11-20 13:00:50 -0600 (Fri, 20 Nov 2009)
New Revision: 3379

Modified:
   MOAB/trunk/MBBits.cpp
   MOAB/trunk/MBBits.hpp
   MOAB/trunk/MBInterface.hpp
   MOAB/trunk/MBSkinner.cpp
   MOAB/trunk/MBTest.cpp
   MOAB/trunk/ReadHDF5.cpp
   MOAB/trunk/TagServer.cpp
   MOAB/trunk/TagServer.hpp
   MOAB/trunk/WriteHDF5.cpp
Log:
o Allow get/set of bit tags for multiple entities in one call.  Bits are
  unpacked such that a byte is returned for each entity, with the tag value
  stored in the lower bits (the same as was done for single entities before.)

o Fix inconsistent handling of default value for bits tags.  When querying
  a bit tag with a default value for some entity for which it was not set,
  the previous code could do any of the following: successfully return zero,
  successfully return the default value, or return failure, depending on
  details of the internal representation.

o Add more tests for bit tag functionality.

o Update a couple places in code that might benefit from querying many
  bit tags at once.

o Document behavior of query functions in MBInterface for bit tags and
  multiple entities.



Modified: MOAB/trunk/MBBits.cpp
===================================================================
--- MOAB/trunk/MBBits.cpp	2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBBits.cpp	2009-11-20 19:00:50 UTC (rev 3379)
@@ -64,7 +64,222 @@
   return MB_SUCCESS;
 }
 
+  
+MBErrorCode MBBitPage::get_entities_with_value( unsigned char value, 
+                                                int offset, 
+                                                int count, 
+                                                int num_bits_per_flag,
+                                                MBEntityHandle first,
+                                                MBRange& results ) const
+{
+  if (mBitArray) {
+    MBRange::iterator hint = results.begin();
+    for (int i = 0; i < count; ++i) 
+      if (value == MBBitManipulator::get_bits( (offset+i)*num_bits_per_flag, 
+                                               num_bits_per_flag, mBitArray))
+        hint = results.insert( hint, first + i );
+  }
+  return MB_SUCCESS;
+}
 
+void MBBitPage::alloc_array( int num_bits_per_flag, 
+                             const unsigned char* default_value )
+{
+  assert(!mBitArray);
+  
+  mBitArray = new unsigned char[mPageSize];
+    // Modifed by J.Kraftcheck : 31 Jan, 2008:
+    //  Need to initialize to default value to ensure that we return
+    //  the default value for unset entities.  
+
+    // Zero memory if no default value.  Also, if default value is
+    // zero, we can zero all the memory w/out worring about the
+    // number of bits per entity.
+  if (!default_value || !*default_value)
+    memset(mBitArray, 0, mPageSize);
+    // Otherwise initialize memory using default value
+  else {
+      // Mask unused bits of default value so that we can set
+      // individual bits using bitwise-OR w/out having to worry
+      // about masking unwanted stuff.
+    unsigned char defval = (*default_value) & ((1u << num_bits_per_flag) - 1);
+
+    switch (num_bits_per_flag) {
+      // If number of bits is a power of two (a byte contains a whole
+      // number of tag bit values) then use memset to initialize the memory.
+      // Note fall-through for switch cases:  for 1-bit tags we first
+      // copy the lsb into the adjacent bit, then fall through to 2-bit
+      // case, copying last two bits into next two, and so on.
+      case 1: defval |= (defval << 1);
+      case 2: defval |= (defval << 2);
+      case 4: defval |= (defval << 4);
+      case 8: memset( mBitArray, defval, mPageSize );
+        break;
+      // If num_bits_per_flag is not a power of two, then values do
+      // not align with byte boundaries.  Need to initialize values
+      // individually.
+      default:
+        memset(mBitArray, 0, mPageSize);
+        // Subtract 1 from mPageSize because last byte is unused, allowing
+        // questionable MBBitManipulator code to read/write 1 past end 
+        // of array.
+        for (int i = 0; i < 8 * (mPageSize-1); i += num_bits_per_flag)
+          MBBitManipulator::set_bits( i, num_bits_per_flag, defval, mBitArray );
+    }
+  }
+}
+
+
+MBErrorCode MBBitPageGroup::get_bits( MBEntityHandle start, 
+                                      MBEntityID count,
+                                      unsigned char* bits,
+                                      const unsigned char* def_val)
+{
+  MBErrorCode result = MB_SUCCESS, tmp_result;
+  
+  
+  MBEntityID id = ID_FROM_HANDLE(start);
+  MBEntityHandle page = id/mOffsetFactor;
+  MBEntityID offset = id%mOffsetFactor;
+  MBEntityID pcount = mOffsetFactor - offset;
+  while (count) {
+    if (pcount > count)
+      pcount = count;
+    
+    if (page >= mBitPagesSize) {
+      memset( bits, def_val ? *def_val : 0, count );
+      break;
+    }
+    
+    tmp_result = mBitPages[page]->get_bits( offset, pcount, mBitsPerFlag, bits, def_val);
+    if (MB_SUCCESS != tmp_result) {
+      memset( bits, 0, pcount );
+      result = tmp_result;
+    }
+    
+    count -= pcount;
+    bits += pcount;
+    ++page;
+    offset = 0;
+    pcount = mOffsetFactor;
+  }
+  
+  return result;
+}
+
+MBErrorCode MBBitPageGroup::set_bits( MBEntityHandle start, 
+                                      MBEntityID count,
+                                      const unsigned char* bits,
+                                      const unsigned char* def_val)
+{
+  MBErrorCode result = MB_SUCCESS, tmp_result;
+  MBEntityID id = ID_FROM_HANDLE(start);
+  MBEntityHandle page = id/mOffsetFactor;
+  MBEntityID offset = id%mOffsetFactor;
+  MBEntityID pcount = mOffsetFactor - offset;
+  while (count) {
+    if (pcount > count)
+      pcount = count;
+    
+    if (page >= mBitPagesSize) {
+      for(int j = page - mBitPagesSize +1; j--;)
+        mBitPages.push_back(new MBBitPage());
+      mBitPagesSize = mBitPages.size();
+    }
+
+    tmp_result = mBitPages[page]->set_bits( offset, pcount, mBitsPerFlag, bits, def_val);
+    if (MB_SUCCESS != tmp_result) {
+      result = tmp_result;
+    }
+    
+    count -= pcount;
+    bits += pcount;
+    ++page;
+    offset = 0;
+    pcount = mOffsetFactor;
+  }
+  
+  return result;
+}
+
+  
+MBErrorCode MBBitPageGroup::get_entities_with_value( unsigned char value,
+                                                     MBEntityHandle first,
+                                                     MBEntityHandle last,
+                                                     MBRange& results )
+{
+  MBErrorCode rval;
+  assert(last >= first);
+  MBEntityID count = last - first + 1;
+  
+  MBEntityID id = ID_FROM_HANDLE(first);
+  MBEntityHandle page = id/mOffsetFactor;
+  MBEntityID offset = id%mOffsetFactor;
+  MBEntityID pcount = mOffsetFactor - offset;
+  while (count && page < mBitPagesSize) {
+    if (pcount > count)
+      pcount = count;
+    
+    rval = mBitPages[page]->get_entities_with_value( value, offset, pcount, mBitsPerFlag, first, results );
+    if (MB_SUCCESS != rval)
+      return rval;
+    
+    first += pcount;
+    count -= pcount;
+    ++page;
+    offset = 0;
+    pcount = mOffsetFactor;
+  }
+  
+  return MB_SUCCESS;
+}
+
+MBErrorCode MBBitServer::set_bits( MBTagId tag_id, 
+                                   const MBRange& handles,
+                                   const unsigned char* data,
+                                   const unsigned char* default_val)
+{
+  --tag_id; // First ID is 1.
+  if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+    return MB_TAG_NOT_FOUND;
+
+  MBErrorCode rval;
+  MBRange::const_pair_iterator i;
+  for (i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i) {
+    MBEntityType type = TYPE_FROM_HANDLE(i->first);
+    assert(TYPE_FROM_HANDLE(i->second) == type); // should be true because id of zero is never used
+    MBEntityID count = i->second - i->first + 1;
+    rval = mBitPageGroups[type][tag_id]->set_bits(i->first, count, data, default_val);
+    if (MB_SUCCESS != rval)
+      return rval;
+    data += count;
+  }
+  return MB_SUCCESS;
+}
+
+MBErrorCode MBBitServer::get_bits( MBTagId tag_id, 
+                                   const MBRange& handles,
+                                   unsigned char* data,
+                                   const unsigned char* default_val)
+{
+  --tag_id; // First ID is 1.
+  if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+    return MB_TAG_NOT_FOUND;
+
+  MBErrorCode rval;
+  MBRange::const_pair_iterator i;
+  for (i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i) {
+    MBEntityType type = TYPE_FROM_HANDLE(i->first);
+    assert(TYPE_FROM_HANDLE(i->second) == type); // should be true because id of zero is never used
+    MBEntityID count = i->second - i->first + 1;
+    rval = mBitPageGroups[type][tag_id]->get_bits(i->first, count, data, default_val);
+    if (MB_SUCCESS != rval)
+      return rval;
+    data += count;
+  }
+  return MB_SUCCESS;
+}
+
 /*! give back a tag id that was used to set and get bits */
 MBErrorCode MBBitServer::release_tag_id(MBTagId tag_id)
 {
@@ -192,51 +407,50 @@
   return result;
 }
 
-MBErrorCode MBBitServer::get_entities_with_tag_value(MBTagId tag_id, 
-                                                       MBEntityType type,
-                                                       MBRange& entities, 
-                                                       const unsigned char bits)
+MBErrorCode MBBitServer::get_entities_with_tag_value( MBTagId tag_id, 
+                                                      MBEntityType type,
+                                                      MBRange& entities, 
+                                                      const unsigned char bits)
 {
-  MBRange possibles;
-  MBErrorCode result = get_entities(tag_id, type, possibles);
-  if (MB_SUCCESS != result || possibles.empty()) return result;
-  MBErrorCode tmp_result;
-  unsigned char dum = 0;
-  for (MBRange::iterator it = possibles.begin(); it != possibles.end(); it++) {
-    tmp_result = get_bits(tag_id, *it, dum);
-    if (dum == bits) entities.insert(*it);
-    if (tmp_result != MB_SUCCESS) result = tmp_result;
-  }
-  
-  return result;
+  --tag_id; // First ID is 1.
+  if(tag_id >= mBitPageGroups[type].size() || mBitPageGroups[type][tag_id] == NULL)
+    return MB_TAG_NOT_FOUND;
+
+  return mBitPageGroups[type][tag_id]->
+    get_entities_with_value( bits, FIRST_HANDLE(type), LAST_HANDLE(type), entities );
 }
 
-MBErrorCode MBBitServer::get_entities_with_tag_value(const MBRange &range,
-                                                       MBTagId tag_id, MBEntityType type, 
-                                                       MBRange& entities,
-                                                       const unsigned char bits)
+MBErrorCode MBBitServer::get_entities_with_tag_value( const MBRange &range,
+                                                      MBTagId tag_id, 
+                                                      MBEntityType type, 
+                                                      MBRange& entities,
+                                                      const unsigned char bits)
 {
-  MBRange temp1, temp2;
-  MBErrorCode result = get_entities(tag_id, type, temp1);
-  if (MB_SUCCESS != result) return result;
-  std::set_intersection(range.begin(), range.end(),
-                        temp1.begin(), temp1.end(), mb_range_inserter(temp2));
-  if (temp2.empty()) return result;
-  
-  unsigned char dum = 0;
-  MBErrorCode tmp_result;
-  for (MBRange::iterator it = temp2.begin(); it != temp2.end(); it++) {
-    tmp_result = get_bits(tag_id, *it, dum);
-    if (dum == bits) entities.insert(*it);
-    if (tmp_result != MB_SUCCESS) result = tmp_result;
+  --tag_id; // First ID is 1.
+  if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+    return MB_TAG_NOT_FOUND;
+
+  MBErrorCode rval;
+  MBRange::const_pair_iterator i;
+  for (i = range.const_pair_begin(); i != range.const_pair_end(); ++i) {
+    MBEntityType this_type = TYPE_FROM_HANDLE(i->first);
+    assert(TYPE_FROM_HANDLE(i->second) == this_type); // should be true because id of zero is never used
+    if (type < this_type)
+      continue;
+    if (type > this_type)
+      break;
+      
+    rval = mBitPageGroups[type][tag_id]->
+      get_entities_with_value( bits, i->first, i->second, entities );
+    if (MB_SUCCESS != rval)
+      return rval;
   }
-  
-  return result;
+  return MB_SUCCESS;
 }
 
 MBErrorCode MBBitServer::get_number_entities( const MBTagId tag_id,
-                                                const MBEntityType type,
-                                                int& num_entities) 
+                                              const MBEntityType type,
+                                              int& num_entities) 
 {
   MBRange dum_range;
   MBErrorCode result = get_entities(tag_id, type, dum_range);

Modified: MOAB/trunk/MBBits.hpp
===================================================================
--- MOAB/trunk/MBBits.hpp	2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBBits.hpp	2009-11-20 19:00:50 UTC (rev 3379)
@@ -179,12 +179,30 @@
   }
   
   //! get the bits from a bit page
-  MBErrorCode get_bits(int offset, int num_bits_per_flag, unsigned char& bits);
+  MBErrorCode get_bits(int offset, int num_bits_per_flag, unsigned char& bits,
+                       const unsigned char* default_value);
   
   //! set the bits in a bit page
   MBErrorCode set_bits(int offset, int num_bits_per_flag, unsigned char bits, 
                        const unsigned char* default_value);
   
+  //! get the bits from a bit page
+  MBErrorCode get_bits(int offset, int count, int num_bits_per_flag, 
+                       unsigned char* bits,
+                       const unsigned char* default_value);
+  
+  //! set the bits in a bit page
+  MBErrorCode set_bits(int offset, int count, int num_bits_per_flag, 
+                       const unsigned char* bits, 
+                       const unsigned char* default_value);
+  
+  MBErrorCode get_entities_with_value( unsigned char value, 
+                                       int offset, 
+                                       int count, 
+                                       int num_bits_per_flag,
+                                       MBEntityHandle first,
+                                       MBRange& results ) const;
+  
   //! set the bits in a bit page only if space has been allocated
   MBErrorCode weak_set_bits(int offset, int num_bits_per_flag, unsigned char bits);
 
@@ -193,6 +211,8 @@
 private:
   //! bit array  uses lazy allocation
   unsigned char* mBitArray;
+
+  void alloc_array( int num_bits_per_flag, const unsigned char* default_value );
   
   //! don't allow copying of these bit pages
   MBBitPage(const MBBitPage&) 
@@ -217,13 +237,15 @@
     takes how many bits to get
     return bits
 */
-inline MBErrorCode MBBitPage::get_bits(int offset, int num_bits_per_flag, unsigned char& bits)
+inline MBErrorCode MBBitPage::get_bits(int offset, int num_bits_per_flag,
+                                       unsigned char& bits,
+                                       const unsigned char* def_val)
 {
   // because the default bits are 0x0, 
   // we'll return that if no memory has been allocated
   if(!mBitArray)
   {
-    bits = 0;
+    bits = def_val ? *def_val : 0;
     return MB_SUCCESS;
   }
 
@@ -233,66 +255,64 @@
 
   return MB_SUCCESS;
 }
+inline MBErrorCode MBBitPage::get_bits(int offset, int count,
+                                       int num_bits_per_flag,
+                                       unsigned char* bits,
+                                       const unsigned char* def_val)
+{
+  // because the default bits are 0x0, 
+  // we'll return that if no memory has been allocated
+  if(!mBitArray)
+  {
+    memset( bits, def_val ? *def_val : 0, count );
+    return MB_SUCCESS;
+  }
 
+  // get bits using bit manipulator
+  for (int i = 0; i < count; ++i)
+    bits[i] = MBBitManipulator::get_bits(
+      (offset+i)*num_bits_per_flag, num_bits_per_flag, mBitArray);
+
+  return MB_SUCCESS;
+}
+
+
 /*! set the bits in a bit page
     takes bit offset into the page
     takes how many bits to set
     takes the bits to set
 */
-inline MBErrorCode MBBitPage::set_bits(int offset, 
-    int num_bits_per_flag, unsigned char bits,
-    const unsigned char* default_value)
+inline MBErrorCode MBBitPage::set_bits( int offset, 
+                                        int num_bits_per_flag, 
+                                        unsigned char bits,
+                                        const unsigned char* default_value)
 {
   // if memory hasn't been allocated, allocate it and zero the memory
   if(!mBitArray)
-  {
-    mBitArray = new unsigned char[mPageSize];
-      // Modifed by J.Kraftcheck : 31 Jan, 2008:
-      //  Need to initialize to default value to ensure that we return
-      //  the default value for unset entities.  
-      
-      // Zero memory if no default value.  Also, if default value is
-      // zero, we can zero all the memory w/out worring about the
-      // number of bits per entity.
-    if (!default_value || !*default_value)
-      memset(mBitArray, 0, mPageSize);
-      // Otherwise initialize memory using default value
-    else {
-        // Mask unused bits of default value so that we can set
-        // individual bits using bitwise-OR w/out having to worry
-        // about masking unwanted stuff.
-      unsigned char defval = (*default_value) & ((1u << num_bits_per_flag) - 1);
-    
-      switch (num_bits_per_flag) {
-        // If number of bits is a power of two (a byte contains a whole
-        // number of tag bit values) then use memset to initialize the memory.
-        // Note fall-through for switch cases:  for 1-bit tags we first
-        // copy the lsb into the adjacent bit, then fall through to 2-bit
-        // case, copying last two bits into next two, and so on.
-        case 1: defval |= (defval << 1);
-        case 2: defval |= (defval << 2);
-        case 4: defval |= (defval << 4);
-        case 8: memset( mBitArray, defval, mPageSize );
-          break;
-        // If num_bits_per_flag is not a power of two, then values do
-        // not align with byte boundaries.  Need to initialize values
-        // individually.
-        default:
-          memset(mBitArray, 0, mPageSize);
-          // Subtract 1 from mPageSize because last byte is unused, allowing
-          // questionable MBBitManipulator code to read/write 1 past end 
-          // of array.
-          for (int i = 0; i < 8 * (mPageSize-1); i += num_bits_per_flag)
-            MBBitManipulator::set_bits( i, num_bits_per_flag, defval, mBitArray );
-      }
-    }
-  }
+    alloc_array( num_bits_per_flag, default_value );
 
   // set the bits using bit manipulator
   return MBBitManipulator::set_bits(
       offset*num_bits_per_flag, num_bits_per_flag, bits, mBitArray);
 }
+inline MBErrorCode MBBitPage::set_bits( int offset, int count,
+                                        int num_bits_per_flag, 
+                                        const unsigned char* bits,
+                                        const unsigned char* default_value)
+{
+  // if memory hasn't been allocated, allocate it and zero the memory
+  if(!mBitArray)
+    alloc_array( num_bits_per_flag, default_value );
 
+  // set the bits using bit manipulator
+  for (int i = 0; i < count; ++i) 
+    MBBitManipulator::set_bits( (offset+i)*num_bits_per_flag,
+                                num_bits_per_flag,
+                                bits[i], mBitArray );
+  return MB_SUCCESS;
+}
+
+
 /*! weak set bits only sets bits if memory has been allocated
     takes bit offset
     takes number of bits to set
@@ -331,16 +351,32 @@
   }
 
   //! get bits from bit pages
-  MBErrorCode get_bits(MBEntityHandle handle, unsigned char& bits);
+  MBErrorCode get_bits(MBEntityHandle handle, unsigned char& bits,
+                       const unsigned char* default_value);
 
   //! set bits in bit pages
   MBErrorCode set_bits(MBEntityHandle handle, unsigned char bits, 
                        const unsigned char* default_value);
 
+  //! get bits from bit pages
+  MBErrorCode get_bits(MBEntityHandle start, MBEntityID count,
+                       unsigned char* data,
+                       const unsigned char* default_value);
+
+  //! set bits in bit pages
+  MBErrorCode set_bits(MBEntityHandle start, MBEntityID count,
+                       const unsigned char* data, 
+                       const unsigned char* default_value);
+
   //! set bits in bit pages only if the bit page allocated memory
   MBErrorCode weak_set_bits(MBEntityHandle handle, unsigned char bits);
 
   MBErrorCode get_entities(MBEntityType type, MBRange& entities);
+  
+  MBErrorCode get_entities_with_value( unsigned char value,
+                                       MBEntityHandle first,
+                                       MBEntityHandle last,
+                                       MBRange& results );
 
   //! if this page group contains this entity, return true, otherwise false
   bool contains(const MBEntityHandle handle) const;
@@ -391,7 +427,9 @@
     takes entity handle
     return the bits
 */
-inline MBErrorCode MBBitPageGroup::get_bits(MBEntityHandle handle, unsigned char& bits)
+inline MBErrorCode MBBitPageGroup::get_bits(MBEntityHandle handle, 
+                                            unsigned char& bits,
+                                            const unsigned char* def_val)
 {
   // strip off the entity type
   handle = ID_FROM_HANDLE(handle);
@@ -399,14 +437,14 @@
   unsigned int which_page = handle / mOffsetFactor;
   
   // if the page isn't there, just return 0x0
-  if(which_page >= mBitPagesSize)
-  {
-    bits = 0;
-    return MB_TAG_NOT_FOUND;
+  if(which_page >= mBitPagesSize) {
+    bits = def_val ? *def_val : 0;
+    return MB_SUCCESS;
   }
 
   // return bits from bit page
-  return mBitPages[which_page]->get_bits( (handle - ( which_page * mOffsetFactor )), mBitsPerFlag, bits);
+  return mBitPages[which_page]->get_bits( (handle - ( which_page * mOffsetFactor )), 
+                                          mBitsPerFlag, bits, def_val);
 }
 
 /*! set the bits in bit pages
@@ -504,11 +542,26 @@
   //! release a tag id for reuse
   MBErrorCode release_tag_id(MBTagId tag_id);
 
-  //! get the bits associated with an entity handle
-  MBErrorCode get_bits(MBTagId tag_id, MBEntityHandle handle, unsigned char& bits);
+  //! get the bits associated with entity handles
+  MBErrorCode get_bits(MBTagId tag_id, 
+                       const MBEntityHandle* handles, 
+                       int num_handles, 
+                       unsigned char* data,
+                       const unsigned char* default_value);
+  MBErrorCode get_bits(MBTagId tag_id, 
+                       const MBRange& handles, 
+                       unsigned char* data,
+                       const unsigned char* default_value);
   //! set the bits associated with an entity handle
-  MBErrorCode set_bits(MBTagId tag_id, MBEntityHandle handle, unsigned char bits, 
+  MBErrorCode set_bits(MBTagId tag_id, 
+                       const MBEntityHandle* handles, 
+                       int num_handles,
+                       const unsigned char* data, 
                        const unsigned char* default_value);
+  MBErrorCode set_bits(MBTagId tag_id, 
+                       const MBRange& handles, 
+                       const unsigned char* data, 
+                       const unsigned char* default_value);
   //! set the bits associated with an entity handle, only if memory has been allocated
   MBErrorCode weak_set_bits(MBTagId tag_id, MBEntityHandle handle, unsigned char bits);
 
@@ -559,28 +612,46 @@
 };
 
 /*! get some bits based on a tag id and handle */
-inline MBErrorCode MBBitServer::get_bits(MBTagId tag_id, 
-    MBEntityHandle handle, unsigned char& bits)
+inline 
+MBErrorCode MBBitServer::get_bits( MBTagId tag_id, 
+                                   const MBEntityHandle* handles, 
+                                   int num_handles,
+                                   unsigned char* data,
+                                   const unsigned char* default_val)
 {
   --tag_id; // First ID is 1.
-  if(tag_id >= (*mBitPageGroups).size() || (*mBitPageGroups)[tag_id] == NULL)
-    return MB_FAILURE;
+  if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+    return MB_TAG_NOT_FOUND;
 
-  return mBitPageGroups[TYPE_FROM_HANDLE(handle)][tag_id]->get_bits(handle, bits);
-
+  MBErrorCode rval;
+  for (int i = 0; i < num_handles; ++i) {
+    rval = mBitPageGroups[TYPE_FROM_HANDLE(handles[i])][tag_id]
+      ->get_bits(handles[i], data[i], default_val);
+    if (MB_SUCCESS != rval)
+      return rval;
+  }
+  return MB_SUCCESS;
 }
 
-/*! set some bits based on a tag id and handle */
-inline MBErrorCode MBBitServer::set_bits( MBTagId tag_id, 
-                                          MBEntityHandle handle, 
-                                          unsigned char bits,
-                                          const unsigned char* default_value )
+inline 
+MBErrorCode MBBitServer::set_bits( MBTagId tag_id, 
+                                   const MBEntityHandle* handles, 
+                                   int num_handles,
+                                   const unsigned char* data,
+                                   const unsigned char* default_val)
 {
   --tag_id; // First ID is 1.
-  if(tag_id >= mBitPageGroupsSize || (*mBitPageGroups)[tag_id] == NULL)
-    return MB_FAILURE;
+  if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+    return MB_TAG_NOT_FOUND;
 
-  return mBitPageGroups[TYPE_FROM_HANDLE(handle)][tag_id]->set_bits(handle, bits, default_value);
+  MBErrorCode rval;
+  for (int i = 0; i < num_handles; ++i) {
+    rval = mBitPageGroups[TYPE_FROM_HANDLE(handles[i])][tag_id]
+      ->set_bits(handles[i], data[i], default_val);
+    if (MB_SUCCESS != rval)
+      return rval;
+  }
+  return MB_SUCCESS;
 }
 
 /*! set some bits based on a tag id and handle only if memory has been allocated*/

Modified: MOAB/trunk/MBInterface.hpp
===================================================================
--- MOAB/trunk/MBInterface.hpp	2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBInterface.hpp	2009-11-20 19:00:50 UTC (rev 3379)
@@ -1143,8 +1143,11 @@
 
     //! Get the value of the indicated tag on the specified entities in the specified vector
     /** Get the value of the indicated tag on the specified entities; <em>tag_data</em> must contain
-        enough space (i.e. tag_size*num_entities bytes or bits) to hold all tag data.  MB does <em>not</em>
+        enough space (i.e. tag_size*num_entities bytes) to hold all tag data.  MOAB does <em>not</em>
         check whether this space is available before writing to it.
+        \note For bit tags, tag_data must contain one byte per entity.  For each
+              entity, the corresponding byte will contain the tag bits in the
+              lower bit positions and zero bits in the higher.
         \param tag_handle Tag whose values are being queried.
         \param entity_handles 1d vector of entity handles whose tag values are being queried
         \param num_entities Number of entities in 1d vector of entity handles
@@ -1168,6 +1171,9 @@
     //! Set the value of the indicated tag on the specified entities in the specified vector
     /** Set the value of the indicated tag on the specified entities; <em>tag_data</em> contains the
         values, <em>one value per entity in <em>entity_handles</em></em>.
+        \note For bit tags, tag_data must contain one byte per entity.  For each
+              entity, the tag bits will be read from the lower bits of the 
+              corresponding byte.
         \param tag_handle Tag whose values are being set
         \param entity_handles 1d vector of entity handles whose tag values are being set
         \param num_entities Number of entities in 1d vector of entity handles
@@ -1192,6 +1198,7 @@
     /**\brief Get pointers to tag data
      *
      * For a tag, get the values for a list of passed entity handles.
+     *\note  This function may not be used for bit tags.
      *\param tag_handle     The tag
      *\param entity_handles An array of entity handles for which to retreive tag values.
      *\param num_entities   The length of the 'entity_handles' array.
@@ -1211,6 +1218,7 @@
     /**\brief Get pointers to tag data
      *
      * For a tag, get the values for a list of passed entity handles.
+     *\note  This function may not be used for bit tags.
      *\param tag_handle     The tag
      *\param entity_handles The entity handles for which to retreive tag values.
      *\param tag_data       An array of 'const void*'.  Array is populated (output)
@@ -1227,6 +1235,7 @@
     /**\brief Set tag data given an array of pointers to tag values.
      *
      * For a tag, set the values for a list of passed entity handles.
+     *\note  This function may not be used for bit tags.
      *\param tag_handle     The tag
      *\param entity_handles An array of entity handles for which to set tag values.
      *\param num_entities   The length of the 'entity_handles' array.
@@ -1246,6 +1255,7 @@
     /**\brief Set tag data given an array of pointers to tag values.
      *
      * For a tag, set the values for a list of passed entity handles.
+     *\note  This function may not be used for bit tags.
      *\param tag_handle     The tag
      *\param entity_handles The entity handles for which to set tag values.
      *\param tag_data       An array of 'const void*'.  Array is expected to

Modified: MOAB/trunk/MBSkinner.cpp
===================================================================
--- MOAB/trunk/MBSkinner.cpp	2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBSkinner.cpp	2009-11-20 19:00:50 UTC (rev 3379)
@@ -1031,27 +1031,15 @@
     return rval;
   
     // tag all entities in input range
-  if (use_bit_tag) {
-    bit = '\001';
-    for (MBRange::const_iterator it = entities.begin(); it != entities.end(); ++it) {
-      rval = thisMB->tag_set_data( tag, &*it, 1, &bit );
-      if (MB_SUCCESS != rval) {
-        thisMB->tag_delete(tag);
-        return rval;
-      }
-    }
+  size_t count = entities.size();
+  char* vect = new char[count];
+  memset( vect, 1, count );
+  rval = thisMB->tag_set_data( tag, entities, vect );
+  delete [] vect;
+  if (MB_SUCCESS != rval) {
+    thisMB->tag_delete(tag);
+    return rval;
   }
-  else {
-    size_t count = entities.size();
-    char* vect = new char[count];
-    memset( vect, 1, count );
-    rval = thisMB->tag_set_data( tag, entities, vect );
-    delete [] vect;
-    if (MB_SUCCESS != rval) {
-      thisMB->tag_delete(tag);
-      return rval;
-    }
-  }
   
   switch (dim) {
     case 1:
@@ -1101,7 +1089,6 @@
   std::vector<char> tag_vals;
   std::vector<MBEntityHandle> adj;
   int count;
-  char bit;
   for (MBRange::const_iterator it = verts.begin(); it != verts.end(); ++it) {
     adj.clear();
     rval = thisMB->get_adjacencies( &*it, 1, 1, false, adj );
@@ -1110,21 +1097,10 @@
       continue;
 
         // remove those not in the input list
-    if (use_bit_tag) {
-      count = 0;
-      for (i = adj.begin(); i != adj.end(); ++i) {
-        rval = thisMB->tag_get_data( tag, &*i, 1, &bit );
-        if (MB_SUCCESS != rval) return rval;
-        if (bit) 
-          ++count;
-      }
-    }
-    else {
-      tag_vals.resize( adj.size() );
-      rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
-      if (MB_SUCCESS != rval) return rval;
-      count = std::count( tag_vals.begin(), tag_vals.end(), '\001' );
-    }
+    tag_vals.resize( adj.size() );
+    rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
+    if (MB_SUCCESS != rval) return rval;
+    count = std::count( tag_vals.begin(), tag_vals.end(), '\001' );
     
     if (count == 1) {
       hint = skin_verts.insert( hint, *it );
@@ -1352,7 +1328,6 @@
   std::vector<MBEntityHandle> storage;
   const MBEntityHandle *conn;
   int len;
-  char bit;
   bool find_edges = skin_edges || create_edges;
   MBEntityHandle face;
   
@@ -1380,26 +1355,15 @@
 
       // remove those not in the input list
     i = j = adj.begin();
-    if (use_bit_tag) {
-      for (; i != adj.end(); ++i) {
-        rval = thisMB->tag_get_data( tag, &*i, 1, &bit );
-        if (MB_SUCCESS != rval) return rval;
-        if (bit) 
-          *(j++) = *i;
-      }
-      adj.erase( j, adj.end() );
-    }
-    else {
-      tag_vals.resize( adj.size() );
-      rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
-      if (MB_SUCCESS != rval) return rval;
-      
-      i = j = adj.begin();
-      for (; i != adj.end(); ++i) 
-        if (tag_vals[i - adj.begin()])
-          *(j++) = *i;
-      adj.erase( j, adj.end() );
-    } 
+    tag_vals.resize( adj.size() );
+    rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
+    if (MB_SUCCESS != rval) return rval;
+
+    i = j = adj.begin();
+    for (; i != adj.end(); ++i) 
+      if (tag_vals[i - adj.begin()])
+        *(j++) = *i;
+    adj.erase( j, adj.end() );
     
       // For each adjacent face, check the edges adjacent to the current vertex
     adj_edges.clear();    // other vertex for adjacent edges
@@ -1521,7 +1485,6 @@
   std::vector<MBEntityHandle> storage, storage2;
   const MBEntityHandle *conn, *conn2;
   int len, len2;
-  char bit;
   bool find_faces = skin_faces || create_faces;
   int clen, side, sense, offset, indices[9];
   MBEntityType face_type;
@@ -1552,24 +1515,13 @@
       
       // remove those not in the input list
     i = j = adj.begin();
-    if (use_bit_tag) {
-      for (; i != adj.end(); ++i) {
-        rval = thisMB->tag_get_data( tag, &*i, 1, &bit );
-        if (MB_SUCCESS != rval) return rval;
-        if (bit) 
-          *(j++) = *i;
-      }
-      adj.erase( j, adj.end() );
-    }
-    else {
-      tag_vals.resize( adj.size() );
-      rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
-      if (MB_SUCCESS != rval) return rval;
-      for (; i != adj.end(); ++i) 
-        if (tag_vals[i - adj.begin()])
-          *(j++) = *i;
-      adj.erase( j, adj.end() );
-    } 
+    tag_vals.resize( adj.size() );
+    rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
+    if (MB_SUCCESS != rval) return rval;
+    for (; i != adj.end(); ++i) 
+      if (tag_vals[i - adj.begin()])
+        *(j++) = *i;
+    adj.erase( j, adj.end() );
       
       // Build lists of sides of 3D element adjacent to the current vertex
     adj_quads.clear(); // store three other vertices for each adjacent quad face

Modified: MOAB/trunk/MBTest.cpp
===================================================================
--- MOAB/trunk/MBTest.cpp	2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBTest.cpp	2009-11-20 19:00:50 UTC (rev 3379)
@@ -3420,7 +3420,56 @@
     if(bits != ((*iter) & 0x7))
       return MB_FAILURE;
   }
+  
+  // test range-based query for all vertices
+  std::vector<unsigned char> data(entities.size());
+  success = MB->tag_get_data( bit_tag, entities, &data[0] );
+  if (MB_SUCCESS != success) return success;
+  std::vector<unsigned char>::iterator i = data.begin();
+  for (iter = entities.begin(); iter != entities.end(); ++iter, ++i) 
+    if (*i != ((*iter) & 0x7))
+      return MB_FAILURE;
 
+  // test vector-based query for all vertices
+  std::vector<MBEntityHandle> verts(entities.begin(), entities.end());
+  success = MB->tag_get_data( bit_tag, &verts[0], verts.size(), &data[0] );
+  if (MB_SUCCESS != success) return success;
+  i = data.begin();
+  for (iter = entities.begin(); iter != entities.end(); ++iter, ++i) 
+    if (*i != ((*iter) & 0x7))
+      return MB_FAILURE;
+  
+  // test default value
+  const unsigned char default_bits = '\005'; // 0000 0101
+  MBTag tag2;
+  success = MB->tag_create( "bit with default", 4, MB_TAG_BIT, tag2, &default_bits );
+  if (MB_SUCCESS != success) {
+    cout << "Failed to create bit tag with default value" << std::endl;
+    return success;
+  }
+  
+  // set value to zero on a single vertex
+  bits = 0;
+  MBEntityHandle zh = verts[verts.size()/2];
+  success = MB->tag_set_data( tag2, &zh, 1, &bits );
+  if (MB_SUCCESS != success)
+    return success;
+  
+  // get tag values for all entities
+  data.clear();
+  data.resize( verts.size(), 0x7A ); // initialize with 0111 1010
+  success = MB->tag_get_data( tag2, entities, &data[0] );
+  if (MB_SUCCESS != success)
+    return success;
+  
+  // check values
+  i = data.begin();
+  for (iter = entities.begin(); iter != entities.end(); ++iter, ++i) 
+    if (*iter == zh && *i) // the one we set to zero
+      return MB_FAILURE;
+    else if (*iter != zh && *i != default_bits)
+      return MB_FAILURE;
+
   return MB_SUCCESS;
 }
 

Modified: MOAB/trunk/ReadHDF5.cpp
===================================================================
--- MOAB/trunk/ReadHDF5.cpp	2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/ReadHDF5.cpp	2009-11-20 19:00:50 UTC (rev 3379)
@@ -3038,18 +3038,8 @@
           return error(rval);
       }
       
-/*** FIX ME - need to do one at a time for BIT tags!  This is stupid. ***/
-      if (mbtype == MB_TYPE_BIT)
-      {
-        rval = MB_SUCCESS;
-        for ( ; MB_SUCCESS == rval && i < j; ++i)
-          rval = iFace->tag_set_data( tag_handle, idbuf + i, 1, databuf + i );
-      }
-      else
-      {
-        rval = iFace->tag_set_data( tag_handle, idbuf + i, j - i, databuf + i*read_size );
-        i = j;
-      }
+      rval = iFace->tag_set_data( tag_handle, idbuf + i, j - i, databuf + i*read_size );
+      i = j;
       if (MB_SUCCESS != rval)
         return error(rval);
     } // for(ever)

Modified: MOAB/trunk/TagServer.cpp
===================================================================
--- MOAB/trunk/TagServer.cpp	2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/TagServer.cpp	2009-11-20 19:00:50 UTC (rev 3379)
@@ -223,37 +223,6 @@
 }
 
 
-//! set the value of a tag
-MBErrorCode TagServer::set_bits(const MBTag tag_handle, const MBEntityHandle entity_handle, unsigned char data )
-{
-  if(TYPE_FROM_HANDLE(entity_handle) >= MBMAXTYPE)
-    return MB_TYPE_OUT_OF_RANGE;
-  const TagInfo* info = get_tag_info( tag_handle );
-  if (!info)
-    return MB_TAG_NOT_FOUND;
-  return mBitServer->set_bits(ID_FROM_TAG_HANDLE(tag_handle), entity_handle, data,
-                              reinterpret_cast<const unsigned char*>(info->default_value()));
-}
-
-//! get the value of a tag
-MBErrorCode TagServer::get_bits(const MBTag tag_handle, const MBEntityHandle entity_handle, unsigned char& data )
-{
-  if(TYPE_FROM_HANDLE(entity_handle) >= MBMAXTYPE)
-    return MB_TYPE_OUT_OF_RANGE;
-  MBErrorCode rval = mBitServer->get_bits(ID_FROM_TAG_HANDLE(tag_handle), entity_handle, data);
-  if (MB_TAG_NOT_FOUND == rval) {
-    const TagInfo* info = get_tag_info( tag_handle );
-    if (!info)
-      return MB_FAILURE;
-    if (info->default_value())
-      data = *reinterpret_cast<const unsigned char*>(info->default_value());
-    else 
-      data = '\0';
-    return MB_SUCCESS;
-  }
-  return rval;    
-}
-
 MBErrorCode TagServer::set_mesh_data( const MBTag tag_handle,
                                       const void* data,
                                       int size )
@@ -301,12 +270,14 @@
       break;
       
     case MB_TAG_BIT:
-      if (num_entities == 1)
-        rval = sequenceManager->check_valid_entities( entity_handles, num_entities );
+      if (!(tag_info = get_tag_info( tag_id, tag_type )))
+        rval = MB_TAG_NOT_FOUND;
       else
-        rval = MB_FAILURE;
+        rval = sequenceManager->check_valid_entities( entity_handles, num_entities );
       if (MB_SUCCESS == rval)
-        rval = set_bits( tag_handle, *entity_handles, *reinterpret_cast<const unsigned char*>(data) );
+        rval= mBitServer->set_bits( tag_id, entity_handles, num_entities, 
+                                    reinterpret_cast<const unsigned char*>(data),
+                                    reinterpret_cast<const unsigned char*>(tag_info->default_value()));
       break;
     
     default:
@@ -340,12 +311,14 @@
       break;
     
     case MB_TAG_BIT:
-      if (entity_handles.size() == 1)
-        rval = sequenceManager->check_valid_entities( entity_handles );
+      if (!(tag_info = get_tag_info( tag_id, tag_type )))
+        rval = MB_TAG_NOT_FOUND;
       else
-        rval = MB_FAILURE;
+        rval = sequenceManager->check_valid_entities( entity_handles );
       if (MB_SUCCESS == rval)
-        rval = set_bits( tag_handle, entity_handles.front(), *reinterpret_cast<const unsigned char*>(data) );
+        rval= mBitServer->set_bits( tag_id, entity_handles, 
+                                    reinterpret_cast<const unsigned char*>(data),
+                                    reinterpret_cast<const unsigned char*>(tag_info->default_value()));
       break;
     
     default:
@@ -386,12 +359,7 @@
       break;
     
     case MB_TAG_BIT:
-      if (num_entities == 1)
-        rval = sequenceManager->check_valid_entities( entity_handles, num_entities );
-      else
-        rval = MB_FAILURE;
-      if (MB_SUCCESS == rval)
-        rval = set_bits( tag_handle, *entity_handles, *reinterpret_cast<const unsigned char*>(*data) );
+      rval = MB_FAILURE;
       break;
     
     default:
@@ -431,12 +399,7 @@
       break;
     
     case MB_TAG_BIT:
-      if (entity_handles.size() == 1)
-        rval = sequenceManager->check_valid_entities( entity_handles );
-      else
-        rval = MB_FAILURE;
-      if (MB_SUCCESS == rval)
-        rval = set_bits( tag_handle, entity_handles.front(), *reinterpret_cast<const unsigned char*>(*data) );
+      rval = MB_FAILURE;
       break;
     
     default:
@@ -517,11 +480,9 @@
     case MB_TAG_SPARSE:
       return mSparseData->get_data( tag_id, entity_handles, num_entities, data, default_val );
     case MB_TAG_BIT:
-      if (num_entities == 1)
-        return get_bits( tag_handle, *entity_handles, *reinterpret_cast<unsigned char*>(data) );
-      else
-        return MB_FAILURE;
-    
+      return mBitServer->get_bits( tag_id, entity_handles, num_entities, 
+                                   reinterpret_cast<unsigned char*>(data),
+                                   reinterpret_cast<const unsigned char*>(default_val));
     default:
       return MB_TAG_NOT_FOUND;
   }
@@ -543,11 +504,9 @@
     case MB_TAG_SPARSE:
       return mSparseData->get_data( tag_id, entity_handles, data, default_val );
     case MB_TAG_BIT:
-      if (entity_handles.size() == 1)
-        return get_bits( tag_handle, entity_handles.front(), *reinterpret_cast<unsigned char*>(data) );
-      else
-        return MB_FAILURE;
-    
+      return mBitServer->get_bits( tag_id, entity_handles,
+                                   reinterpret_cast<unsigned char*>(data),
+                                   reinterpret_cast<const unsigned char*>(default_val));
     default:
       return MB_TAG_NOT_FOUND;
   }
@@ -572,11 +531,7 @@
     case MB_TAG_SPARSE:
       return mSparseData->get_data( tag_id, entity_handles, num_entities, data, lengths, default_val, def_val_len );
     case MB_TAG_BIT:
-      if (num_entities == 1)
-        return get_bits( tag_handle, *entity_handles, *reinterpret_cast<unsigned char*>(data) );
-      else
-        return MB_FAILURE;
-    
+      return MB_FAILURE;
     default:
       return MB_TAG_NOT_FOUND;
   }
@@ -600,11 +555,7 @@
     case MB_TAG_SPARSE:
       return mSparseData->get_data( tag_id, entity_handles, data, lengths, default_val, def_val_len );
     case MB_TAG_BIT:
-      if (entity_handles.size() == 1)
-        return get_bits( tag_handle, entity_handles.front(), *reinterpret_cast<unsigned char*>(data) );
-      else
-        return MB_FAILURE;
-    
+      return MB_FAILURE;
     default:
       return MB_TAG_NOT_FOUND;
   }

Modified: MOAB/trunk/TagServer.hpp
===================================================================
--- MOAB/trunk/TagServer.hpp	2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/TagServer.hpp	2009-11-20 19:00:50 UTC (rev 3379)
@@ -222,13 +222,7 @@
                         const MBRange& entity_handles, 
                         const void** data,
                         int* lengths = 0 );
-  
-  //! set the value of a tag
-  MBErrorCode set_bits(const MBTag tag_handle, const MBEntityHandle entity_handle, unsigned char data );
 
-  //! get the value of a tag
-  MBErrorCode get_bits(const MBTag tag_handle, const MBEntityHandle entity_handle, unsigned char& data );
-
   //! remove global/mesh value of tag
   MBErrorCode remove_mesh_data( const MBTag tag_handle );
 

Modified: MOAB/trunk/WriteHDF5.cpp
===================================================================
--- MOAB/trunk/WriteHDF5.cpp	2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/WriteHDF5.cpp	2009-11-20 19:00:50 UTC (rev 3379)
@@ -1845,20 +1845,7 @@
     iter = stop;
     assert(range.size() == (unsigned)count);
  
- /** Fix me - stupid API requires we get these one at a time for BIT tags */
-    if (mb_type == MB_TAG_BIT)
-    {
-      rval = MB_SUCCESS;
-      char* buf_iter = tag_buffer;
-      for (MBRange::const_iterator it = range.begin(); 
-           MB_SUCCESS == rval && it != range.end(); 
-           ++it, buf_iter += mb_size)
-        rval = iFace->tag_get_data( tag_data.tag_id, &*it, 1, buf_iter );
-    }
-    else
-    {
-      rval = iFace->tag_get_data( tag_data.tag_id, range, tag_buffer );
-    }
+    rval = iFace->tag_get_data( tag_data.tag_id, range, tag_buffer );
     if (MB_SUCCESS != rval) {
       mhdf_closeData( filePtr, tables[1], &status );
       if (value_type && value_type != id_type)



More information about the moab-dev mailing list