📄 inttypes.hh
字号:
#ifndef simtypes_hh_included#define simtypes_hh_included#include <stdlib.h>#include "assert.hh"// GCC before 2.95 doesn't work.#ifdef __GNUC__# if (__GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 95))# error Sulima cannot be compiled with versions of GCC earlier than 2.9x# endif#endif// This header defines a set of minimum-width integer types. There is no need// for fixed-width types, although in many places it may improve performance.// There are four minimum-width signed types Int8, Int16, Int32 and Int64, and// four corresponding unsigned types UInt8, UInt16, UInt32 and UInt64.// Currently, two models are supported, ANSI (use ANSI restrictions on types// up to 32 bit and some unportable 64 bit type) and SIM64 (32 bit integers// and 64 bit longs). The first is currently supported only on GCC and TenDRA// as well as any C99-compatible compilers. Note that all eight types MUST be// distinct, as they are frequently used in overload resolution.typedef signed char Int8;typedef unsigned char UInt8;typedef signed short Int16;typedef unsigned short UInt16;#if defined SIM64typedef signed int Int32;typedef unsigned int UInt32;#elsetypedef signed long Int32;typedef unsigned long UInt32;#endif#if defined SIM64 typedef signed long Int64; typedef unsigned long UInt64;#elif defined __TenDRA__ // We must enable long long first. #pragma TenDRA longlong type allow typedef signed long long Int64; typedef unsigned long long UInt64;#elif defined __GNUC__ // This mess is here so we can use -pedantic without warnings. typedef __typeof__(__extension__ 1LL) Int64; typedef __typeof__(__extension__ 1ULL) UInt64;#elif __STDC_VERSION__ >= 199901L // C99 supports long long from the box. typedef signed long long Int64; typedef unsigned long long UInt64;#else# error Cannot find a suitible 64 bit type.#endif// A template intended to obtain a type given its width.template <int n> struct FixedWidth { };template <> struct FixedWidth<8> { typedef Int8 Signed; // signed type of at least <n> bytse typedef UInt8 Unsigned; // unsigned type of at least <n> bytes};template <> struct FixedWidth<16> { typedef Int16 Signed; typedef UInt16 Unsigned;};template <> struct FixedWidth<32> { typedef Int32 Signed; typedef UInt32 Unsigned;};template <> struct FixedWidth<64> { typedef Int64 Signed; typedef UInt64 Unsigned;};// Some type traits used by various templates. For each type T, I define the// following parameters://// IntTraits<T>::width working width of the type// typename IntTraits<T>::Signed signed counterpart of T// typename IntTraits<T>::Unsigned unsigned counterpart of T// typename IntTraits<T>::Half a type with half of the width of T// typename IntTraits<T>::Double a type with twice the width of T//// Obviously, Half is not defined for 8-bit types and Double is not defined// for 64-bit types.template <typename T> struct IntTraits { };template <> struct IntTraits<Int8> { static const int width = 8; typedef Int8 Signed; typedef UInt8 Unsigned; typedef Int16 Double;};template <> struct IntTraits<Int16> { static const int width = 16; typedef Int16 Signed; typedef UInt16 Unsigned; typedef Int8 Half; typedef Int32 Double;};template <> struct IntTraits<Int32> { static const int width = 32; typedef Int32 Signed; typedef UInt32 Unsigned; typedef Int16 Half; typedef Int64 Double;};template <> struct IntTraits<Int64> { static const int width = 64; typedef Int64 Signed; typedef UInt64 Unsigned; typedef Int32 Half;};template <> struct IntTraits<UInt8> { static const int width = 8; typedef Int8 Signed; typedef UInt8 Unsigned; typedef UInt16 Double;};template <> struct IntTraits<UInt16> { static const int width = 16; typedef Int16 Signed; typedef UInt16 Unsigned; typedef UInt8 Half; typedef UInt32 Double;};template <> struct IntTraits<UInt32> { static const int width = 32; typedef Int32 Signed; typedef UInt32 Unsigned; typedef UInt16 Half; typedef UInt64 Double;};template <> struct IntTraits<UInt64> { static const int width = 64; typedef Int64 Signed; typedef UInt64 Unsigned; typedef UInt32 Half;};// Useful multiplier suffixes.static const int KB = 1024;static const int MB = 1024*KB;static const int GB = 1024*MB;static const int TB = 1024*GB;// Interfaces to ANSI # and ## preprocessing operators. The STR2() and// GLUE2() differ from STR() and GLUE() in that the later macro-expand the// arguments before applying the operator.#define STR2(x) #x#define STR(x) STR2(x)#define GLUE2(x,y) x##y#define GLUE(x,y) GLUE2(x,y)// Two macros used to construct fixed-width constants from unsuffixed// literals. They serve two purposes: (1) to make it possible to define// portable 64 bit constants on 32 bit systems, and (2) to make huge constant// easier to read.#define C32(a,b) \ ((UInt32)((UInt32)GLUE2(0x,a) << 16 | (UInt32)GLUE2(0x,b)))#define C64(a,b,c,d) \ ((UInt64)((UInt64)GLUE2(0x,a) << 48 | (UInt64)GLUE2(0x,b) << 32 | \ (UInt64)GLUE2(0x,c) << 16 | (UInt64)GLUE2(0x,d)))// Returns true iff the host system uses big-endian byte ordering.inline bool big_endian_host(){ const int sample = 1; return !reinterpret_cast<const char &>(sample);}// Return false iff (x) != log2(x) (computed to infinite precision)template <typename T> inline bool is_power_of_two(T x){ return (x & -x) == x;}// Some important bit-swizzling functions. In most cases, these allows me to// avoid computing huge hexadecimal bitmask, which certainly is a good thing.// Return (x) rounded toward -inf to the nearest multiple of (size).// Precondition: size == (1 << x), 0 <= x < 8 * sizeof(T) - 1template <typename T, typename Int> inline T round_down(T x, Int size){ return x & -typename IntTraits<T>::Signed(size);}// Return (x) rounded toward +inf to the nearest multiple of (size).// Precondition: size == (1 << x), 0 <= x < 8 * sizeof(T) - 1template <typename T, typename Int> inline T round_up(T x, Int size){ return (x + size - 1) & -typename IntTraits<T>::Signed(size);}// Create a bit mask with the (n)th bit set.// Precondition: 0 <= n < 64inline UInt64 bitmask(int n){ return (UInt64)1 << n;}// Create a bit mask with the bits in the range [m, n] set. // Precondition: 0 <= m <= n < 64inline UInt64 bitmask(int n, int m){ return ~(UInt64)0 >> m << (63 - n + m) >> (63 - n);}// Return the (n)th bit from (x).// Precondition: 0 <= n < 8 * sizeof(T)template <typename T, typename Int> inline T bit(T x, Int n){ return (x >> n) & 1;}// Return (x) with the (n)th bit cleared.// Precondition: 0 <= n < 8 * sizeof(T).template <typename T, typename Int> inline T clear_bit(T x, Int n){ return x & ~bitmask(n);}// Return (x) with the (n)th bit set.// Precondition: 0 <= n < 8 * sizeof(T).template <typename T, typename Int> inline T set_bit(T x, Int n){ return x | bitmask(n);}// Return (x) with the (n)th bit set to bit(y, 0).// Precondition: 0 <= n < 8 * sizeof(T). template <typename T, typename Int> inline T set_bit(T x, T y, Int n){ return clear_bit(x, n) | (bit(y, 0) << n);}// Return the bit range [m, n] from (x).// Precondition: 0 <= m <= n < 8 * sizeof(T).template <typename T, typename Int> inline T bits(T x, Int n, Int m){ UInt64 y = x; return y << (63 - n) >> (63 - n + m);}// Return (x) with bits in the range [m, n] cleared.// Precondition: 0 <= m <= n < 8 * sizeof(T).template <typename T, typename Int> inline T clear_bits(T x, Int n, Int m){ return x & ~bitmask(n, m);}// Return (x) with bits in the range [m, n] set.// Precondition: 0 <= m <= n < 8 * sizeof(T).template <typename T, typename Int> inline T set_bits(T x, Int n, Int m){ return x | bitmask(n, m);}// Return (x) with bits in the range [m, n] set to bits(y, n - m, 0).// Precondition: 0 <= m <= n < 8 * sizeof(T).template <typename T, typename Int> inline T set_bits(T x, T y, Int n, Int m){ return clear_bits(x, n, m) | (bits(y, n - m, Int(0)) << m);}// Return bits(x, n-1, 0) zero-extended to (8 * sizeof(T)).// Precondition: 0 < n <= 8 * sizeof(T)template <typename T> inline T zero_extend(T x, int n){ return bits(x, n-1, 0);}// Return bits(x, n-1, 0) sign-extended to (8 * sizeof(T)).// Precondition: 0 < n <= 8 * sizeof(T)template <typename T> inline T sign_extend(T x, int n){ if (((typename IntTraits<T>::Signed)-1 >> 1) < 0) { // Host platform does arithmetic right shifts. typename IntTraits<T>::Signed y = x; return y << (8 * sizeof(T) - n) >> (8 * sizeof(T) - n); } else if (size_t(n) < 8 * sizeof(T)) { // We have to manually patch the high-order bits. if (bit(x, n - 1)) return set_bits(x, 8 * sizeof(T) - 1, size_t(n)); else { return clear_bits(x, 8 * sizeof(T) - 1, size_t(n)); } }}// Return (x) with the byte order reversed. byte_swap(x) recursively swaps// each half of (x), until (x) contains only a single byte.template <typename T> inline T byte_swap(T x){ typedef typename IntTraits<T>::Unsigned U; typedef typename IntTraits<U>::Half Half; return (U(byte_swap(Half(x))) << IntTraits<Half>::width) | byte_swap(Half(x >> IntTraits<Half>::width));}template <> inline Int8 byte_swap(Int8 x){ return x;}template <> inline UInt8 byte_swap(UInt8 x){ return x;}// Return floor(log2(x)).// Precondition: x > 0template <typename T> int log2(T x){ assert(x > 0); int i = 0; do { ++i; } while (x >>= 1); return i;}// Perform a long multiplication.// Preconditions: a == sign_extend(a, IntTraits<T>::width)// b == sign_extend(b, IntTraits<T>::width)template <typename T> struct MulResult { T lo, hi; MulResult() { } MulResult(T h, T l) : lo(l), hi(h) { }};template <typename T> MulResult<T> multiply(T a, T b){ const int n = IntTraits<T>::width; typename IntTraits<T>::Double x = a, y = b, z = x * y; return MulResult<T>(bits(z, 2 * n - 1, n), bits(z, n - 1, 0));}// Specializations for 64 bit types are in "sulima/multiply.cc"template <> MulResult<Int64> multiply(Int64 a, Int64 b);template <> MulResult<UInt64> multiply(UInt64 a, UInt64 b);// Perform a portable division, using the standard library div() and ldiv()// functions if possible. The result is always rounded toward zero; I assume// that the compiler is consistent with its treatment of negative arguments to// the / and % operators, which is a reasonable assumption, although not// strictly portable according to ISO.// Preconditions: a == sign_extend(a, IntTraits<T>::width)// b == sign_extend(b, IntTraits<T>::width) != 0template <typename T> struct DivResult { T quot, rem; DivResult() { } DivResult(T q, T r) : quot(q), rem(r) { }};template <typename T> DivResult<T> divide(T a, T b){ const size_t n = IntTraits<T>::width; if (n < sizeof(int)) { div_t r = div(int(a), int(b)); return DivResult<T>(r.quot, r.rem); } else if (n < sizeof(long)) { ldiv_t r = ldiv(long(a), long(b)); return DivResult<T>(r.quot, r.rem); } else { // This has to be specialized for signed types. return DivResult<T>(a / b, a % b); }}// Specialisations for 32 and 64 bit types.template <> inline DivResult<Int32> divide(Int32 a, Int32 b){ if (32 <= sizeof(int)) { div_t r = div(int(a), int(b)); return DivResult<Int32>(r.quot, r.rem); } else { ldiv_t r = ldiv(long(a), long(b)); return DivResult<Int32>(r.quot, r.rem); }}template <> inline DivResult<UInt32> divide(UInt32 a, UInt32 b){ if (32 < sizeof(long)) { ldiv_t r = ldiv(long(a), long(b)); return DivResult<UInt32>(r.quot, r.rem); } else { return DivResult<UInt32>(a / b, a % b); }}template <> inline DivResult<Int64> divide(Int64 a, Int64 b){ if (64 <= sizeof(long)) { ldiv_t r = ldiv(long(a), long(b)); return DivResult<Int64>(r.quot, r.rem); } else if (Int64(-2) % Int64(3) < 0) { // Hardware division rounds towards zero. return DivResult<Int64>(a / b, a % b); } else { // Hardware division rounds towards negative infinity, so fix it. if ((a ^ b) >= 0) return DivResult<Int64>(a / b, a % b); else if (a < 0) return DivResult<Int64>(-(-a / b), -(-a % b)); else { return DivResult<Int64>(-(a / -b), -(a % -b)); } }}/* this may seem completely unnecessary, but these extra definitions * allow the above functions to be used when the last template type is * an enumeration (which has no particular type). In that case, int * will be used, which should be sufficient for any enumerations. */template <typename T> inline T bit(T x, int n){ return bit <T, int> (x, n);}template <typename T> inline T clear_bit(T x, int n){ return clear_bit <T, int> (x, n);}template <typename T> inline T set_bit(T x, int n){ return set_bit <T, int> (x, n);}template <typename T> inline T set_bit(T x, T y, int n){ return set_bit <T, int> (x, y, n);}template <typename T> inline T bits(T x, int n, int m){ return bits <T, int> (x, n, m);}template <typename T> inline T clear_bits(T x, int n, int m){ return clear_bits <T, int> (x, n, m);}template <typename T> inline T set_bits(T x, int n, int m){ return set_bits <T, int> (x, n, m);}template <typename T> inline T set_bits(T x, T y, int n, int m){ return set_bits <T, int> (x, y, n, m);}#endif // simtypes_hh_included
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -