this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Mikael Lagerkvist <lagerkvist@gecode.org>
5 *
6 * Contributing authors:
7 * Linnea Ingmar <linnea.ingmar@hotmail.com>
8 * Christian Schulte <schulte@gecode.org>
9 *
10 * Copyright:
11 * Linnea Ingmar, 2017
12 * Mikael Lagerkvist, 2007
13 * Christian Schulte, 2007
14 *
15 * This file is part of Gecode, the generic constraint
16 * development environment:
17 * http://www.gecode.org
18 *
19 * Permission is hereby granted, free of charge, to any person obtaining
20 * a copy of this software and associated documentation files (the
21 * "Software"), to deal in the Software without restriction, including
22 * without limitation the rights to use, copy, modify, merge, publish,
23 * distribute, sublicense, and/or sell copies of the Software, and to
24 * permit persons to whom the Software is furnished to do so, subject to
25 * the following conditions:
26 *
27 * The above copyright notice and this permission notice shall be
28 * included in all copies or substantial portions of the Software.
29 *
30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 *
38 */
39
40#include <climits>
41
42#ifdef _MSC_VER
43
44#include <intrin.h>
45
46#if defined(_M_IX86)
47#pragma intrinsic(_BitScanForward)
48#pragma intrinsic(__popcnt)
49#define GECODE_SUPPORT_MSVC_32
50#endif
51
52#if defined(_M_X64) || defined(_M_IA64)
53#pragma intrinsic(_BitScanForward64)
54#pragma intrinsic(__popcnt64)
55#define GECODE_SUPPORT_MSVC_64
56#endif
57
58#endif
59
60namespace Gecode { namespace Support {
61
62 class RawBitSetBase;
63
64 /// Date item for bitsets
65 class BitSetData {
66 friend class RawBitSetBase;
67 protected:
68#if defined(GECODE_SUPPORT_MSVC_32)
69 /// Basetype for bits
70 typedef unsigned long int Base;
71#else
72 /// Basetype for bits
73 typedef unsigned long long int Base;
74#endif
75 /// The bits
76 Base bits;
77 public:
78 /// Bits per base
79 static const unsigned int bpb =
80 static_cast<unsigned int>(CHAR_BIT * sizeof(Base));
81 /// Initialize with all bits set if \a setbits
82 void init(bool setbits=false);
83 /// Get number of data elements for \a s bits
84 static unsigned int data(unsigned int s);
85 /// Test wether any bit with position greater or equal to \a i is set
86 bool operator ()(unsigned int i=0U) const;
87 /// Access value at bit \a i
88 bool get(unsigned int i) const;
89 /// Set bit \a i
90 void set(unsigned int i);
91 /// Clear bit \a i
92 void clear(unsigned int i);
93 /// Return next set bit with position greater or equal to \a i (there must be a bit)
94 unsigned int next(unsigned int i=0U) const;
95 /// Whether all bits are set
96 bool all(void) const;
97 /// Whether all bits from bit 0 to bit \a i are set
98 bool all(unsigned int i) const;
99 /// Whether no bits are set
100 bool none(void) const;
101 /// Whether no bits from bit 0 to bit \a i are set
102 bool none(unsigned int i) const;
103 /// Return the number of bits set
104 unsigned int ones(void) const;
105 /// Return the number of bits not set
106 unsigned int zeroes(void) const;
107 /// Check whether exactly one bit is set
108 bool one(void) const;
109 /// Perform "and" with \a a
110 void a(BitSetData a);
111 /// Perform "and" with \a a for bits 0 to \a i
112 void a(BitSetData a, unsigned int i);
113 /// Return "and" of \a a and \a b
114 static BitSetData a(BitSetData a, BitSetData b);
115 /// Perform "or" with \a a
116 void o(BitSetData a);
117 /// Perform "or" with \a a for bits 0 to \a i
118 void o(BitSetData a, unsigned int i);
119 /// Return "or" of \a a and \a b
120 static BitSetData o(BitSetData a, BitSetData b);
121 /// Check if bits are the same as for \a a
122 bool operator ==(BitSetData a) const;
123 /// Check if bits are not the same as for \a a
124 bool operator !=(BitSetData a) const;
125 /// Invert all bits in \a b
126 BitSetData operator ~(void) const;
127 };
128
129 /// Status of a bitset
130 enum BitSetStatus {
131 BSS_NONE, ///< No bits set
132 BSS_ALL, ///< All bits set
133 BSS_SOME ///< Some but not all bits set
134 };
135
136 /// Basic bitset support (without stored size information)
137 class RawBitSetBase {
138 protected:
139 /// Bits per base
140 static const unsigned int bpb = BitSetData::bpb;
141 /// Stored bits
142 BitSetData* data;
143 private:
144 /// Copy constructor (disabled)
145 RawBitSetBase(const RawBitSetBase&);
146 /// Assignment operator (disabled)
147 RawBitSetBase& operator =(const RawBitSetBase&);
148 public:
149 /// Default constructor (yields empty set)
150 RawBitSetBase(void);
151 /// Initialize for \a sz bits and allocator \a a
152 template<class A>
153 RawBitSetBase(A& a, unsigned int sz, bool setbits=false);
154 /// Copy from bitset \a bs with allocator \a a
155 template<class A>
156 RawBitSetBase(A& a, unsigned int sz, const RawBitSetBase& bs);
157 /// Allocate for \a sz bits and allocator \a a (only after default constructor)
158 template<class A>
159 void allocate(A& a, unsigned int sz);
160 /// Initialize for \a sz bits and allocator \a a (only after default constructor)
161 template<class A>
162 void init(A& a, unsigned int sz, bool setbits=false);
163 /// Clear \a sz bits
164 void clearall(unsigned int sz, bool setbits=false);
165 /// Copy \a sz bits from \a bs
166 void copy(unsigned int sz, const RawBitSetBase& bs);
167 /// Access value at bit \a i
168 bool get(unsigned int i) const;
169 /// Set bit \a i
170 void set(unsigned int i);
171 /// Clear bit \a i
172 void clear(unsigned int i);
173 /// Return position greater or equal \a i of next set bit (\a i is allowed to be equal to size)
174 unsigned int next(unsigned int i) const;
175 /// Return status of bitset
176 BitSetStatus status(unsigned int sz) const;
177 /// Test whether all bits are set
178 bool all(unsigned int sz) const;
179 /// Test whether no bits are set
180 bool none(unsigned int sz) const;
181 /// Resize bitset from \a sz to \a n elememts
182 template<class A>
183 void resize(A& a, unsigned int sz, unsigned int n, bool setbits=false);
184 /// Dispose memory for bit set
185 template<class A>
186 void dispose(A& a, unsigned int sz);
187 };
188
189 /// Basic bitset support
190 class BitSetBase : public RawBitSetBase {
191 protected:
192 /// Size of bitset (number of bits)
193 unsigned int sz;
194 private:
195 /// Copy constructor (disabled)
196 BitSetBase(const BitSetBase&);
197 /// Assignment operator (disabled)
198 BitSetBase& operator =(const BitSetBase&);
199 public:
200 /// Default constructor (yields empty set)
201 BitSetBase(void);
202 /// Initialize for \a s bits and allocator \a a
203 template<class A>
204 BitSetBase(A& a, unsigned int s, bool setbits=false);
205 /// Copy from bitset \a bs with allocator \a a
206 template<class A>
207 BitSetBase(A& a, const BitSetBase& bs);
208 /// Initialize for \a s bits and allocator \a a (only after default constructor)
209 template<class A>
210 void init(A& a, unsigned int s, bool setbits=false);
211 /// Clear \a sz bits
212 void clearall(bool setbits=false);
213 /// Copy \a sz bits from \a bs
214 void copy(const BitSetBase& bs);
215 /// Return size of bitset (number of bits)
216 unsigned int size(void) const;
217 /// Access value at bit \a i
218 bool get(unsigned int i) const;
219 /// Set bit \a i
220 void set(unsigned int i);
221 /// Clear bit \a i
222 void clear(unsigned int i);
223 /// Return position greater or equal \a i of next set bit (\a i is allowed to be equal to size)
224 unsigned int next(unsigned int i) const;
225 /// Return status of bitset
226 BitSetStatus status(void) const;
227 /// Test whether all bits are set
228 bool all(void) const;
229 /// Test whether no bits are set
230 bool none(void) const;
231 /// Resize bitset to \a n elememts
232 template<class A>
233 void resize(A& a, unsigned int n, bool setbits=false);
234 /// Dispose memory for bit set
235 template<class A>
236 void dispose(A& a);
237 };
238
239
240 /*
241 * Bitset data
242 *
243 */
244
245 forceinline void
246 BitSetData::init(bool setbits) {
247 bits = setbits ? ~static_cast<Base>(0) : static_cast<Base>(0);
248 }
249 forceinline unsigned int
250 BitSetData::data(unsigned int s) {
251 return s == 0 ? 0 : ((s-1) / bpb + 1);
252 }
253 forceinline bool
254 BitSetData::operator ()(unsigned int i) const {
255 return (bits >> i) != static_cast<Base>(0U);
256 }
257 forceinline bool
258 BitSetData::get(unsigned int i) const {
259 return (bits & (static_cast<Base>(1U) << i)) != static_cast<Base>(0U);
260 }
261 forceinline void
262 BitSetData::set(unsigned int i) {
263 bits |= (static_cast<Base>(1U) << i);
264 }
265 forceinline void
266 BitSetData::clear(unsigned int i) {
267 bits &= ~(static_cast<Base>(1U) << i);
268 }
269 forceinline unsigned int
270 BitSetData::next(unsigned int i) const {
271 assert(bits != static_cast<Base>(0));
272#if defined(GECODE_SUPPORT_MSVC_32)
273 assert(bpb == 32);
274 unsigned long int p;
275 _BitScanForward(&p,bits >> i);
276 return static_cast<unsigned int>(p)+i;
277#elif defined(GECODE_SUPPORT_MSVC_64)
278 assert(bpb == 64);
279 unsigned long int p;
280 _BitScanForward64(&p,bits >> i);
281 return static_cast<unsigned int>(p)+i;
282#elif defined(GECODE_HAS_BUILTIN_FFSLL)
283 if (bpb == 64) {
284 int p = __builtin_ffsll(bits >> i);
285 assert(p > 0);
286 return static_cast<unsigned int>(p-1)+i;
287 }
288#else
289 while (!get(i)) i++;
290 return i;
291#endif
292 }
293 forceinline bool
294 BitSetData::all(void) const {
295 return bits == ~static_cast<Base>(0U);
296 }
297 forceinline bool
298 BitSetData::all(unsigned int i) const {
299 const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
300 return (bits & mask) == mask;
301 }
302 forceinline bool
303 BitSetData::none(void) const {
304 return bits == static_cast<Base>(0U);
305 }
306 forceinline bool
307 BitSetData::none(unsigned int i) const {
308 const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
309 return (bits & mask) == static_cast<Base>(0U);
310 }
311
312 forceinline unsigned int
313 BitSetData::ones(void) const {
314#if defined(GECODE_SUPPORT_MSVC_32)
315 assert(bpb == 32);
316 return static_cast<unsigned int>(__popcnt(bits));
317#elif defined(GECODE_SUPPORT_MSVC_64)
318 assert(bpb == 64);
319 return static_cast<unsigned int>(__popcnt64(bits));
320#elif defined(GECODE_HAS_BUILTIN_POPCOUNTLL)
321 if (bpb == 64)
322 return static_cast<unsigned int>(__builtin_popcountll(bits));
323#else
324 const unsigned long long int m1 = 0x5555555555555555;
325 const unsigned long long int m2 = 0x3333333333333333;
326 const unsigned long long int m4 = 0x0f0f0f0f0f0f0f0f;
327 unsigned long long int b = bits;
328 b -= (b >> 1) & m1;
329 b = (b & m2) + ((b >> 2) & m2);
330 b = (b + (b >> 4)) & m4;
331 b += b >> 8; b += b >> 16; b += b >> 32;
332 return static_cast<unsigned int>(b & 0x7f);
333#endif
334 }
335 forceinline unsigned int
336 BitSetData::zeroes(void) const {
337 return bpb - ones();
338 }
339 forceinline bool
340 BitSetData::one(void) const {
341 return (bits & (bits - static_cast<Base>(1U))) ==
342 static_cast<Base>(0U);
343 }
344
345 forceinline void
346 BitSetData::a(BitSetData a) {
347 bits &= a.bits;
348 }
349 forceinline void
350 BitSetData::a(BitSetData a, unsigned int i) {
351 const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
352 bits &= (a.bits & mask);
353 }
354 forceinline BitSetData
355 BitSetData::a(BitSetData a, BitSetData b) {
356 BitSetData ab;
357 ab.bits = a.bits & b.bits;
358 return ab;
359 }
360
361 forceinline void
362 BitSetData::o(BitSetData a) {
363 bits |= a.bits;
364 }
365 forceinline void
366 BitSetData::o(BitSetData a, unsigned int i) {
367 const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
368 bits |= (a.bits & mask);
369 }
370 forceinline BitSetData
371 BitSetData::o(BitSetData a, BitSetData b) {
372 BitSetData ab;
373 ab.bits = a.bits | b.bits;
374 return ab;
375 }
376
377 forceinline BitSetData
378 BitSetData::operator ~(void) const {
379 BitSetData iv;
380 iv.bits = ~bits;
381 return iv;
382 }
383 forceinline bool
384 BitSetData::operator ==(BitSetData a) const {
385 return bits == a.bits;
386 }
387 forceinline bool
388 BitSetData::operator !=(BitSetData a) const {
389 return bits != a.bits;
390 }
391
392
393 /*
394 * Basic bit sets
395 *
396 */
397
398 forceinline bool
399 RawBitSetBase::get(unsigned int i) const {
400 return data[i / bpb].get(i % bpb);
401 }
402 forceinline void
403 RawBitSetBase::set(unsigned int i) {
404 data[i / bpb].set(i % bpb);
405 }
406 forceinline void
407 RawBitSetBase::clear(unsigned int i) {
408 data[i / bpb].clear(i % bpb);
409 }
410
411 template<class A>
412 void
413 RawBitSetBase::resize(A& a, unsigned int sz, unsigned int n, bool setbits) {
414 if (n>sz) {
415 data = a.template realloc<BitSetData>(data,BitSetData::data(sz+1),
416 BitSetData::data(n+1));
417 for (unsigned int i=BitSetData::data(sz)+1;
418 i<BitSetData::data(n+1); i++) {
419 data[i].init(setbits);
420 }
421 for (unsigned int i=(sz%bpb); i<bpb; i++)
422 if (setbits)
423 data[sz / bpb].set(i);
424 else
425 data[sz / bpb].clear(i);
426 }
427 set(n);
428 }
429
430 template<class A>
431 forceinline void
432 RawBitSetBase::dispose(A& a, unsigned int sz) {
433 a.template free<BitSetData>(data,BitSetData::data(sz+1));
434 }
435
436 forceinline
437 RawBitSetBase::RawBitSetBase(void)
438 : data(nullptr) {}
439
440 template<class A>
441 forceinline
442 RawBitSetBase::RawBitSetBase(A& a, unsigned int sz, bool setbits)
443 : data(a.template alloc<BitSetData>(BitSetData::data(sz+1))) {
444 for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
445 data[i].init(setbits);
446 // Set a bit at position sz as sentinel (for efficient next)
447 set(sz);
448 }
449
450 template<class A>
451 forceinline
452 RawBitSetBase::RawBitSetBase(A& a, unsigned int sz, const RawBitSetBase& bs)
453 : data(a.template alloc<BitSetData>(BitSetData::data(sz+1))) {
454 for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
455 data[i] = bs.data[i];
456 // Set a bit at position sz as sentinel (for efficient next)
457 set(sz);
458 }
459
460 template<class A>
461 forceinline void
462 RawBitSetBase::allocate(A& a, unsigned int sz) {
463 assert(data == nullptr);
464 data=a.template alloc<BitSetData>(BitSetData::data(sz+1));
465 }
466
467 template<class A>
468 forceinline void
469 RawBitSetBase::init(A& a, unsigned int sz, bool setbits) {
470 assert(data == nullptr);
471 data=a.template alloc<BitSetData>(BitSetData::data(sz+1));
472 for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
473 data[i].init(setbits);
474 // Set a bit at position sz as sentinel (for efficient next)
475 set(sz);
476 }
477
478 forceinline void
479 RawBitSetBase::copy(unsigned int sz, const RawBitSetBase& bs) {
480 for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
481 data[i] = bs.data[i];
482 }
483
484 forceinline void
485 RawBitSetBase::clearall(unsigned int sz, bool setbits) {
486 for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
487 data[i].init(setbits);
488 }
489
490 forceinline unsigned int
491 RawBitSetBase::next(unsigned int i) const {
492 unsigned int pos = i / bpb;
493 unsigned int bit = i % bpb;
494 if (data[pos](bit))
495 return pos * bpb + data[pos].next(bit);
496 // The sentinel bit guarantees that this loop always terminates
497 do {
498 pos++;
499 } while (!data[pos]());
500 return pos * bpb + data[pos].next();
501 }
502
503 forceinline BitSetStatus
504 RawBitSetBase::status(unsigned int sz) const {
505 unsigned int pos = sz / bpb;
506 unsigned int bits = sz % bpb;
507 if (pos > 0) {
508 if (data[0].all()) {
509 for (unsigned int i=1; i<pos; i++)
510 if (!data[i].all())
511 return BSS_SOME;
512 return data[pos].all(bits) ? BSS_ALL : BSS_SOME;
513 } else if (data[0].none()) {
514 for (unsigned int i=1; i<pos; i++)
515 if (!data[i].none())
516 return BSS_SOME;
517 return data[pos].none(bits) ? BSS_NONE : BSS_SOME;
518 } else {
519 return BSS_SOME;
520 }
521 }
522 if (data[0].all(bits))
523 return BSS_ALL;
524 if (data[0].none(bits))
525 return BSS_NONE;
526 return BSS_SOME;
527 }
528
529 forceinline bool
530 RawBitSetBase::all(unsigned int sz) const {
531 return status(sz) == BSS_ALL;
532 }
533
534 forceinline bool
535 RawBitSetBase::none(unsigned int sz) const {
536 return status(sz) == BSS_NONE;
537 }
538
539
540 template<class A>
541 void
542 BitSetBase::resize(A& a, unsigned int n, bool setbits) {
543 RawBitSetBase::resize(a,sz,n,setbits); sz=n;
544 }
545
546 template<class A>
547 forceinline void
548 BitSetBase::dispose(A& a) {
549 RawBitSetBase::dispose(a,sz);
550 }
551
552 forceinline
553 BitSetBase::BitSetBase(void)
554 : sz(0U) {}
555
556 template<class A>
557 forceinline
558 BitSetBase::BitSetBase(A& a, unsigned int s, bool setbits)
559 : RawBitSetBase(a,s,setbits), sz(s) {}
560
561 template<class A>
562 forceinline
563 BitSetBase::BitSetBase(A& a, const BitSetBase& bs)
564 : RawBitSetBase(a,bs.sz,bs), sz(bs.sz) {}
565
566 template<class A>
567 forceinline void
568 BitSetBase::init(A& a, unsigned int s, bool setbits) {
569 assert(sz == 0);
570 RawBitSetBase::init(a,s,setbits); sz=s;
571 }
572
573 forceinline void
574 BitSetBase::copy(const BitSetBase& bs) {
575 assert(sz == bs.sz);
576 RawBitSetBase::copy(sz,bs);
577 }
578
579 forceinline void
580 BitSetBase::clearall(bool setbits) {
581 RawBitSetBase::clearall(sz,setbits);
582 }
583
584 forceinline unsigned int
585 BitSetBase::size(void) const {
586 return sz;
587 }
588
589 forceinline bool
590 BitSetBase::get(unsigned int i) const {
591 assert(i < sz);
592 return RawBitSetBase::get(i);
593 }
594 forceinline void
595 BitSetBase::set(unsigned int i) {
596 assert(i < sz);
597 RawBitSetBase::set(i);
598 }
599 forceinline void
600 BitSetBase::clear(unsigned int i) {
601 assert(i < sz);
602 RawBitSetBase::clear(i);
603 }
604
605 forceinline unsigned int
606 BitSetBase::next(unsigned int i) const {
607 assert(i <= sz);
608 return RawBitSetBase::next(i);
609 }
610
611 forceinline BitSetStatus
612 BitSetBase::status(void) const {
613 return RawBitSetBase::status(sz);
614 }
615
616 forceinline bool
617 BitSetBase::all(void) const {
618 return RawBitSetBase::all(sz);
619 }
620
621 forceinline bool
622 BitSetBase::none(void) const {
623 return RawBitSetBase::none(sz);
624 }
625
626}}
627
628#ifdef GECODE_SUPPORT_MSVC_32
629#undef GECODE_SUPPORT_MSVC_32
630#endif
631#ifdef GECODE_SUPPORT_MSVC_64
632#undef GECODE_SUPPORT_MSVC_64
633#endif
634
635// STATISTICS: support-any