a88e6349254dd30269447b34ec587d7136124007
[folly.git] / folly / Bits.h
1 /*
2  * Copyright 2012 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * Various low-level, bit-manipulation routines.
19  *
20  * findFirstSet(x)  [constexpr]
21  *    find first (least significant) bit set in a value of an integral type,
22  *    1-based (like ffs()).  0 = no bits are set (x == 0)
23  *
24  * findLastSet(x)  [constexpr]
25  *    find last (most significant) bit set in a value of an integral type,
26  *    1-based.  0 = no bits are set (x == 0)
27  *    for x != 0, findLastSet(x) == 1 + floor(log2(x))
28  *
29  * nextPowTwo(x)  [constexpr]
30  *    Finds the next power of two >= x.
31  *
32  * isPowTwo(x)  [constexpr]
33  *    return true iff x is a power of two
34  *
35  * popcount(x)
36  *    return the number of 1 bits in x
37  *
38  * Endian
39  *    convert between native, big, and little endian representation
40  *    Endian::big(x)      big <-> native
41  *    Endian::little(x)   little <-> native
42  *    Endian::swap(x)     big <-> little
43  *
44  * BitIterator
45  *    Wrapper around an iterator over an integral type that iterates
46  *    over its underlying bits in MSb to LSb order
47  *
48  * findFirstSet(BitIterator begin, BitIterator end)
49  *    return a BitIterator pointing to the first 1 bit in [begin, end), or
50  *    end if all bits in [begin, end) are 0
51  *
52  * @author Tudor Bosman (tudorb@fb.com)
53  */
54
55 #ifndef FOLLY_BITS_H_
56 #define FOLLY_BITS_H_
57
58 #include "folly/Portability.h"
59
60 #ifndef _GNU_SOURCE
61 #define _GNU_SOURCE 1
62 #endif
63
64 #ifndef __GNUC__
65 #error GCC required
66 #endif
67
68 #include "folly/detail/BitsDetail.h"
69 #include "folly/detail/BitIteratorDetail.h"
70 #include "folly/Likely.h"
71
72 #include <byteswap.h>
73 #include <cassert>
74 #include <cinttypes>
75 #include <endian.h>
76 #include <iterator>
77 #include <limits>
78 #include <type_traits>
79 #include <boost/iterator/iterator_adaptor.hpp>
80 #include <stdint.h>
81
82 namespace folly {
83
84 // Generate overloads for findFirstSet as wrappers around
85 // appropriate ffs, ffsl, ffsll gcc builtins
86 template <class T>
87 inline constexpr
88 typename std::enable_if<
89   (std::is_integral<T>::value &&
90    std::is_unsigned<T>::value &&
91    sizeof(T) <= sizeof(unsigned int)),
92   unsigned int>::type
93   findFirstSet(T x) {
94   return __builtin_ffs(x);
95 }
96
97 template <class T>
98 inline constexpr
99 typename std::enable_if<
100   (std::is_integral<T>::value &&
101    std::is_unsigned<T>::value &&
102    sizeof(T) > sizeof(unsigned int) &&
103    sizeof(T) <= sizeof(unsigned long)),
104   unsigned int>::type
105   findFirstSet(T x) {
106   return __builtin_ffsl(x);
107 }
108
109 template <class T>
110 inline constexpr
111 typename std::enable_if<
112   (std::is_integral<T>::value &&
113    std::is_unsigned<T>::value &&
114    sizeof(T) > sizeof(unsigned long) &&
115    sizeof(T) <= sizeof(unsigned long long)),
116   unsigned int>::type
117   findFirstSet(T x) {
118   return __builtin_ffsll(x);
119 }
120
121 template <class T>
122 inline constexpr
123 typename std::enable_if<
124   (std::is_integral<T>::value && std::is_signed<T>::value),
125   unsigned int>::type
126   findFirstSet(T x) {
127   // Note that conversion from a signed type to the corresponding unsigned
128   // type is technically implementation-defined, but will likely work
129   // on any impementation that uses two's complement.
130   return findFirstSet(static_cast<typename std::make_unsigned<T>::type>(x));
131 }
132
133 // findLastSet: return the 1-based index of the highest bit set
134 // for x > 0, findLastSet(x) == 1 + floor(log2(x))
135 template <class T>
136 inline constexpr
137 typename std::enable_if<
138   (std::is_integral<T>::value &&
139    std::is_unsigned<T>::value &&
140    sizeof(T) <= sizeof(unsigned int)),
141   unsigned int>::type
142   findLastSet(T x) {
143   return x ? 8 * sizeof(unsigned int) - __builtin_clz(x) : 0;
144 }
145
146 template <class T>
147 inline constexpr
148 typename std::enable_if<
149   (std::is_integral<T>::value &&
150    std::is_unsigned<T>::value &&
151    sizeof(T) > sizeof(unsigned int) &&
152    sizeof(T) <= sizeof(unsigned long)),
153   unsigned int>::type
154   findLastSet(T x) {
155   return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0;
156 }
157
158 template <class T>
159 inline constexpr
160 typename std::enable_if<
161   (std::is_integral<T>::value &&
162    std::is_unsigned<T>::value &&
163    sizeof(T) > sizeof(unsigned long) &&
164    sizeof(T) <= sizeof(unsigned long long)),
165   unsigned int>::type
166   findLastSet(T x) {
167   return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0;
168 }
169
170 template <class T>
171 inline constexpr
172 typename std::enable_if<
173   (std::is_integral<T>::value &&
174    std::is_signed<T>::value),
175   unsigned int>::type
176   findLastSet(T x) {
177   return findLastSet(static_cast<typename std::make_unsigned<T>::type>(x));
178 }
179
180 template <class T>
181 inline constexpr
182 typename std::enable_if<
183   std::is_integral<T>::value && std::is_unsigned<T>::value,
184   T>::type
185 nextPowTwo(T v) {
186   return v ? (1ul << findLastSet(v - 1)) : 1;
187 }
188
189 template <class T>
190 inline constexpr
191 typename std::enable_if<
192   std::is_integral<T>::value && std::is_unsigned<T>::value,
193   bool>::type
194 isPowTwo(T v) {
195   return (v != 0) && !(v & (v - 1));
196 }
197
198 /**
199  * Population count
200  */
201 template <class T>
202 inline typename std::enable_if<
203   (std::is_integral<T>::value &&
204    std::is_unsigned<T>::value &&
205    sizeof(T) <= sizeof(unsigned int)),
206   size_t>::type
207   popcount(T x) {
208   return detail::popcount(x);
209 }
210
211 template <class T>
212 inline typename std::enable_if<
213   (std::is_integral<T>::value &&
214    std::is_unsigned<T>::value &&
215    sizeof(T) > sizeof(unsigned int) &&
216    sizeof(T) <= sizeof(unsigned long long)),
217   size_t>::type
218   popcount(T x) {
219   return detail::popcountll(x);
220 }
221
222 /**
223  * Endianness detection and manipulation primitives.
224  */
225 namespace detail {
226
227 template <class T>
228 struct EndianIntBase {
229  public:
230   static T swap(T x);
231 };
232
233 #define FB_GEN(t, fn) \
234 template<> inline t EndianIntBase<t>::swap(t x) { return fn(x); }
235
236 // fn(x) expands to (x) if the second argument is empty, which is exactly
237 // what we want for [u]int8_t
238 FB_GEN( int8_t,)
239 FB_GEN(uint8_t,)
240 FB_GEN( int64_t, bswap_64)
241 FB_GEN(uint64_t, bswap_64)
242 FB_GEN( int32_t, bswap_32)
243 FB_GEN(uint32_t, bswap_32)
244 FB_GEN( int16_t, bswap_16)
245 FB_GEN(uint16_t, bswap_16)
246
247 #undef FB_GEN
248
249 #if __BYTE_ORDER == __LITTLE_ENDIAN
250
251 template <class T>
252 struct EndianInt : public detail::EndianIntBase<T> {
253  public:
254   static T big(T x) { return EndianInt::swap(x); }
255   static T little(T x) { return x; }
256 };
257
258 #elif __BYTE_ORDER == __BIG_ENDIAN
259
260 template <class T>
261 struct EndianInt : public detail::EndianIntBase<T> {
262  public:
263   static T big(T x) { return x; }
264   static T little(T x) { return EndianInt::swap(x); }
265 };
266
267 #else
268 # error Your machine uses a weird endianness!
269 #endif  /* __BYTE_ORDER */
270
271 }  // namespace detail
272
273 // big* convert between native and big-endian representations
274 // little* convert between native and little-endian representations
275 // swap* convert between big-endian and little-endian representations
276 //
277 // ntohs, htons == big16
278 // ntohl, htonl == big32
279 #define FB_GEN1(fn, t, sz) \
280   static t fn##sz(t x) { return fn<t>(x); } \
281
282 #define FB_GEN2(t, sz) \
283   FB_GEN1(swap, t, sz) \
284   FB_GEN1(big, t, sz) \
285   FB_GEN1(little, t, sz)
286
287 #define FB_GEN(sz) \
288   FB_GEN2(uint##sz##_t, sz) \
289   FB_GEN2(int##sz##_t, sz)
290
291 class Endian {
292  public:
293   enum class Order : uint8_t {
294     LITTLE,
295     BIG
296   };
297
298   static constexpr Order order =
299 #if __BYTE_ORDER == __LITTLE_ENDIAN
300     Order::LITTLE;
301 #elif __BYTE_ORDER == __BIG_ENDIAN
302     Order::BIG;
303 #else
304 # error Your machine uses a weird endianness!
305 #endif  /* __BYTE_ORDER */
306
307   template <class T> static T swap(T x) {
308     return detail::EndianInt<T>::swap(x);
309   }
310   template <class T> static T big(T x) {
311     return detail::EndianInt<T>::big(x);
312   }
313   template <class T> static T little(T x) {
314     return detail::EndianInt<T>::little(x);
315   }
316
317   FB_GEN(64)
318   FB_GEN(32)
319   FB_GEN(16)
320   FB_GEN(8)
321 };
322
323 #undef FB_GEN
324 #undef FB_GEN2
325 #undef FB_GEN1
326
327 /**
328  * Fast bit iteration facility.
329  */
330
331
332 template <class BaseIter> class BitIterator;
333 template <class BaseIter>
334 BitIterator<BaseIter> findFirstSet(BitIterator<BaseIter>,
335                                    BitIterator<BaseIter>);
336 /**
337  * Wrapper around an iterator over an integer type that iterates
338  * over its underlying bits in LSb to MSb order.
339  *
340  * BitIterator models the same iterator concepts as the base iterator.
341  */
342 template <class BaseIter>
343 class BitIterator
344   : public bititerator_detail::BitIteratorBase<BaseIter>::type {
345  public:
346   /**
347    * Return the number of bits in an element of the underlying iterator.
348    */
349   static size_t bitsPerBlock() {
350     return std::numeric_limits<
351       typename std::make_unsigned<
352         typename std::iterator_traits<BaseIter>::value_type
353       >::type
354     >::digits;
355   }
356
357   /**
358    * Construct a BitIterator that points at a given bit offset (default 0)
359    * in iter.
360    */
361   explicit BitIterator(const BaseIter& iter, size_t bitOffset=0)
362     : bititerator_detail::BitIteratorBase<BaseIter>::type(iter),
363       bitOffset_(bitOffset) {
364     assert(bitOffset_ < bitsPerBlock());
365   }
366
367   size_t bitOffset() const {
368     return bitOffset_;
369   }
370
371   void advanceToNextBlock() {
372     bitOffset_ = 0;
373     ++this->base_reference();
374   }
375
376   BitIterator& operator=(const BaseIter& other) {
377     this->~BitIterator();
378     new (this) BitIterator(other);
379     return *this;
380   }
381
382  private:
383   friend class boost::iterator_core_access;
384   friend BitIterator findFirstSet<>(BitIterator, BitIterator);
385
386   typedef bititerator_detail::BitReference<
387       typename std::iterator_traits<BaseIter>::reference,
388       typename std::iterator_traits<BaseIter>::value_type
389     > BitRef;
390
391   void advanceInBlock(size_t n) {
392     bitOffset_ += n;
393     assert(bitOffset_ < bitsPerBlock());
394   }
395
396   BitRef dereference() const {
397     return BitRef(*this->base_reference(), bitOffset_);
398   }
399
400   void advance(ssize_t n) {
401     size_t bpb = bitsPerBlock();
402     ssize_t blocks = n / bpb;
403     bitOffset_ += n % bpb;
404     if (bitOffset_ >= bpb) {
405       bitOffset_ -= bpb;
406       ++blocks;
407     }
408     this->base_reference() += blocks;
409   }
410
411   void increment() {
412     if (++bitOffset_ == bitsPerBlock()) {
413       advanceToNextBlock();
414     }
415   }
416
417   void decrement() {
418     if (bitOffset_-- == 0) {
419       bitOffset_ = bitsPerBlock() - 1;
420       --this->base_reference();
421     }
422   }
423
424   bool equal(const BitIterator& other) const {
425     return (bitOffset_ == other.bitOffset_ &&
426             this->base_reference() == other.base_reference());
427   }
428
429   ssize_t distance_to(const BitIterator& other) const {
430     return
431       (other.base_reference() - this->base_reference()) * bitsPerBlock() +
432       (other.bitOffset_ - bitOffset_);
433   }
434
435   ssize_t bitOffset_;
436 };
437
438 /**
439  * Helper function, so you can write
440  * auto bi = makeBitIterator(container.begin());
441  */
442 template <class BaseIter>
443 BitIterator<BaseIter> makeBitIterator(const BaseIter& iter) {
444   return BitIterator<BaseIter>(iter);
445 }
446
447
448 /**
449  * Find first bit set in a range of bit iterators.
450  * 4.5x faster than the obvious std::find(begin, end, true);
451  */
452 template <class BaseIter>
453 BitIterator<BaseIter> findFirstSet(BitIterator<BaseIter> begin,
454                                    BitIterator<BaseIter> end) {
455   // shortcut to avoid ugly static_cast<>
456   static const typename BaseIter::value_type one = 1;
457
458   while (begin.base() != end.base()) {
459     typename BaseIter::value_type v = *begin.base();
460     // mask out the bits that don't matter (< begin.bitOffset)
461     v &= ~((one << begin.bitOffset()) - 1);
462     size_t firstSet = findFirstSet(v);
463     if (firstSet) {
464       --firstSet;  // now it's 0-based
465       assert(firstSet >= begin.bitOffset());
466       begin.advanceInBlock(firstSet - begin.bitOffset());
467       return begin;
468     }
469     begin.advanceToNextBlock();
470   }
471
472   // now begin points to the same block as end
473   if (end.bitOffset() != 0) {  // assume end is dereferenceable
474     typename BaseIter::value_type v = *begin.base();
475     // mask out the bits that don't matter (< begin.bitOffset)
476     v &= ~((one << begin.bitOffset()) - 1);
477     // mask out the bits that don't matter (>= end.bitOffset)
478     v &= (one << end.bitOffset()) - 1;
479     size_t firstSet = findFirstSet(v);
480     if (firstSet) {
481       --firstSet;  // now it's 0-based
482       assert(firstSet >= begin.bitOffset());
483       begin.advanceInBlock(firstSet - begin.bitOffset());
484       return begin;
485     }
486   }
487
488   return end;
489 }
490
491
492 template <class T, class Enable=void> struct Unaligned;
493
494 /**
495  * Representation of an unaligned value of a POD type.
496  */
497 template <class T>
498 struct Unaligned<
499     T,
500     typename std::enable_if<std::is_pod<T>::value>::type> {
501   Unaligned() = default;  // uninitialized
502   /* implicit */ Unaligned(T v) : value(v) { }
503   T value;
504 } __attribute__((packed));
505
506 /**
507  * Read an unaligned value of type T and return it.
508  */
509 template <class T>
510 inline T loadUnaligned(const void* p) {
511   static_assert(sizeof(Unaligned<T>) == sizeof(T), "Invalid unaligned size");
512   static_assert(alignof(Unaligned<T>) == 1, "Invalid alignment");
513   return static_cast<const Unaligned<T>*>(p)->value;
514 }
515
516 /**
517  * Write an unaligned value of type T.
518  */
519 template <class T>
520 inline void storeUnaligned(void* p, T value) {
521   static_assert(sizeof(Unaligned<T>) == sizeof(T), "Invalid unaligned size");
522   static_assert(alignof(Unaligned<T>) == 1, "Invalid alignment");
523   new (p) Unaligned<T>(value);
524 }
525
526 }  // namespace folly
527
528 #endif /* FOLLY_BITS_H_ */
529