X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FBits.h;h=4c1182a633c99dbac620a4e251065d47e77631f6;hb=aa7aebf348c1b60d2ef2e81dd526aacd2f8d8769;hp=ade126d0803b6920c7fdd8dd1c30fd0009308811;hpb=217e88e6a6f011a6cc4d44490b319f919574a620;p=folly.git diff --git a/folly/Bits.h b/folly/Bits.h index ade126d0..4c1182a6 100644 --- a/folly/Bits.h +++ b/folly/Bits.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2015 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,16 +55,10 @@ #ifndef FOLLY_BITS_H_ #define FOLLY_BITS_H_ -#include - -#ifndef __GNUC__ -#error GCC required -#endif - -#ifndef __clang__ +#if !defined(__clang__) && !defined(_MSC_VER) #define FOLLY_INTRINSIC_CONSTEXPR constexpr #else -// Unlike GCC, in Clang (as of 3.2) intrinsics aren't constexpr. +// GCC is the only compiler with intrinsics constexpr. #define FOLLY_INTRINSIC_CONSTEXPR const #endif @@ -78,6 +72,14 @@ # include #endif +#ifdef _MSC_VER +# include +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanForward64) +# pragma intrinsic(_BitScanReverse) +# pragma intrinsic(_BitScanReverse64) +#endif + #include #include #include @@ -98,7 +100,12 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned int)), unsigned int>::type findFirstSet(T x) { +#ifdef _MSC_VER + unsigned long index; + return _BitScanForward(&index, x) ? index : 0; +#else return __builtin_ffs(x); +#endif } template @@ -110,7 +117,12 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned long)), unsigned int>::type findFirstSet(T x) { +#ifdef _MSC_VER + unsigned long index; + return _BitScanForward(&index, x) ? index : 0; +#else return __builtin_ffsl(x); +#endif } template @@ -122,7 +134,12 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned long long)), unsigned int>::type findFirstSet(T x) { +#ifdef _MSC_VER + unsigned long index; + return _BitScanForward64(&index, x) ? index : 0; +#else return __builtin_ffsll(x); +#endif } template @@ -147,7 +164,18 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned int)), unsigned int>::type findLastSet(T x) { +#ifdef _MSC_VER + unsigned long index; + int clz; + if (_BitScanReverse(&index, x)) { + clz = static_cast(31 - index); + } else { + clz = 32; + } + return x ? 8 * sizeof(unsigned int) - clz : 0; +#else return x ? 8 * sizeof(unsigned int) - __builtin_clz(x) : 0; +#endif } template @@ -159,7 +187,18 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned long)), unsigned int>::type findLastSet(T x) { +#ifdef _MSC_VER + unsigned long index; + int clz; + if (_BitScanReverse(&index, x)) { + clz = static_cast(31 - index); + } else { + clz = 32; + } + return x ? 8 * sizeof(unsigned int) - clz : 0; +#else return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0; +#endif } template @@ -171,7 +210,18 @@ typename std::enable_if< sizeof(T) <= sizeof(unsigned long long)), unsigned int>::type findLastSet(T x) { +#ifdef _MSC_VER + unsigned long index; + unsigned long long clz; + if (_BitScanReverse(&index, x)) { + clz = static_cast(63 - index); + } else { + clz = 64; + } + return x ? 8 * sizeof(unsigned long long) - clz : 0; +#else return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0; +#endif } template @@ -237,6 +287,8 @@ struct EndianIntBase { static T swap(T x); }; +#ifndef _MSC_VER + /** * If we have the bswap_16 macro from byteswap.h, use it; otherwise, provide our * own definition. @@ -254,6 +306,8 @@ our_bswap16(Int16 x) { } #endif +#endif + #define FB_GEN(t, fn) \ template<> inline t EndianIntBase::swap(t x) { return fn(x); } @@ -262,12 +316,21 @@ template<> inline t EndianIntBase::swap(t x) { return fn(x); } // __builtin_bswap16 for some reason, so we have to provide our own. FB_GEN( int8_t,) FB_GEN(uint8_t,) +#ifdef _MSC_VER +FB_GEN( int64_t, _byteswap_uint64) +FB_GEN(uint64_t, _byteswap_uint64) +FB_GEN( int32_t, _byteswap_ulong) +FB_GEN(uint32_t, _byteswap_ulong) +FB_GEN( int16_t, _byteswap_ushort) +FB_GEN(uint16_t, _byteswap_ushort) +#else FB_GEN( int64_t, __builtin_bswap64) FB_GEN(uint64_t, __builtin_bswap64) FB_GEN( int32_t, __builtin_bswap32) FB_GEN(uint32_t, __builtin_bswap32) FB_GEN( int16_t, our_bswap16) FB_GEN(uint16_t, our_bswap16) +#endif #undef FB_GEN @@ -339,10 +402,12 @@ class Endian { return detail::EndianInt::little(x); } +#if !defined(__ANDROID__) FB_GEN(64) FB_GEN(32) FB_GEN(16) FB_GEN(8) +#endif }; #undef FB_GEN @@ -371,7 +436,7 @@ class BitIterator /** * Return the number of bits in an element of the underlying iterator. */ - static size_t bitsPerBlock() { + static unsigned int bitsPerBlock() { return std::numeric_limits< typename std::make_unsigned< typename std::iterator_traits::value_type @@ -457,10 +522,10 @@ class BitIterator ssize_t distance_to(const BitIterator& other) const { return (other.base_reference() - this->base_reference()) * bitsPerBlock() + - (other.bitOffset_ - bitOffset_); + other.bitOffset_ - bitOffset_; } - ssize_t bitOffset_; + unsigned int bitOffset_; }; /**