summaryrefslogtreecommitdiff
path: root/lib/vasnprintf.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2011-10-15 13:20:29 +0200
committerBruno Haible <bruno@clisp.org>2011-10-15 13:20:29 +0200
commit8f9c414718161f157f9970b3c97b977d0343093e (patch)
tree0575eef60cadb5f33789b18daa5e25d476691dc1 /lib/vasnprintf.c
parent3e89323b7976e230cc01744c046b825d049c7fa6 (diff)
downloadgnulib-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.c73
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. */