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) {