math: ilogb cleanup
authorSzabolcs Nagy <nsz@port70.net>
Mon, 2 Sep 2013 23:33:20 +0000 (23:33 +0000)
committerSzabolcs Nagy <nsz@port70.net>
Thu, 5 Sep 2013 11:30:07 +0000 (11:30 +0000)
* consistent code style
* explicit union instead of typedef for double and float bit access
* turn FENV_ACCESS ON to make 0/0.0f raise invalid flag
* (untested) ld128 version of ilogbl (used by logbl which has ld128 support)

src/math/ilogb.c
src/math/ilogbf.c
src/math/ilogbl.c

index 5a1819d85f4c31e1de8302095586eddea260d21a..64d40154d60ab065b8597d69faef4f76a2fac49d 100644 (file)
@@ -3,22 +3,24 @@
 
 int ilogb(double x)
 {
-       union dshape u = {x};
-       int e = u.bits>>52 & 0x7ff;
+       #pragma STDC FENV_ACCESS ON
+       union {double f; uint64_t i;} u = {x};
+       uint64_t i = u.i;
+       int e = i>>52 & 0x7ff;
 
        if (!e) {
-               u.bits <<= 12;
-               if (u.bits == 0) {
+               i <<= 12;
+               if (i == 0) {
                        FORCE_EVAL(0/0.0f);
                        return FP_ILOGB0;
                }
                /* subnormal x */
-               for (e = -0x3ff; u.bits < (uint64_t)1<<63; e--, u.bits<<=1);
+               for (e = -0x3ff; i>>63 == 0; e--, i<<=1);
                return e;
        }
        if (e == 0x7ff) {
                FORCE_EVAL(0/0.0f);
-               return u.bits<<12 ? FP_ILOGBNAN : INT_MAX;
+               return i<<12 ? FP_ILOGBNAN : INT_MAX;
        }
        return e - 0x3ff;
 }
index 42cd62e2dd9b37598c716b73825090fd74eb588a..e23ba209ec4cd1c7648ca903e6b3aa948c6dc053 100644 (file)
@@ -3,22 +3,24 @@
 
 int ilogbf(float x)
 {
-       union fshape u = {x};
-       int e = u.bits>>23 & 0xff;
+       #pragma STDC FENV_ACCESS ON
+       union {float f; uint32_t i;} u = {x};
+       uint32_t i = u.i;
+       int e = i>>23 & 0xff;
 
        if (!e) {
-               u.bits <<= 9;
-               if (u.bits == 0) {
+               i <<= 9;
+               if (i == 0) {
                        FORCE_EVAL(0/0.0f);
                        return FP_ILOGB0;
                }
                /* subnormal x */
-               for (e = -0x7f; u.bits < (uint32_t)1<<31; e--, u.bits<<=1);
+               for (e = -0x7f; i>>31 == 0; e--, i<<=1);
                return e;
        }
        if (e == 0xff) {
                FORCE_EVAL(0/0.0f);
-               return u.bits<<9 ? FP_ILOGBNAN : INT_MAX;
+               return i<<9 ? FP_ILOGBNAN : INT_MAX;
        }
        return e - 0x7f;
 }
index 7df6eb6c96e16e5dfd22ce11920125ccb9b6d03a..7b1a9cf8d007ff16c1d6fe072916a5a8a226e3e3 100644 (file)
@@ -9,23 +9,46 @@ int ilogbl(long double x)
 #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
 int ilogbl(long double x)
 {
+       #pragma STDC FENV_ACCESS ON
        union ldshape u = {x};
        uint64_t m = u.i.m;
        int e = u.i.se & 0x7fff;
 
        if (!e) {
                if (m == 0) {
-                       FORCE_EVAL(x/x);
+                       FORCE_EVAL(0/0.0f);
                        return FP_ILOGB0;
                }
                /* subnormal x */
-               for (e = -0x3fff+1; m < (uint64_t)1<<63; e--, m<<=1);
+               for (e = -0x3fff+1; m>>63 == 0; e--, m<<=1);
                return e;
        }
        if (e == 0x7fff) {
                FORCE_EVAL(0/0.0f);
-               /* in ld80 msb is set in inf */
-               return m << 1 ? FP_ILOGBNAN : INT_MAX;
+               return m<<1 ? FP_ILOGBNAN : INT_MAX;
+       }
+       return e - 0x3fff;
+}
+#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
+int ilogbl(long double x)
+{
+       #pragma STDC FENV_ACCESS ON
+       union ldshape u = {x};
+       int e = u.i.se & 0x7fff;
+
+       if (!e) {
+               if (x == 0) {
+                       FORCE_EVAL(0/0.0f);
+                       return FP_ILOGB0;
+               }
+               /* subnormal x */
+               x *= 0x1p120;
+               return ilogbl(x) - 120;
+       }
+       if (e == 0x7fff) {
+               FORCE_EVAL(0/0.0f);
+               u.i.se = 0;
+               return u.f ? FP_ILOGBNAN : INT_MAX;
        }
        return e - 0x3fff;
 }