1#ifndef DUNE_MULTIDOMAINGRID_SUBDOMAINSET_HH 
    2#define DUNE_MULTIDOMAINGRID_SUBDOMAINSET_HH 
   10#include <dune/common/typetraits.hh> 
   11#include <dune/common/iteratorfacades.hh> 
   12#include <dune/common/exceptions.hh> 
   14#include <dune/grid/multidomaingrid/utility.hh> 
   21template<
typename SubDomainIndex, std::
size_t capacity>
 
   22class IntegralTypeSubDomainSet;
 
   24template<
typename SubDomainIndex, std::
size_t capacity>
 
   25bool setContains(
const IntegralTypeSubDomainSet<SubDomainIndex,capacity>& a,
 
   26                 const IntegralTypeSubDomainSet<SubDomainIndex,capacity>& b);
 
   28template<
typename SubDomainIndex, std::
size_t capacity>
 
   29void setAdd(IntegralTypeSubDomainSet<SubDomainIndex,capacity>& a,
 
   30            const IntegralTypeSubDomainSet<SubDomainIndex,capacity>& b);
 
   43  struct Candidate<uint8_t> {
 
   45    typedef Candidate<uint16_t> next_candidate;
 
   50  struct Candidate<uint16_t> {
 
   51    typedef uint16_t type;
 
   52    typedef Candidate<uint32_t> next_candidate;
 
   57  struct Candidate<uint32_t> {
 
   58    typedef uint32_t type;
 
   59    typedef Candidate<uint64_t> next_candidate;
 
   64  struct Candidate<uint64_t> {
 
   65    typedef uint64_t type;
 
   66    typedef void next_candidate;
 
   70  template<std::
size_t capacity, 
typename cand
idate>
 
   71  struct SetStorageTester {
 
   73    static_assert(std::numeric_limits<typename candidate::type>::is_specialized,
"numeric_limits<> lacks specialization");
 
   75    typedef typename std::conditional<capacity <= static_cast<std::size_t>(std::numeric_limits<typename candidate::type>::digits),
 
   76                                 typename candidate::type,
 
   77                                 typename SetStorageTester<capacity,
 
   78                                                           typename candidate::next_candidate
 
   82    static_assert((!std::is_same<type,void>::value),
"unsupported maximum number of subdomains");
 
   89  template<std::
size_t capacity>
 
   90  struct SetStorageTester<capacity,void> {
 
   97  template<std::
size_t capacity>
 
   98  struct SetStorageChooser {
 
   99    typedef typename SetStorageTester<capacity,Candidate<uint8_t> >::type type;
 
  107    inline static std::size_t doCalculation(T value);
 
  111    inline static std::size_t calculate(T value) {
 
  112      assert(value != 0 && (value & (value-1)) == 0); 
 
  113      return doCalculation(value);
 
  119  inline std::size_t Log2<uint8_t>::doCalculation(uint8_t value) {
 
  120    return __builtin_ffs(value)-1;
 
  125  inline std::size_t Log2<uint16_t>::doCalculation(uint16_t value) {
 
  126    return __builtin_ffs(value)-1;
 
  131  inline std::size_t Log2<uint32_t>::doCalculation(uint32_t value) {
 
  132    return __builtin_ffsl(value)-1;
 
  137  inline std::size_t Log2<uint64_t>::doCalculation(uint64_t value) {
 
  138    return __builtin_ffsll(value)-1;
 
  142  template<
typename SubDomainIndex, 
typename SetStorage>
 
  143  class Iterator : 
public ForwardIteratorFacade<Iterator<SubDomainIndex,SetStorage>,
 
  148    template<
typename,std::
size_t>
 
  149    friend class ::Dune::mdgrid::IntegralTypeSubDomainSet;
 
  153    typedef Iterator<SubDomainIndex,SetStorage> ThisType;
 
  154    static const SetStorage base = 1;
 
  156    SubDomainIndex dereference()
 const {
 
  161    bool equals(
const ThisType& rhs)
 const {
 
  162      return _state == rhs._state;
 
  166      _state &= ~(base << _value);
 
  174    void findNextValue() {
 
  175      SetStorage lowestBit = _state & ((~_state) + 1);
 
  176      _value = Log2<SetStorage>::calculate(lowestBit);
 
  179    explicit Iterator(SetStorage state) :
 
  188    explicit Iterator() :
 
  194    SubDomainIndex _value;
 
  203template<
typename SubDomainIndexT, std::
size_t capacity>
 
  204class IntegralTypeSubDomainSet {
 
  206  friend bool setContains<>(
const IntegralTypeSubDomainSet<SubDomainIndexT,capacity>& a,
 
  207                          const IntegralTypeSubDomainSet<SubDomainIndexT,capacity>& b);
 
  209  friend void setAdd<>(IntegralTypeSubDomainSet<SubDomainIndexT,capacity>& a,
 
  210                     const IntegralTypeSubDomainSet<SubDomainIndexT,capacity>& b);
 
  212  typedef typename sds_detail::SetStorageChooser<capacity>::type SetStorage;
 
  213  static const SetStorage base = 1;
 
  216  static const std::size_t maxSize = capacity;
 
  217  typedef SubDomainIndexT SubDomainIndex;
 
  218  typedef sds_detail::Iterator<SubDomainIndex,SetStorage> Iterator;
 
  219  typedef IntegralTypeSubDomainSet<SubDomainIndex,capacity> This;
 
  223    typedef SetStorage DataType;
 
  225    static bool fixedSize(
int dim, 
int codim)
 
  230    static std::size_t size(
const IntegralTypeSubDomainSet& sds)
 
  235    template<
typename MessageBufferImp>
 
  236    static void gather(MessageBufferImp& buf, 
const IntegralTypeSubDomainSet& sds)
 
  241    template<
typename MessageBufferImp>
 
  242    static void scatter(MessageBufferImp& buf, IntegralTypeSubDomainSet& sds, std::size_t n)
 
  244      IntegralTypeSubDomainSet h;
 
  251  enum SetState {emptySet,simpleSet,multipleSet};
 
  253  Iterator begin()
 const {
 
  254    return Iterator(_set);
 
  257  Iterator end()
 const {
 
  261  bool contains(SubDomainIndex domain)
 const {
 
  262    assert(domain < maxSize);
 
  263    return (base << domain) & _set;
 
  266  template<
typename Set>
 
  267  bool containsAll(
const Set& set)
 const {
 
  268    return setContains(*
this,set);
 
  271  void difference(
const IntegralTypeSubDomainSet& minuend, 
const IntegralTypeSubDomainSet& subtrahend)
 
  273    _set = minuend._set & ~subtrahend._set;
 
  276  bool simple()
 const {
 
  277    return (!empty()) && ((_set & (_set - 1)) == 0);
 
  284  SetState state()
 const {
 
  285    return (_set == 0 ? emptySet : (_set & (_set - 1)) == 0 ? simpleSet : multipleSet);
 
  288  std::size_t size()
 const {
 
  290    for (SetStorage t = _set; t; ++c) {
 
  300  void add(SubDomainIndex domain) {
 
  301    assert(domain < maxSize);
 
  302    _set |= base << domain;
 
  305  void remove(SubDomainIndex domain) {
 
  306    assert(domain < maxSize);
 
  307    _set &= ~(base << domain);
 
  310  void set(SubDomainIndex domain) {
 
  311    assert(domain < maxSize);
 
  312    _set = base << domain;
 
  315  template<
typename Set>
 
  316  void addAll(
const Set& rhs) {
 
  320  int domainOffset(SubDomainIndex domain)
 const {
 
  321    assert(domain >= 0 && domain < maxSize);
 
  325  IntegralTypeSubDomainSet() :
 
  329  bool operator==(
const IntegralTypeSubDomainSet& r)
 const {
 
  330    return _set == r._set;
 
  333  bool operator!=(
const IntegralTypeSubDomainSet& r)
 const {
 
  334    return !operator==(r);
 
  343template<
typename A, 
typename B>
 
  344inline bool setContains(
const A& a, 
const B& b) {
 
  345  return std::all_of(b.begin(),b.end(),[&a](
decltype(*(b.begin())) i) { return a.contains(i); });
 
  348template<
typename A, 
typename B>
 
  349inline void setAdd(A& a, 
const B& b) {
 
  350  std::for_each(b.begin(),b.end(),[&a](
decltype(*(b.begin())) i) { a.add(i); });
 
  354template<
typename SubDomainIndex, std::
size_t capacity>
 
  355inline bool setContains(
const IntegralTypeSubDomainSet<SubDomainIndex,capacity>& a,
 
  356                        const IntegralTypeSubDomainSet<SubDomainIndex,capacity>& b) {
 
  357  return (a._set & b._set) == b._set;
 
  360template<
typename SubDomainIndex, std::
size_t capacity>
 
  361inline void setAdd(IntegralTypeSubDomainSet<SubDomainIndex,capacity>& a,
 
  362                   const IntegralTypeSubDomainSet<SubDomainIndex,capacity>& b) {