about summary refs log tree commit diff
path: root/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c
diff options
context:
space:
mode:
authorAdhemerval Zanella <azanella@linux.vnet.ibm.com>2012-05-10 15:11:55 -0500
committerRyan S. Arnold <rsa@linux.vnet.ibm.com>2012-05-10 15:11:55 -0500
commit89c9aa491a7cee97bf78a29cddbf0a25c902a671 (patch)
treea03f7f7a4864421a67c1f4ba3c4ad74090cc0e63 /sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c
parent021db4be6f1f4189f66feee066a495d49e92b93e (diff)
downloadglibc-89c9aa491a7cee97bf78a29cddbf0a25c902a671.tar.gz
glibc-89c9aa491a7cee97bf78a29cddbf0a25c902a671.tar.xz
glibc-89c9aa491a7cee97bf78a29cddbf0a25c902a671.zip
Fix for logb/logbf/logbl (bugs 13954/13955/13956)
POSIX 2008 states that if the input for 'logb[f|l]' is a subnormal number
it should be treated as if it were normalized.  This means the
implementation should calculate the log2 of the mantissa and add it to the
subnormal exponent (-126 for float and -1022 for double and IBM long
double).  This patch takes care of that.
Diffstat (limited to 'sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c')
-rw-r--r--sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c
index 2ad6c7ddbd..474eeef36b 100644
--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c
+++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_logb.c
@@ -1,5 +1,5 @@
 /* Compute radix independent exponent.
-   Copyright (C) 2011 Free Software Foundation, Inc.
+   Copyright (C) 2011, 2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gmail.com>, 2011.
 
@@ -25,16 +25,21 @@
 double
 __logb (double x)
 {
-  int64_t ix;
+  int64_t ix, ex;
 
   EXTRACT_WORDS64 (ix, x);
   ix &= UINT64_C(0x7fffffffffffffff);
   if (ix == 0)
     return -1.0 / fabs (x);
-  unsigned int ex = ix >> 52;
+  ex = ix >> 52;
   if (ex == 0x7ff)
     return x * x;
-  return ex == 0 ? -1022.0 : (double) (ex - 1023);
+  if (__builtin_expect (ex == 0, 0))
+    {
+      int m = (ix == 0) ? 0 : __builtin_clzl (ix);
+      return -1022.0 + (double)(11 -m);
+    }
+  return (double) (ex - 1023);
 }
 weak_alias (__logb, logb)
 #ifdef NO_LONG_DOUBLE