From 453b54856ea9b0de377a71f70c84530eb930d104 Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sun, 12 Nov 2017 09:41:10 +0100 Subject: [PATCH] Move CLZ from genint to core --- m-core.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ m-genint.h | 49 ------------------------------------------------- 2 files changed, 50 insertions(+), 49 deletions(-) diff --git a/m-core.h b/m-core.h index 801dd5ff..42437bb0 100644 --- a/m-core.h +++ b/m-core.h @@ -1252,6 +1252,56 @@ static inline uint64_t m_core_roundpow2(uint64_t v) return v; } +/* Return the count leading zero of the argument */ +#if defined(__GNUC__) && (__GNUC__*100 + __GNUC_MINOR__) >= 304 +static inline unsigned int m_core_clz(unsigned long limb) +{ + return M_UNLIKELY (limb == 0) ? sizeof(unsigned long)*CHAR_BIT : __builtin_clzl(limb); +} +#else +#define M_CORE_CLZ_TAB "\010\07\06\06\05\05\05\05\04\04\04\04\04\04\04\04\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" + +static inline unsigned int m_core_clz(unsigned long limb) +{ + unsigned int shift = 0; + /* This code should be branchless on most targets */ +#if ULONG_MAX == 18446744073709551615UL + /* Compute shift so that, it is + + -7 if the highest 56 bits are clear, + + -6 for the highest 48 bits, + + -5 for the highest 40 bits, + + -4 for the highest 32 bits, + + -3 for the highest 24 bits, + + -2 for the highest 16 bits, + + -1 for the highest 8 bits, + + 0 otherwise */ + shift = -(limb < 0x100000000000000UL); + shift -= (limb < 0x1000000000000UL); + shift -= (limb < 0x10000000000UL); + shift -= (limb < 0x100000000UL); + shift -= (limb < 0x1000000UL); + shift -= (limb < 0x10000UL); + shift -= (limb < 0x100UL); + shift = shift*8 + 56; + shift = 56 - shift + M_CORE_CLZ_TAB[limb >> shift ]; +#elif ULONG_MAX == 4294967295UL + /* Compute shift so that, it is + + -3 if the highest 24 bits are clear, + + -2 for the highest 16 bits, + + -1 for the highest 8 bits, + + 0 otherwise */ + shift = -(limb < 0x1000000UL); + shift -= (limb < 0x10000UL); + shift -= (limb < 0x100UL); + shift = shift*8 + 24; + shift = 24 - shift + M_CORE_CLZ_TAB[limb >> shift ]; +#else +# error Unkown size for unsigned long. Please create a bug report and report the ULONG_MAX value. +#endif + return shift; +} +#endif + /* Implement a kind of FNV1A Hash. Inspired by http://www.sanmayce.com/Fastest_Hash/ Jesteress and port to 64 bits. See https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash diff --git a/m-genint.h b/m-genint.h index b7922461..3c7c6f21 100644 --- a/m-genint.h +++ b/m-genint.h @@ -76,55 +76,6 @@ static inline void genint_clear(genint_t s) s->data = NULL; } -#if defined(__GNUC__) && (__GNUC__*100 + __GNUC_MINOR__) >= 304 -static inline unsigned int m_core_clz(unsigned long limb) -{ - return M_UNLIKELY (limb == 0) ? sizeof(unsigned long)*CHAR_BIT : __builtin_clzl(limb); -} -#else -#define M_CORE_CLZ_TAB "\010\07\06\06\05\05\05\05\04\04\04\04\04\04\04\04\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\03\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\02\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\01\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00" - -static inline unsigned int m_core_clz(unsigned long limb) -{ - unsigned int shift = 0; - /* This code should be branchless on most targets */ -#if ULONG_MAX == 18446744073709551615UL - /* Compute shift so that, it is - + -7 if the highest 56 bits are clear, - + -6 for the highest 48 bits, - + -5 for the highest 40 bits, - + -4 for the highest 32 bits, - + -3 for the highest 24 bits, - + -2 for the highest 16 bits, - + -1 for the highest 8 bits, - + 0 otherwise */ - shift = -(limb < 0x100000000000000UL); - shift -= (limb < 0x1000000000000UL); - shift -= (limb < 0x10000000000UL); - shift -= (limb < 0x100000000UL); - shift -= (limb < 0x1000000UL); - shift -= (limb < 0x10000UL); - shift -= (limb < 0x100UL); - shift = shift*8 + 56; - shift = 56 - shift + M_CORE_CLZ_TAB[limb >> shift ]; -#elif ULONG_MAX == 4294967295UL - /* Compute shift so that, it is - + -3 if the highest 24 bits are clear, - + -2 for the highest 16 bits, - + -1 for the highest 8 bits, - + 0 otherwise */ - shift = -(limb < 0x1000000UL); - shift -= (limb < 0x10000UL); - shift -= (limb < 0x100UL); - shift = shift*8 + 24; - shift = 24 - shift + M_CORE_CLZ_TAB[limb >> shift ]; -#else -# error Unkown size for unsigned long. Please create a bug report and report the ULONG_MAX value. -#endif - return shift; -} -#endif - static inline size_t genint_pop(genint_t s) { GENINT_CONTRACT(s);