[Numpy-svn] r8521 - in branches/1.5.x/numpy/core/src: npymath private
numpy-svn at scipy.org
numpy-svn at scipy.org
Sat Jul 24 06:43:02 EDT 2010
Author: ptvirtan
Date: 2010-07-24 05:43:02 -0500 (Sat, 24 Jul 2010)
New Revision: 8521
Modified:
branches/1.5.x/numpy/core/src/npymath/ieee754.c.src
branches/1.5.x/numpy/core/src/private/npy_fpmath.h
Log:
BUG: quick and ugly fix for long double on linux ppc.
(cherry picked from commit r8511)
Modified: branches/1.5.x/numpy/core/src/npymath/ieee754.c.src
===================================================================
--- branches/1.5.x/numpy/core/src/npymath/ieee754.c.src 2010-07-24 10:42:41 UTC (rev 8520)
+++ branches/1.5.x/numpy/core/src/npymath/ieee754.c.src 2010-07-24 10:43:02 UTC (rev 8521)
@@ -126,8 +126,131 @@
return x;
}
+#ifdef HAVE_LDOUBLE_DOUBLE_DOUBLE_BE
+
+/*
+ * FIXME: this is ugly and untested. The asm part only works with gcc, and we
+ * should consolidate the GET_LDOUBLE* / SET_LDOUBLE macros
+ */
+#define math_opt_barrier(x) \
+ ({ __typeof (x) __x = x; __asm ("" : "+m" (__x)); __x; })
+#define math_force_eval(x) __asm __volatile ("" : : "m" (x))
+
+/* only works for big endian */
+typedef union
+{
+ npy_longdouble value;
+ struct
+ {
+ npy_uint64 msw;
+ npy_uint64 lsw;
+ } parts64;
+ struct
+ {
+ npy_uint32 w0, w1, w2, w3;
+ } parts32;
+} ieee854_long_double_shape_type;
+
+/* Get two 64 bit ints from a long double. */
+
+#define GET_LDOUBLE_WORDS64(ix0,ix1,d) \
+do { \
+ ieee854_long_double_shape_type qw_u; \
+ qw_u.value = (d); \
+ (ix0) = qw_u.parts64.msw; \
+ (ix1) = qw_u.parts64.lsw; \
+} while (0)
+
+/* Set a long double from two 64 bit ints. */
+
+#define SET_LDOUBLE_WORDS64(d,ix0,ix1) \
+do { \
+ ieee854_long_double_shape_type qw_u; \
+ qw_u.parts64.msw = (ix0); \
+ qw_u.parts64.lsw = (ix1); \
+ (d) = qw_u.value; \
+} while (0)
+
npy_longdouble _nextl(npy_longdouble x, int p)
{
+ npy_int64 hx,ihx,ilx;
+ npy_uint64 lx;
+
+ GET_LDOUBLE_WORDS64(hx, lx, x);
+ ihx = hx & 0x7fffffffffffffffLL; /* |hx| */
+ ilx = lx & 0x7fffffffffffffffLL; /* |lx| */
+
+ if(((ihx & 0x7ff0000000000000LL)==0x7ff0000000000000LL)&&
+ ((ihx & 0x000fffffffffffffLL)!=0)) {
+ return x; /* signal the nan */
+ }
+ if(ihx == 0 && ilx == 0) { /* x == 0 */
+ npy_longdouble u;
+ SET_LDOUBLE_WORDS64(x, p, 0ULL);/* return +-minsubnormal */
+ u = x * x;
+ if (u == x) {
+ return u;
+ } else {
+ return x; /* raise underflow flag */
+ }
+ }
+
+ npy_longdouble u;
+ if(p < 0) { /* p < 0, x -= ulp */
+ if((hx==0xffefffffffffffffLL)&&(lx==0xfc8ffffffffffffeLL))
+ return x+x; /* overflow, return -inf */
+ if (hx >= 0x7ff0000000000000LL) {
+ SET_LDOUBLE_WORDS64(u,0x7fefffffffffffffLL,0x7c8ffffffffffffeLL);
+ return u;
+ }
+ if(ihx <= 0x0360000000000000LL) { /* x <= LDBL_MIN */
+ u = math_opt_barrier (x);
+ x -= __LDBL_DENORM_MIN__;
+ if (ihx < 0x0360000000000000LL
+ || (hx > 0 && (npy_int64) lx <= 0)
+ || (hx < 0 && (npy_int64) lx > 1)) {
+ u = u * u;
+ math_force_eval (u); /* raise underflow flag */
+ }
+ return x;
+ }
+ if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */
+ SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL);
+ u *= 0x1.0000000000000p-105L;
+ } else
+ SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL);
+ return x - u;
+ } else { /* p >= 0, x += ulp */
+ if((hx==0x7fefffffffffffffLL)&&(lx==0x7c8ffffffffffffeLL))
+ return x+x; /* overflow, return +inf */
+ if ((npy_uint64) hx >= 0xfff0000000000000ULL) {
+ SET_LDOUBLE_WORDS64(u,0xffefffffffffffffLL,0xfc8ffffffffffffeLL);
+ return u;
+ }
+ if(ihx <= 0x0360000000000000LL) { /* x <= LDBL_MIN */
+ u = math_opt_barrier (x);
+ x += __LDBL_DENORM_MIN__;
+ if (ihx < 0x0360000000000000LL
+ || (hx > 0 && (npy_int64) lx < 0 && lx != 0x8000000000000001LL)
+ || (hx < 0 && (npy_int64) lx >= 0)) {
+ u = u * u;
+ math_force_eval (u); /* raise underflow flag */
+ }
+ if (x == 0.0L) /* handle negative __LDBL_DENORM_MIN__ case */
+ x = -0.0L;
+ return x;
+ }
+ if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */
+ SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL);
+ u *= 0x1.0000000000000p-105L;
+ } else
+ SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL);
+ return x + u;
+ }
+}
+#else
+npy_longdouble _nextl(npy_longdouble x, int p)
+{
volatile npy_longdouble t;
union IEEEl2bitsrep ux;
@@ -188,6 +311,7 @@
return ux.e;
}
+#endif
/*
* nextafter code taken from BSD math lib, the code contains the following
Modified: branches/1.5.x/numpy/core/src/private/npy_fpmath.h
===================================================================
--- branches/1.5.x/numpy/core/src/private/npy_fpmath.h 2010-07-24 10:42:41 UTC (rev 8520)
+++ branches/1.5.x/numpy/core/src/private/npy_fpmath.h 2010-07-24 10:43:02 UTC (rev 8521)
@@ -39,7 +39,8 @@
defined(HAVE_LDOUBLE_IEEE_DOUBLE_BE) || \
defined(HAVE_LDOUBLE_IEEE_DOUBLE_16_BYTES_BE) || \
defined(HAVE_LDOUBLE_INTEL_EXTENDED_16_BYTES_LE) || \
- defined(HAVE_LDOUBLE_INTEL_EXTENDED_12_BYTES_LE))
+ defined(HAVE_LDOUBLE_INTEL_EXTENDED_12_BYTES_LE) || \
+ defined(HAVE_LDOUBLE_DOUBLE_DOUBLE_BE))
#error No long double representation defined
#endif
More information about the Numpy-svn
mailing list