Improve _hb_popcount()

Support 128bit type.
This commit is contained in:
Behdad Esfahbod 2018-02-16 16:06:17 -08:00
parent 7b5ce74047
commit 978ace6fbb
4 changed files with 44 additions and 24 deletions

View File

@ -76,7 +76,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
AM_CONDITIONAL([ENABLE_GTK_DOC], false)
])
# Functions and headers
# Types, functions, and headers
AC_CHECK_TYPES(unsigned __int128)
AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l setlinebuf)
AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h)

View File

@ -99,7 +99,7 @@ struct ValueFormat : HBUINT16
#endif
inline unsigned int get_len (void) const
{ return _hb_popcount32 ((unsigned int) *this); }
{ return _hb_popcount ((unsigned int) *this); }
inline unsigned int get_size (void) const
{ return get_len () * Value::static_size; }

View File

@ -139,7 +139,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
{
static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1;
unsigned int global_bit_shift = _hb_popcount32 (HB_GLYPH_FLAG_DEFINED);
unsigned int global_bit_shift = _hb_popcount (HB_GLYPH_FLAG_DEFINED);
m.global_mask = global_bit_mask;

View File

@ -323,31 +323,50 @@ typedef const struct _hb_void_t *hb_void_t;
#define HB_VOID ((const _hb_void_t *) nullptr)
/* Return the number of 1 bits in mask. */
template <typename T>
static inline HB_CONST_FUNC unsigned int
_hb_popcount32 (uint32_t mask)
_hb_popcount (T mask)
{
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__OPTIMIZE__)
if (sizeof (unsigned int) >= sizeof (mask))
return __builtin_popcount (mask);
#else
if (sizeof (unsigned long) >= sizeof (mask))
return __builtin_popcountl (mask);
if (sizeof (unsigned long long) >= sizeof (mask))
return __builtin_popcountll (mask);
#endif
if (sizeof (T) <= 4)
{
/* "HACKMEM 169" */
uint32_t y;
y = (mask >> 1) &033333333333;
y = mask - y - ((y >>1) & 033333333333);
return (((y + (y >> 3)) & 030707070707) % 077);
#endif
}
if (sizeof (T) == 8)
{
unsigned int shift = 32;
return _hb_popcount<uint32_t> ((uint32_t) mask) + _hb_popcount ((uint32_t) (mask >> shift));
}
if (sizeof (T) == 16)
{
unsigned int shift = 64;
return _hb_popcount<uint64_t> ((uint64_t) mask) + _hb_popcount ((uint64_t) (mask >> shift));
}
unsigned int count = 0;
while (mask)
{
count += _hb_popcount<uint64_t> ((uint64_t) mask);
unsigned int shift = 64;
mask = (T) (mask >> shift);
}
}
static inline HB_CONST_FUNC unsigned int
_hb_popcount64 (uint64_t mask)
{
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
if (sizeof (long) >= sizeof (mask))
return __builtin_popcountl (mask);
#endif
return _hb_popcount32 (mask & 0xFFFFFFFF) + _hb_popcount32 (mask >> 32);
}
template <typename T> static inline unsigned int _hb_popcount (T mask);
template <> inline unsigned int _hb_popcount<uint32_t> (uint32_t mask) { return _hb_popcount32 (mask); }
template <> inline unsigned int _hb_popcount<uint64_t> (uint64_t mask) { return _hb_popcount64 (mask); }
/* Returns the number of bits needed to store number */
static inline HB_CONST_FUNC unsigned int