mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-04-16 12:28:48 +02:00
Fix bug in g_bit_nth_lsf (#371631) and use __builtin_clzl for
2007-01-03 Behdad Esfahbod <behdad@gnome.org> * glib/gutils.h: Fix bug in g_bit_nth_lsf (#371631) and use __builtin_clzl for g_bit_storage if available (#371670). * tests/Makefile.am: * tests/bit-test.c: New test, to test g_bit_* operations against naive and builtin implementations. svn path=/trunk/; revision=5200
This commit is contained in:
parent
bf1b1d2711
commit
048efdfbd5
@ -1,3 +1,12 @@
|
|||||||
|
2007-01-03 Behdad Esfahbod <behdad@gnome.org>
|
||||||
|
|
||||||
|
* glib/gutils.h: Fix bug in g_bit_nth_lsf (#371631) and use
|
||||||
|
__builtin_clzl for g_bit_storage if available (#371670).
|
||||||
|
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/bit-test.c: New test, to test g_bit_* operations against
|
||||||
|
naive and builtin implementations.
|
||||||
|
|
||||||
2007-01-02 Behdad Esfahbod <behdad@gnome.org>
|
2007-01-02 Behdad Esfahbod <behdad@gnome.org>
|
||||||
|
|
||||||
* configure.in: Avoid more warnings from running libtool --config.
|
* configure.in: Avoid more warnings from running libtool --config.
|
||||||
|
@ -250,10 +250,10 @@ gchar* g_find_program_in_path (const gchar *program);
|
|||||||
/* Bit tests
|
/* Bit tests
|
||||||
*/
|
*/
|
||||||
G_INLINE_FUNC gint g_bit_nth_lsf (gulong mask,
|
G_INLINE_FUNC gint g_bit_nth_lsf (gulong mask,
|
||||||
gint nth_bit);
|
gint nth_bit) G_GNUC_CONST;
|
||||||
G_INLINE_FUNC gint g_bit_nth_msf (gulong mask,
|
G_INLINE_FUNC gint g_bit_nth_msf (gulong mask,
|
||||||
gint nth_bit);
|
gint nth_bit) G_GNUC_CONST;
|
||||||
G_INLINE_FUNC guint g_bit_storage (gulong number);
|
G_INLINE_FUNC guint g_bit_storage (gulong number) G_GNUC_CONST;
|
||||||
|
|
||||||
/* Trash Stacks
|
/* Trash Stacks
|
||||||
* elements need to be >= sizeof (gpointer)
|
* elements need to be >= sizeof (gpointer)
|
||||||
@ -277,33 +277,36 @@ G_INLINE_FUNC gint
|
|||||||
g_bit_nth_lsf (gulong mask,
|
g_bit_nth_lsf (gulong mask,
|
||||||
gint nth_bit)
|
gint nth_bit)
|
||||||
{
|
{
|
||||||
do
|
if (G_UNLIKELY (nth_bit < -1))
|
||||||
|
nth_bit = -1;
|
||||||
|
while (nth_bit < ((GLIB_SIZEOF_LONG * 8) - 1))
|
||||||
{
|
{
|
||||||
nth_bit++;
|
nth_bit++;
|
||||||
if (mask & (1UL << nth_bit))
|
if (mask & (1UL << nth_bit))
|
||||||
return nth_bit;
|
return nth_bit;
|
||||||
}
|
}
|
||||||
while (nth_bit < ((GLIB_SIZEOF_LONG * 8) - 1));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
G_INLINE_FUNC gint
|
G_INLINE_FUNC gint
|
||||||
g_bit_nth_msf (gulong mask,
|
g_bit_nth_msf (gulong mask,
|
||||||
gint nth_bit)
|
gint nth_bit)
|
||||||
{
|
{
|
||||||
if (nth_bit < 0)
|
if (nth_bit < 0 || G_UNLIKELY (nth_bit > GLIB_SIZEOF_LONG * 8))
|
||||||
nth_bit = GLIB_SIZEOF_LONG * 8;
|
nth_bit = GLIB_SIZEOF_LONG * 8;
|
||||||
do
|
while (nth_bit > 0)
|
||||||
{
|
{
|
||||||
nth_bit--;
|
nth_bit--;
|
||||||
if (mask & (1UL << nth_bit))
|
if (mask & (1UL << nth_bit))
|
||||||
return nth_bit;
|
return nth_bit;
|
||||||
}
|
}
|
||||||
while (nth_bit > 0);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
G_INLINE_FUNC guint
|
G_INLINE_FUNC guint
|
||||||
g_bit_storage (gulong number)
|
g_bit_storage (gulong number)
|
||||||
{
|
{
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
|
||||||
|
return number ? GLIB_SIZEOF_LONG * 8 - __builtin_clzl(number) : 1;
|
||||||
|
#else
|
||||||
register guint n_bits = 0;
|
register guint n_bits = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -313,6 +316,7 @@ g_bit_storage (gulong number)
|
|||||||
}
|
}
|
||||||
while (number);
|
while (number);
|
||||||
return n_bits;
|
return n_bits;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
G_INLINE_FUNC void
|
G_INLINE_FUNC void
|
||||||
g_trash_stack_push (GTrashStack **stack_p,
|
g_trash_stack_push (GTrashStack **stack_p,
|
||||||
|
@ -65,6 +65,7 @@ test_programs = \
|
|||||||
atomic-test \
|
atomic-test \
|
||||||
array-test \
|
array-test \
|
||||||
base64-test \
|
base64-test \
|
||||||
|
bit-test \
|
||||||
$(CXX_TEST) \
|
$(CXX_TEST) \
|
||||||
child-test \
|
child-test \
|
||||||
completion-test \
|
completion-test \
|
||||||
@ -130,6 +131,7 @@ module_ldadd = $(libgmodule) $(G_MODULE_LIBS) $(progs_ldadd)
|
|||||||
atomic_test_LDADD = $(progs_ldadd)
|
atomic_test_LDADD = $(progs_ldadd)
|
||||||
array_test_LDADD = $(progs_ldadd)
|
array_test_LDADD = $(progs_ldadd)
|
||||||
base64_test_LDADD = $(progs_ldadd)
|
base64_test_LDADD = $(progs_ldadd)
|
||||||
|
bit_test_LDADD = $(progs_ldadd)
|
||||||
bookmarkfile_test_LDADD = $(progs_ldadd)
|
bookmarkfile_test_LDADD = $(progs_ldadd)
|
||||||
child_test_LDADD = $(thread_ldadd)
|
child_test_LDADD = $(thread_ldadd)
|
||||||
completion_test_LDADD = $(progs_ldadd)
|
completion_test_LDADD = $(progs_ldadd)
|
||||||
|
145
tests/bit-test.c
Normal file
145
tests/bit-test.c
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||||
|
# define TEST_BUILTINS 1
|
||||||
|
#else
|
||||||
|
# define TEST_BUILTINS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TEST_BUILTINS
|
||||||
|
static gint
|
||||||
|
builtin_bit_nth_lsf1 (gulong mask, gint nth_bit)
|
||||||
|
{
|
||||||
|
if (nth_bit >= 0)
|
||||||
|
{
|
||||||
|
if (G_LIKELY (nth_bit < GLIB_SIZEOF_LONG * 8 - 1))
|
||||||
|
mask &= -(1<<(nth_bit+1));
|
||||||
|
else
|
||||||
|
mask = 0;
|
||||||
|
}
|
||||||
|
return __builtin_ffsl(mask) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
builtin_bit_nth_lsf2 (gulong mask, gint nth_bit)
|
||||||
|
{
|
||||||
|
if (nth_bit >= 0)
|
||||||
|
{
|
||||||
|
if (G_LIKELY (nth_bit < GLIB_SIZEOF_LONG * 8 - 1))
|
||||||
|
mask &= -(1<<(nth_bit+1));
|
||||||
|
else
|
||||||
|
mask = 0;
|
||||||
|
}
|
||||||
|
return mask ? __builtin_ctzl(mask) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
builtin_bit_nth_msf (gulong mask, gint nth_bit)
|
||||||
|
{
|
||||||
|
if (nth_bit >= 0 && nth_bit < GLIB_SIZEOF_LONG * 8)
|
||||||
|
mask &= (1<<nth_bit)-1;
|
||||||
|
return mask ? GLIB_SIZEOF_LONG * 8 - 1 - __builtin_clzl(mask) : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static guint
|
||||||
|
builtin_bit_storage (gulong number)
|
||||||
|
{
|
||||||
|
return number ? GLIB_SIZEOF_LONG * 8 - __builtin_clzl(number) : 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static gint
|
||||||
|
naive_bit_nth_lsf (gulong mask, gint nth_bit)
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (nth_bit < -1))
|
||||||
|
nth_bit = -1;
|
||||||
|
while (nth_bit < ((GLIB_SIZEOF_LONG * 8) - 1))
|
||||||
|
{
|
||||||
|
nth_bit++;
|
||||||
|
if (mask & (1UL << nth_bit))
|
||||||
|
return nth_bit;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
naive_bit_nth_msf (gulong mask, gint nth_bit)
|
||||||
|
{
|
||||||
|
if (nth_bit < 0 || G_UNLIKELY (nth_bit > GLIB_SIZEOF_LONG * 8))
|
||||||
|
nth_bit = GLIB_SIZEOF_LONG * 8;
|
||||||
|
while (nth_bit > 0)
|
||||||
|
{
|
||||||
|
nth_bit--;
|
||||||
|
if (mask & (1UL << nth_bit))
|
||||||
|
return nth_bit;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
naive_bit_storage (gulong number)
|
||||||
|
{
|
||||||
|
register guint n_bits = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
n_bits++;
|
||||||
|
number >>= 1;
|
||||||
|
}
|
||||||
|
while (number);
|
||||||
|
return n_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define TEST(f1, f2, i) \
|
||||||
|
if (f1 (i) != f2 (i)) { \
|
||||||
|
g_error (G_STRINGIFY (f1) " (%lu) = %d; " \
|
||||||
|
G_STRINGIFY (f2) " (%lu) = %d; ", \
|
||||||
|
i, f1 (i), \
|
||||||
|
i, f2 (i)); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
#define TEST2(f1, f2, i, n) \
|
||||||
|
if (f1 (i, n) != f2 (i, n)) { \
|
||||||
|
g_error (G_STRINGIFY (f1) " (%lu, %d) = %d; " \
|
||||||
|
G_STRINGIFY (f2) " (%lu, %d) = %d; ", \
|
||||||
|
i, n, f1 (i, n), \
|
||||||
|
i, n, f2 (i, n)); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
gulong i;
|
||||||
|
gint nth_bit;
|
||||||
|
|
||||||
|
/* we loop like this: 0, -1, 1, -2, 2, -3, 3, ... */
|
||||||
|
for (i = 0; (glong)i < 1500 ; i = -(i+((glong)i>=0))) {
|
||||||
|
|
||||||
|
#if TEST_BUILTINS
|
||||||
|
TEST (naive_bit_storage, builtin_bit_storage, i);
|
||||||
|
#endif
|
||||||
|
TEST (naive_bit_storage, g_bit_storage, i);
|
||||||
|
|
||||||
|
for (nth_bit = -3; nth_bit <= 2 + GLIB_SIZEOF_LONG * 8; nth_bit++) {
|
||||||
|
|
||||||
|
#if TEST_BUILTINS
|
||||||
|
TEST2 (naive_bit_nth_lsf, builtin_bit_nth_lsf1, i, nth_bit);
|
||||||
|
TEST2 (naive_bit_nth_lsf, builtin_bit_nth_lsf2, i, nth_bit);
|
||||||
|
#endif
|
||||||
|
TEST2 (naive_bit_nth_lsf, g_bit_nth_lsf, i, nth_bit);
|
||||||
|
|
||||||
|
#if TEST_BUILTINS
|
||||||
|
TEST2 (naive_bit_nth_msf, builtin_bit_nth_msf, i, nth_bit);
|
||||||
|
#endif
|
||||||
|
TEST2 (naive_bit_nth_msf, g_bit_nth_msf, i, nth_bit);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user