diff --git a/src/libFLAC/bitmath.c b/src/libFLAC/bitmath.c index 043bb490..189977c6 100644 --- a/src/libFLAC/bitmath.c +++ b/src/libFLAC/bitmath.c @@ -58,10 +58,16 @@ * ilog2(17) = 4 * ilog2(18) = 4 */ + +#ifndef __GNUC__ + +/* For GNUC, use static inline version in include/private/bitmath.h. */ + unsigned FLAC__bitmath_ilog2(FLAC__uint32 v) { - unsigned l = 0; - FLAC__ASSERT(v > 0); + unsigned l = 0; + if (v == 0) + return 0; while(v >>= 1) l++; return l; @@ -70,11 +76,13 @@ unsigned FLAC__bitmath_ilog2(FLAC__uint32 v) unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v) { unsigned l = 0; - FLAC__ASSERT(v > 0); + if (v == 0) + return 0; while(v >>= 1) l++; return l; } +#endif /* An example of what FLAC__bitmath_silog2() computes: * diff --git a/src/libFLAC/bitreader.c b/src/libFLAC/bitreader.c index c3edd163..ef24951c 100644 --- a/src/libFLAC/bitreader.c +++ b/src/libFLAC/bitreader.c @@ -55,14 +55,24 @@ typedef FLAC__uint32 brword; #else #define SWAP_BE_WORD_TO_HOST(x) ENDSWAP_32(x) #endif + +#if defined(__GNUC__) +/* "int __builtin_clz (unsigned int x) If x is 0, the result is undefined" */ +static inline uint32_t +COUNT_ZERO_MSBS (uint32_t word) +{ + if (word == 0) + return 32; + return __builtin_clz (word); +} +#else /* counts the # of zero MSBs in a word */ #define COUNT_ZERO_MSBS(word) ( \ (word) <= 0xffff ? \ ( (word) <= 0xff? byte_to_unary_table[word] + 24 : byte_to_unary_table[(word) >> 8] + 16 ) : \ ( (word) <= 0xffffff? byte_to_unary_table[word >> 16] + 8 : byte_to_unary_table[(word) >> 24] ) \ ) -/* this alternate might be slightly faster on some systems/compilers: */ -#define COUNT_ZERO_MSBS2(word) ( (word) <= 0xff ? byte_to_unary_table[word] + 24 : ((word) <= 0xffff ? byte_to_unary_table[(word) >> 8] + 16 : ((word) <= 0xffffff ? byte_to_unary_table[(word) >> 16] + 8 : byte_to_unary_table[(word) >> 24])) ) +#endif /* diff --git a/src/libFLAC/include/private/bitmath.h b/src/libFLAC/include/private/bitmath.h index 67b70bad..b3d18f47 100644 --- a/src/libFLAC/include/private/bitmath.h +++ b/src/libFLAC/include/private/bitmath.h @@ -34,8 +34,30 @@ #include "FLAC/ordinals.h" + +#if defined(__GNUC__) + +static inline unsigned FLAC__bitmath_ilog2(FLAC__uint32 v) +{ + if (v == 0) + return 0; + return sizeof(FLAC__uint32) * __CHAR_BIT__ - 1 - __builtin_clz(v); +} + +static inline unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v) +{ + if (v == 0) + return 0; + return sizeof(FLAC__uint64) * __CHAR_BIT__ - 1 - __builtin_clzll(v); +} + +#else + unsigned FLAC__bitmath_ilog2(FLAC__uint32 v); unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v); + +#endif + unsigned FLAC__bitmath_silog2(int v); unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v);