diff options
author | Bruno Haible <bruno@clisp.org> | 2011-10-15 13:20:29 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2011-10-15 13:20:29 +0200 |
commit | 8f9c414718161f157f9970b3c97b977d0343093e (patch) | |
tree | 0575eef60cadb5f33789b18daa5e25d476691dc1 /lib/vasnprintf.c | |
parent | 3e89323b7976e230cc01744c046b825d049c7fa6 (diff) | |
download | gnulib-8f9c414718161f157f9970b3c97b977d0343093e.tar.gz |
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.
Diffstat (limited to 'lib/vasnprintf.c')
-rw-r--r-- | lib/vasnprintf.c | 73 |
1 files changed, 51 insertions, 22 deletions
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. */ |