changeset 18005:79653c5b6147

make int64 ops implemented with long double work again (bug #40607) * oct-conf-post.in.h : Use SIZEOF_LONG_DOUBLE < 16 in condition used to define OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED. * oct-inttypes.h, oct-inttypes.cc: Return octave_int64 or octave_uint64 from external long double operation functions instead of returning long double.
author John W. Eaton <jwe@octave.org>
date Mon, 25 Nov 2013 16:24:47 -0500
parents b001d9e9fd17
children b992a17767fe
files liboctave/util/oct-inttypes.cc liboctave/util/oct-inttypes.h oct-conf-post.in.h
diffstat 3 files changed, 46 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/util/oct-inttypes.cc	Mon Nov 25 20:39:44 2013 +0100
+++ b/liboctave/util/oct-inttypes.cc	Mon Nov 25 16:24:47 2013 -0500
@@ -111,25 +111,35 @@
   return retval;
 }
 
-#define OCTAVE_LONG_DOUBLE_OP(OP, NAME) \
-  long double \
-  octave_external_long_double_ ## NAME (long double x, long double y) \
+// Note that if we return long double it is apparently possible for
+// truncation to happen at the point of storing the result in retval,
+// which can happen after we end long double rounding.  Attempt to avoid
+// that problem by storing the full precision temporary value in the
+// integer value before we end the long double rounding mode.
+
+#define OCTAVE_LONG_DOUBLE_OP(RT, OP, NAME) \
+  RT \
+  RT ## _external_long_double_ ## NAME (long double x, long double y) \
   { \
     DECL_LONG_DOUBLE_ROUNDING \
  \
     BEGIN_LONG_DOUBLE_ROUNDING (); \
  \
-    long double retval = x OP y; \
+    RT retval = RT (x OP y); \
  \
     END_LONG_DOUBLE_ROUNDING (); \
  \
     return retval; \
   }
 
-OCTAVE_LONG_DOUBLE_OP (+, add)
-OCTAVE_LONG_DOUBLE_OP (-, sub)
-OCTAVE_LONG_DOUBLE_OP (*, mul)
-OCTAVE_LONG_DOUBLE_OP (/, div)
+#define OCTAVE_LONG_DOUBLE_OPS(RT) \
+  OCTAVE_LONG_DOUBLE_OP (RT, +, add); \
+  OCTAVE_LONG_DOUBLE_OP (RT, -, sub); \
+  OCTAVE_LONG_DOUBLE_OP (RT, *, mul); \
+  OCTAVE_LONG_DOUBLE_OP (RT, /, div)
+
+OCTAVE_LONG_DOUBLE_OPS(octave_int64);
+OCTAVE_LONG_DOUBLE_OPS(octave_uint64);
 
 #endif
 
--- a/liboctave/util/oct-inttypes.h	Mon Nov 25 20:39:44 2013 +0100
+++ b/liboctave/util/oct-inttypes.h	Mon Nov 25 16:24:47 2013 -0500
@@ -1037,17 +1037,22 @@
 typedef octave_int<uint32_t> octave_uint32;
 typedef octave_int<uint64_t> octave_uint64;
 
-extern OCTAVE_API long double
-octave_external_long_double_add (long double x, long double y);
+#ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
 
-extern OCTAVE_API long double
-octave_external_long_double_sub (long double x, long double y);
+#define DECLARE_EXTERNAL_LONG_DOUBLE_OP(RT, OP) \
+  extern OCTAVE_API RT \
+  RT ## _external_long_double_ ## OP (long double x, long double y)
 
-extern OCTAVE_API long double
-octave_external_long_double_mul (long double x, long double y);
+#define DECLARE_EXTERNAL_LONG_DOUBLE_OPS(RT) \
+  DECLARE_EXTERNAL_LONG_DOUBLE_OP (RT, add); \
+  DECLARE_EXTERNAL_LONG_DOUBLE_OP (RT, sub); \
+  DECLARE_EXTERNAL_LONG_DOUBLE_OP (RT, mul); \
+  DECLARE_EXTERNAL_LONG_DOUBLE_OP (RT, div)
 
-extern OCTAVE_API long double
-octave_external_long_double_div (long double x, long double y);
+DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_int64);
+DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_uint64);
+
+#endif
 
 #define OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
   template <class T> \
@@ -1068,37 +1073,33 @@
   inline octave_int64 \
   operator OP (const double& x, const octave_int64& y) \
   { \
-    return octave_int64 \
-      (octave_external_long_double_ ## NAME \
-       (static_cast<long double> (x), \
-        static_cast<long double> (y.value ()))); \
+    return octave_int64_external_long_double_ ## NAME \
+     (static_cast<long double> (x), \
+      static_cast<long double> (y.value ())); \
   } \
   template <> \
   inline octave_uint64 \
   operator OP (const double& x, const octave_uint64& y) \
   { \
-    return octave_uint64 \
-      (octave_external_long_double_ ## NAME \
-       (static_cast<long double> (x), \
-        static_cast<long double> (y.value ()))); \
+    return octave_uint64_external_long_double_ ## NAME \
+     (static_cast<long double> (x), \
+      static_cast<long double> (y.value ())); \
   } \
   template <> \
   inline octave_int64 \
   operator OP (const octave_int64& x, const double& y) \
   { \
-    return octave_int64 \
-      (octave_external_long_double_ ## NAME \
-       (static_cast<long double> (x.value ()), \
-        static_cast<long double> (y))); \
+    return octave_int64_external_long_double_ ## NAME \
+     (static_cast<long double> (x.value ()), \
+      static_cast<long double> (y)); \
   } \
   template <> \
   inline octave_uint64 \
   operator OP (const octave_uint64& x, const double& y) \
   { \
-    return octave_uint64 \
-      (octave_external_long_double_ ## NAME \
-       (static_cast<long double> (x.value ()), \
-        static_cast<long double> (y))); \
+    return octave_uint64_external_long_double_ ## NAME \
+     (static_cast<long double> (x.value ()), \
+      static_cast<long double> (y)); \
   }
 #else
 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
@@ -1154,6 +1155,8 @@
 
 #undef OCTAVE_INT_DOUBLE_BIN_OP0
 #undef OCTAVE_INT_DOUBLE_BIN_OP
+#undef DECLARE_EXTERNAL_LONG_DOUBLE_OP
+#undef DECLARE_EXTERNAL_LONG_DOUBLE_OPS
 
 #define OCTAVE_INT_DOUBLE_CMP_OP(OP,NAME) \
   template <class T> \
--- a/oct-conf-post.in.h	Mon Nov 25 20:39:44 2013 +0100
+++ b/oct-conf-post.in.h	Mon Nov 25 16:24:47 2013 -0500
@@ -108,7 +108,7 @@
    FIXME: Maybe substitute this by a more precise check in the future?  */
 #if (SIZEOF_LONG_DOUBLE >= 10) && defined (HAVE_ROUNDL)
 # define OCTAVE_INT_USE_LONG_DOUBLE
-# if (SIZEOF_LONG_DOUBLE == 10 \
+# if (SIZEOF_LONG_DOUBLE < 16 \
       && (defined __i386__ || defined __x86_64__) && defined __GNUC__)
 #define OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED 1
 # endif