From: Bruno Haible Date: Sat, 15 Oct 2011 11:20:29 +0000 (+0200) Subject: vasnprintf: Optimize bit search operation. X-Git-Tag: v0.1~1567 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=8f9c414718161f157f9970b3c97b977d0343093e;p=gnulib.git vasnprintf: Optimize bit search operation. * lib/vasnprintf.c (divide): Use optimizations from integer_length.c. * m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF): Require gl_DOUBLE_EXPONENT_LOCATION. * modules/vasnprintf (Files): Add m4/exponentd.m4. * modules/unistdio/u8-vasnprintf (Files): Likewise. * modules/unistdio/u8-u8-vasnprintf (Files): Likewise. * modules/unistdio/u16-vasnprintf (Files): Likewise. * modules/unistdio/u16-u16-vasnprintf (Files): Likewise. * modules/unistdio/u32-vasnprintf (Files): Likewise. * modules/unistdio/u32-u32-vasnprintf (Files): Likewise. * modules/unistdio/ulc-vasnprintf (Files): Likewise. * m4/isnand.m4 (gl_PREREQ_ISNAND): Use AC_REQUIRE. --- diff --git a/ChangeLog b/ChangeLog index 43024b3415..ee724cd329 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-10-15 Bruno Haible + + vasnprintf: Optimize bit search operation. + * lib/vasnprintf.c (divide): Use optimizations from integer_length.c. + * m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF): Require + gl_DOUBLE_EXPONENT_LOCATION. + * modules/vasnprintf (Files): Add m4/exponentd.m4. + * modules/unistdio/u8-vasnprintf (Files): Likewise. + * modules/unistdio/u8-u8-vasnprintf (Files): Likewise. + * modules/unistdio/u16-vasnprintf (Files): Likewise. + * modules/unistdio/u16-u16-vasnprintf (Files): Likewise. + * modules/unistdio/u32-vasnprintf (Files): Likewise. + * modules/unistdio/u32-u32-vasnprintf (Files): Likewise. + * modules/unistdio/ulc-vasnprintf (Files): Likewise. + * m4/isnand.m4 (gl_PREREQ_ISNAND): Use AC_REQUIRE. + 2011-10-15 Bruno Haible vasnprintf: Fix comments. diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 9c22475222..40789f9ebb 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -553,32 +553,61 @@ divide (mpn_t a, mpn_t b, mpn_t *q) size_t s; { mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */ - s = 31; - if (msd >= 0x10000) - { - msd = msd >> 16; - s -= 16; - } - if (msd >= 0x100) - { - msd = msd >> 8; - s -= 8; - } - if (msd >= 0x10) - { - msd = msd >> 4; - s -= 4; - } - if (msd >= 0x4) + /* Determine s = GMP_LIMB_BITS - integer_length (msd). + Code copied from gnulib's integer_length.c. */ +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + s = __builtin_clz (msd); +# else +# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT + if (GMP_LIMB_BITS <= DBL_MANT_BIT) { - msd = msd >> 2; - s -= 2; + /* Use 'double' operations. + Assumes an IEEE 754 'double' implementation. */ +# define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7) +# define DBL_EXP_BIAS (DBL_EXP_MASK / 2 - 1) +# define NWORDS \ + ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) + union { double value; unsigned int word[NWORDS]; } m; + + /* Use a single integer to floating-point conversion. */ + m.value = msd; + + s = GMP_LIMB_BITS + - (((m.word[DBL_EXPBIT0_WORD] >> DBL_EXPBIT0_BIT) & DBL_EXP_MASK) + - DBL_EXP_BIAS); } - if (msd >= 0x2) + else +# undef NWORDS +# endif { - msd = msd >> 1; - s -= 1; + s = 31; + if (msd >= 0x10000) + { + msd = msd >> 16; + s -= 16; + } + if (msd >= 0x100) + { + msd = msd >> 8; + s -= 8; + } + if (msd >= 0x10) + { + msd = msd >> 4; + s -= 4; + } + if (msd >= 0x4) + { + msd = msd >> 2; + s -= 2; + } + if (msd >= 0x2) + { + msd = msd >> 1; + s -= 1; + } } +# endif } /* 0 <= s < GMP_LIMB_BITS. Copy b, shifting it left by s bits. */ diff --git a/m4/isnand.m4 b/m4/isnand.m4 index 2b18b0ac6d..48f1a48078 100644 --- a/m4/isnand.m4 +++ b/m4/isnand.m4 @@ -1,4 +1,4 @@ -# isnand.m4 serial 10 +# isnand.m4 serial 11 dnl Copyright (C) 2007-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -43,7 +43,7 @@ AC_DEFUN([gl_FUNC_ISNAND_NO_LIBM], dnl Prerequisites of replacement isnand definition. It does not need -lm. AC_DEFUN([gl_PREREQ_ISNAND], [ - gl_DOUBLE_EXPONENT_LOCATION + AC_REQUIRE([gl_DOUBLE_EXPONENT_LOCATION]) ]) dnl Test whether isnand() can be used with libm. diff --git a/m4/vasnprintf.m4 b/m4/vasnprintf.m4 index 749d708d9e..da0a6d9efc 100644 --- a/m4/vasnprintf.m4 +++ b/m4/vasnprintf.m4 @@ -1,4 +1,4 @@ -# vasnprintf.m4 serial 33 +# vasnprintf.m4 serial 34 dnl Copyright (C) 2002-2004, 2006-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -64,6 +64,9 @@ AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF], dnl Use the _snprintf function only if it is declared (because on NetBSD it dnl is defined as a weak alias of snprintf; we prefer to use the latter). AC_CHECK_DECLS([_snprintf], , , [[#include ]]) + dnl Knowing DBL_EXPBIT0_WORD and DBL_EXPBIT0_BIT enables an optimization + dnl in the code for NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE. + AC_REQUIRE([gl_DOUBLE_EXPONENT_LOCATION]) dnl We can avoid a lot of code by assuming that snprintf's return value dnl conforms to ISO C99. So check that. AC_REQUIRE([gl_SNPRINTF_RETVAL_C99]) diff --git a/modules/unistdio/u16-u16-vasnprintf b/modules/unistdio/u16-u16-vasnprintf index d9e37e23ad..7a7f46f111 100644 --- a/modules/unistdio/u16-u16-vasnprintf +++ b/modules/unistdio/u16-u16-vasnprintf @@ -13,6 +13,7 @@ m4/longlong.m4 m4/intmax_t.m4 m4/stdint_h.m4 m4/inttypes_h.m4 +m4/exponentd.m4 Depends-on: unistdio/base diff --git a/modules/unistdio/u16-vasnprintf b/modules/unistdio/u16-vasnprintf index 21d19bd0ff..09e1330b46 100644 --- a/modules/unistdio/u16-vasnprintf +++ b/modules/unistdio/u16-vasnprintf @@ -13,6 +13,7 @@ m4/longlong.m4 m4/intmax_t.m4 m4/stdint_h.m4 m4/inttypes_h.m4 +m4/exponentd.m4 Depends-on: unistdio/base diff --git a/modules/unistdio/u32-u32-vasnprintf b/modules/unistdio/u32-u32-vasnprintf index c239248ad7..ac248bacb6 100644 --- a/modules/unistdio/u32-u32-vasnprintf +++ b/modules/unistdio/u32-u32-vasnprintf @@ -13,6 +13,7 @@ m4/longlong.m4 m4/intmax_t.m4 m4/stdint_h.m4 m4/inttypes_h.m4 +m4/exponentd.m4 Depends-on: unistdio/base diff --git a/modules/unistdio/u32-vasnprintf b/modules/unistdio/u32-vasnprintf index d73ddc8c30..6539a3ecb6 100644 --- a/modules/unistdio/u32-vasnprintf +++ b/modules/unistdio/u32-vasnprintf @@ -13,6 +13,7 @@ m4/longlong.m4 m4/intmax_t.m4 m4/stdint_h.m4 m4/inttypes_h.m4 +m4/exponentd.m4 Depends-on: unistdio/base diff --git a/modules/unistdio/u8-u8-vasnprintf b/modules/unistdio/u8-u8-vasnprintf index 5cc91503e1..52d3c44243 100644 --- a/modules/unistdio/u8-u8-vasnprintf +++ b/modules/unistdio/u8-u8-vasnprintf @@ -13,6 +13,7 @@ m4/longlong.m4 m4/intmax_t.m4 m4/stdint_h.m4 m4/inttypes_h.m4 +m4/exponentd.m4 Depends-on: unistdio/base diff --git a/modules/unistdio/u8-vasnprintf b/modules/unistdio/u8-vasnprintf index 049e5c1f8e..adb9616886 100644 --- a/modules/unistdio/u8-vasnprintf +++ b/modules/unistdio/u8-vasnprintf @@ -13,6 +13,7 @@ m4/longlong.m4 m4/intmax_t.m4 m4/stdint_h.m4 m4/inttypes_h.m4 +m4/exponentd.m4 Depends-on: unistdio/base diff --git a/modules/unistdio/ulc-vasnprintf b/modules/unistdio/ulc-vasnprintf index c3563c5e32..8caa7ec7b8 100644 --- a/modules/unistdio/ulc-vasnprintf +++ b/modules/unistdio/ulc-vasnprintf @@ -13,6 +13,7 @@ m4/longlong.m4 m4/intmax_t.m4 m4/stdint_h.m4 m4/inttypes_h.m4 +m4/exponentd.m4 Depends-on: unistdio/base diff --git a/modules/vasnprintf b/modules/vasnprintf index da6b28056c..54db892684 100644 --- a/modules/vasnprintf +++ b/modules/vasnprintf @@ -19,6 +19,7 @@ m4/inttypes_h.m4 m4/vasnprintf.m4 m4/printf.m4 m4/math_h.m4 +m4/exponentd.m4 Depends-on: alloca-opt