Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
moab::range_tool< pair_iter_t > Class Template Reference

Methods to insert/remove range-based data from contents list. Templatized to operate on both Range and set-based MeshSets. More...

Static Public Member Functions

static ErrorCode ranged_insert_entities (MeshSet::Count &count, MeshSet::CompactList &clist, pair_iter_t begin, pair_iter_t end, EntityHandle my_handle, AEntityFactory *adj)
 
static ErrorCode ranged_remove_entities (MeshSet::Count &count, MeshSet::CompactList &clist, pair_iter_t begin, pair_iter_t end, EntityHandle my_handle, AEntityFactory *adj)
 
static ErrorCode vector_insert_entities (MeshSet::Count &count, MeshSet::CompactList &clist, pair_iter_t begin, pair_iter_t end, EntityHandle my_handle, AEntityFactory *adj)
 

Detailed Description

template<typename pair_iter_t>
class moab::range_tool< pair_iter_t >

Methods to insert/remove range-based data from contents list. Templatized to operate on both Range and set-based MeshSets.

Definition at line 37 of file MeshSet.cpp.

Member Function Documentation

◆ ranged_insert_entities()

template<typename pair_iter_t >
ErrorCode moab::range_tool< pair_iter_t >::ranged_insert_entities ( MeshSet::Count count,
MeshSet::CompactList clist,
pair_iter_t  begin,
pair_iter_t  end,
EntityHandle  my_handle,
AEntityFactory adj 
)
inlinestatic

Insert range-based data into range-based MeshSet

Definition at line 441 of file MeshSet.cpp.

447 {
448  // first pass:
449  // 1) merge existing ranges
450  // 2) count number of new ranges that must be inserted
451  EntityHandle* list_ptr;
452  size_t list_size;
453  if( count < MeshSet::MANY )
454  {
455  list_ptr = clist.hnd;
456  list_size = count;
457  }
458  else
459  {
460  list_ptr = clist.ptr[0];
461  list_size = clist.ptr[1] - clist.ptr[0];
462  }
463 
464  MeshSetRange* list = reinterpret_cast< MeshSetRange* >( list_ptr );
465  assert( 0 == list_size % 2 );
466  assert( 2 * sizeof( EntityHandle ) == sizeof( MeshSetRange ) );
467  list_size /= 2;
468  MeshSetRange* const list_end = list + list_size;
469  MeshSetRange *list_read = list, *list_write = list;
470  pair_iter_t i = begin;
471 
472  // count number of range pairs that are straight insertions
473  // (don't overlap any range pair in the current set) that
474  // could not be inserted during the first pass.
475  size_t insert_count = 0;
476 
477  // merge lists
478  while( i != end )
479  {
480  // find first range that intersects the current input range
481 
482  // do binary search if no holes in current set contents
483  if( list_read == list_write )
484  {
485  // subtract one from i->first because if it is one greater
486  // then the the last value of some block, then we want that
487  // block to append to.
488  MeshSetRange tmp;
489  tmp.first = i->first - 1;
490  tmp.second = i->second;
491  list_write = std::lower_bound( list_read, list_end, tmp, MeshSetRComp() );
492  list_read = list_write;
493  }
494  // otherwise shift down until we find where we find a range block
495  // that intersects
496  else
497  while( list_read != list_end && list_read->second + 1 < i->first )
498  {
499  *list_write = *list_read;
500  ++list_write;
501  ++list_read;
502  }
503 
504  // handle any straight insertions of range blocks
505  for( ; i != end && ( list_read == list_end || i->second + 1 < list_read->first ); ++i )
506  {
507  // If we haven't removed any range pairs, we don't have space to
508  // insert here. Defer the insertion until later.
509  if( list_read == list_write )
510  {
511  ++insert_count;
512  }
513  else
514  {
515  if( adj )
516  for( EntityHandle j = i->first; j <= i->second; ++j )
517  adj->add_adjacency( j, my_handle, false );
518 
519  list_write->first = i->first;
520  list_write->second = i->second;
521  ++list_write;
522  }
523  }
524 
525  // merge all the stuff that gets merged into a single range pair
526  // from both the input list and the existing set data
527  if( list_read != list_end )
528  {
529  MeshSetRange working = *list_read; // copy because might be the same as list_write
530  ++list_read;
531 
532  // Check if we need to prepend to the existing block.
533  // We only need to check this for the first input range because
534  // after this working.first will always be the first possible handle
535  // in the merged set of ranges.
536  if( i != end && i->first < working.first && i->second + 1 >= working.first )
537  {
538  if( adj )
539  for( EntityHandle h = i->first; h < working.first; ++h )
540  adj->add_adjacency( h, my_handle, false );
541  working.first = i->first;
542  }
543 
544  // Now append from the input list and the remaining set contents
545  // until we've consolidated all overlapping/touching ranges.
546  bool done = false;
547  while( !done )
548  {
549  // does next set contents range touch working range?
550  bool set_overlap = list_read != list_end && list_read->first <= working.second + 1;
551  // does next input range touch working range?
552  bool inp_overlap = i != end && i->first <= working.second + 1;
553 
554  // if both ranges touch...
555  if( inp_overlap && set_overlap )
556  {
557  // if next set range is contained in working, skip it
558  if( list_read->second <= working.second ) ++list_read;
559  // if next input range is contained in working, skip it
560  else if( i->second <= working.second )
561  ++i;
562  // Otherwise set the working end to the smaller of the two
563  // ends: either the next set end or the next input end.
564  // We want the smaller of the two because the larger might
565  // intersect additional ranges in the other list.
566  else if( list_read->second <= i->second )
567  {
568  working.second = list_read->second;
569  ++list_read;
570  }
571  else
572  {
573  working.second = i->second;
574  ++i;
575  }
576  }
577  // If only the input range intersect the current working range...
578  else if( inp_overlap )
579  {
580  // Would it be more efficient to just extent 'working' to
581  // the end of the current input range? We'd end up adding
582  // adjacencies for for entities that are already in the tracking
583  // set and therefore already have the adjacency.
584  EntityHandle last = i->second;
585  if( list_read != list_end && list_read->first < last )
586  last = list_read->first - 1;
587  else
588  ++i;
589 
590  if( last > working.second )
591  {
592  if( adj )
593  for( EntityHandle h = working.second + 1; h <= last; ++h )
594  adj->add_adjacency( h, my_handle, false );
595 
596  working.second = last;
597  }
598  }
599  else if( set_overlap )
600  {
601  if( working.second < list_read->second ) working.second = list_read->second;
602  ++list_read;
603  }
604  else
605  {
606  done = true;
607  }
608  }
609 
610  assert( list_write < list_read );
611  *list_write = working;
612  ++list_write;
613  }
614  }
615 
616  // shuffle down entries to fill holes
617  if( list_read == list_write )
618  list_read = list_write = list_end;
619  else
620  while( list_read < list_end )
621  {
622  *list_write = *list_read;
623  ++list_read;
624  ++list_write;
625  }
626 
627  // adjust allocated array size
628  const size_t occupied_size = list_write - list;
629  const size_t new_list_size = occupied_size + insert_count;
630  list_ptr = resize_compact_list( count, clist, 2 * new_list_size );
631  // done?
632  if( !insert_count ) return MB_SUCCESS;
633  list = reinterpret_cast< MeshSetRange* >( list_ptr );
634 
635  // Second pass: insert non-mergable range pairs
636  // All range pairs in the input are either completely disjoint from
637  // the ones in the mesh set and must be inserted or are entirely contained
638  // within a range pair in the mesh set.
639  assert( begin != end ); // can't have items to insert if given empty input list
640  pair_iter_t ri = end;
641  --ri;
642  list_write = list + new_list_size - 1;
643  list_read = list + occupied_size - 1;
644  for( ; list_write >= list; --list_write )
645  {
646  if( list_read >= list )
647  {
648  while( ri->first >= list_read->first && ri->second <= list_read->second )
649  {
650  assert( ri != begin );
651  --ri;
652  }
653 
654  if( list_read->first > ri->second )
655  {
656  *list_write = *list_read;
657  --list_read;
658  continue;
659  }
660  }
661 
662  assert( insert_count > 0 );
663  if( adj )
664  for( EntityHandle h = ri->first; h <= ri->second; ++h )
665  adj->add_adjacency( h, my_handle, false );
666  list_write->first = ri->first;
667  list_write->second = ri->second;
668 
669  // don't have reverse iterator, so check before decrement
670  // if insert_count isn't zero, must be more in range
671  if( 0 == --insert_count )
672  {
673  assert( list_read == list_write - 1 );
674  break;
675  }
676  else
677  {
678  --ri;
679  }
680  }
681 
682  assert( !insert_count );
683  return MB_SUCCESS;
684 }

References moab::AEntityFactory::add_adjacency(), moab::MeshSet::CompactList::hnd, moab::MeshSet::MANY, MB_SUCCESS, moab::MeshSet::CompactList::ptr, and moab::resize_compact_list().

Referenced by moab::MeshSet::insert_entity_vector().

◆ ranged_remove_entities()

template<typename pair_iter_t >
ErrorCode moab::range_tool< pair_iter_t >::ranged_remove_entities ( MeshSet::Count count,
MeshSet::CompactList clist,
pair_iter_t  begin,
pair_iter_t  end,
EntityHandle  my_handle,
AEntityFactory adj 
)
inlinestatic

Remove range-based data from range-based MeshSet

Definition at line 687 of file MeshSet.cpp.

693 {
694  // first pass:
695  // 1) remove (from) existing ranges
696  // 2) count number of ranges that must be split
697  ptrdiff_t split_count = 0;
698  EntityHandle* list;
699  size_t list_size;
700  if( count < MeshSet::MANY )
701  {
702  list = clist.hnd;
703  list_size = count;
704  }
705  else
706  {
707  list = clist.ptr[0];
708  list_size = clist.ptr[1] - clist.ptr[0];
709  }
710 
711  EntityHandle* list_write = list;
712  EntityHandle *const list_end = list + list_size, *list_read = list;
713  pair_iter_t i = begin;
714 
715  while( list_read != list_end && i != end )
716  {
717 
718  while( i != end && i->second < list_read[0] )
719  ++i;
720  if( i == end ) break;
721 
722  // if there are holes in the current array, shuffle blocks
723  // down until we find the next block to remove
724  if( list_read != list_write )
725  {
726  while( list_read != list_end && i->second < list_read[0] )
727  {
728  list_write[0] = list_read[0];
729  list_write[1] = list_read[1];
730  list_write += 2;
731  list_read += 2;
732  }
733  }
734  // otherwise do a binary search
735  else
736  {
737  list_write = std::lower_bound( list_write, list_end, i->first );
738  // if in middle of range block (odd index), back up to start of block
739  list_write -= ( list_write - list ) % 2;
740  list_read = list_write;
741  }
742 
743  // if everything remaning is past end of set contents...
744  if( list_read == list_end ) break;
745 
746  // skip any remove pairs that aren't in the list
747  if( i->second < list_read[0] )
748  {
749  ++i;
750  continue;
751  }
752 
753  // Begin by assuming that we will keep the entire block
754  list_write[0] = list_read[0];
755  list_write[1] = list_read[1];
756  list_read += 2;
757 
758  for( ; i != end && i->first <= list_write[1]; ++i )
759  {
760  if( i->first <= list_write[0] )
761  {
762  // remove whole block
763  if( i->second >= list_write[1] )
764  {
765  if( adj )
766  for( EntityHandle h = list_write[0]; h <= list_write[1]; ++h )
767  adj->remove_adjacency( h, my_handle );
768  list_write -= 2;
769  break;
770  }
771  // remove from start of block
772  else if( i->second >= list_write[0] )
773  {
774  if( adj )
775  for( EntityHandle h = list_write[0]; h <= i->second; ++h )
776  adj->remove_adjacency( h, my_handle );
777  list_write[0] = i->second + 1;
778  }
779  }
780  else if( i->first <= list_write[1] )
781  {
782  // remove from end of block
783  if( i->second >= list_write[1] )
784  {
785  if( adj )
786  for( EntityHandle h = i->first; h <= list_write[1]; ++h )
787  adj->remove_adjacency( h, my_handle );
788  list_write[1] = i->first - 1;
789  // list_write += 2;
790  break;
791  }
792  // split block
793  else
794  {
795  if( adj )
796  for( EntityHandle h = i->first; h <= i->second; ++h )
797  adj->remove_adjacency( h, my_handle );
798 
799  if( list_read - list_write <= 2 )
800  {
801  ++split_count;
802  continue;
803  }
804  else
805  {
806  list_write[3] = list_write[1];
807  list_write[1] = i->first - 1;
808  list_write[2] = i->second + 1;
809  list_write += 2;
810  }
811  }
812  }
813  }
814  list_write += 2;
815  }
816 
817  // shuffle down entries to fill holes
818  if( list_read == list_write )
819  list_read = list_write = list_end;
820  else
821  while( list_read < list_end )
822  {
823  list_write[0] = list_read[0];
824  list_write[1] = list_read[1];
825  list_read += 2;
826  list_write += 2;
827  }
828 
829  // adjust allocated array size
830  const size_t occupied_size = list_write - list;
831  const size_t new_list_size = occupied_size + 2 * split_count;
832  list = resize_compact_list( count, clist, new_list_size );
833  // done?
834  if( !split_count ) return MB_SUCCESS;
835 
836  // Second pass: split range pairs
837  // All range pairs in the input are either already removed or
838  // require one of the existing range pairs to be split
839  assert( begin != end ); // can't have ranges to split if given empty input list
840  pair_iter_t ri = end;
841  --ri;
842  list_write = list + new_list_size - 2;
843  list_read = list + occupied_size - 2;
844  for( ; list_write >= list; list_write -= 2 )
845  {
846  if( list_read >= list )
847  {
848  while( ri->second > list_read[1] )
849  {
850  assert( ri != begin );
851  --ri;
852  }
853 
854  if( list_read[0] > ri->second )
855  {
856  list_write[0] = list_read[0];
857  list_write[1] = list_read[1];
858  list_read -= 2;
859  continue;
860  }
861  }
862 
863  assert( split_count > 0 );
864  list_write[0] = ri->second + 1;
865  list_write[1] = list_read[1];
866  list_read[1] = ri->first - 1;
867 
868  // don't have reverse iterator, so check before decrement
869  // if insert_count isn't zero, must be more in range
870  if( 0 == --split_count )
871  {
872  assert( list_read == list_write - 2 );
873  break;
874  }
875  else
876  {
877  --ri;
878  }
879  }
880 
881  assert( !split_count );
882  return MB_SUCCESS;
883 }

References moab::MeshSet::CompactList::hnd, moab::MeshSet::MANY, MB_SUCCESS, moab::MeshSet::CompactList::ptr, moab::AEntityFactory::remove_adjacency(), and moab::resize_compact_list().

Referenced by moab::MeshSet::remove_entity_ranges(), and moab::MeshSet::remove_entity_vector().

◆ vector_insert_entities()

template<typename pair_iter_t >
ErrorCode moab::range_tool< pair_iter_t >::vector_insert_entities ( MeshSet::Count count,
MeshSet::CompactList clist,
pair_iter_t  begin,
pair_iter_t  end,
EntityHandle  my_handle,
AEntityFactory adj 
)
inlinestatic

Insert range-based data into list-based MeshSet

Definition at line 886 of file MeshSet.cpp.

892 {
893  const size_t init_size = count < MeshSet::MANY ? (int)count : clist.ptr[1] - clist.ptr[0];
894  size_t add_size = 0;
895  for( pair_iter_t i = begin; i != end; ++i )
896  add_size += i->second - i->first + 1;
897  EntityHandle* list = resize_compact_list( count, clist, init_size + add_size );
898  EntityHandle* li = list + init_size;
899 
900  for( pair_iter_t i = begin; i != end; ++i )
901  {
902  for( EntityHandle h = i->first; h <= i->second; ++h )
903  {
904  if( adj ) adj->add_adjacency( h, my_handle, false );
905  *li = h;
906  ++li;
907  }
908  }
909 
910  return MB_SUCCESS;
911 }

References moab::AEntityFactory::add_adjacency(), moab::MeshSet::MANY, MB_SUCCESS, moab::MeshSet::CompactList::ptr, and moab::resize_compact_list().

Referenced by moab::MeshSet::insert_entity_ranges().


The documentation for this class was generated from the following file: