changeset 18017:0cd39f7f2409 stable

additional improvements for int64 ops implemented with long double (bug #40607) * oct-inttypes.h, oct-inttypes.cc: Ensure that conversions between 64-bit integer and long double are performed when long double rounding rules are in effect.
author John W. Eaton <jwe@octave.org>
date Tue, 26 Nov 2013 02:04:10 -0500
parents 683f9c39da06
children 9acd7b0f0639 5d42ffc6850a
files liboctave/util/oct-inttypes.cc liboctave/util/oct-inttypes.h
diffstat 2 files changed, 126 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/util/oct-inttypes.cc	Mon Nov 25 22:32:13 2013 -0800
+++ b/liboctave/util/oct-inttypes.cc	Tue Nov 26 02:04:10 2013 -0500
@@ -56,32 +56,58 @@
 
 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
 
-template <class xop>
-bool
-octave_int_cmp_op::external_mop (long double x, long double y)
-{
-   DECL_LONG_DOUBLE_ROUNDING
-
-   BEGIN_LONG_DOUBLE_ROUNDING ();
-
-   bool retval = xop::op (x, y);
-
-   END_LONG_DOUBLE_ROUNDING ();
+#define DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES(T) \
+  template <class xop> \
+  bool \
+  octave_int_cmp_op::external_mop (double x, T y) \
+  { \
+     DECL_LONG_DOUBLE_ROUNDING \
+   \
+     BEGIN_LONG_DOUBLE_ROUNDING (); \
+   \
+     bool retval = xop::op (static_cast<long double> (x), \
+                            static_cast<long double> (y)); \
+   \
+     END_LONG_DOUBLE_ROUNDING (); \
+   \
+     return retval; \
+  } \
+   \
+  template <class xop> \
+  bool \
+  octave_int_cmp_op::external_mop (T x, double y) \
+  { \
+     DECL_LONG_DOUBLE_ROUNDING \
+   \
+     BEGIN_LONG_DOUBLE_ROUNDING (); \
+   \
+     bool retval = xop::op (static_cast<long double> (x), \
+                            static_cast<long double> (y)); \
+   \
+     END_LONG_DOUBLE_ROUNDING (); \
+   \
+     return retval; \
+  }
 
-   return retval;
-}
+DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES (int64_t)
+DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES (uint64_t)
 
-#define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(OP) \
+#define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(OP, T) \
+  template OCTAVE_API bool \
+  octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (double, T); \
   template OCTAVE_API bool \
-  octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (long double, \
-                                                          long double)
+  octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (T, double)
 
-INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(lt);
-INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(le);
-INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(gt);
-INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(ge);
-INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(eq);
-INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(ne);
+#define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS(T) \
+  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (lt, T); \
+  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (le, T); \
+  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (gt, T); \
+  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (ge, T); \
+  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (eq, T); \
+  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (ne, T)
+
+INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS (int64_t);
+INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS (uint64_t);
 
 uint64_t
 octave_external_uint64_uint64_mul (uint64_t x, uint64_t y)
@@ -116,27 +142,43 @@
 // 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.
+// Similarly, the conversion from the 64-bit integer type to long double
+// must also occur in long double rounding mode.
 
-#define OCTAVE_LONG_DOUBLE_OP(RT, OP, NAME) \
-  RT \
-  RT ## _external_long_double_ ## NAME (long double x, long double y) \
+#define OCTAVE_LONG_DOUBLE_OP(T, OP, NAME) \
+  T \
+  external_double_ ## T ## _ ## NAME (double x, T y) \
   { \
     DECL_LONG_DOUBLE_ROUNDING \
  \
     BEGIN_LONG_DOUBLE_ROUNDING (); \
  \
-    RT retval = RT (x OP y); \
+    T retval = T (x OP static_cast<long double> (y.value ())); \
+ \
+    END_LONG_DOUBLE_ROUNDING (); \
+ \
+    return retval; \
+  } \
+ \
+  T \
+  external_ ## T ## _double_ ## NAME (T x, double y) \
+  { \
+    DECL_LONG_DOUBLE_ROUNDING \
+ \
+    BEGIN_LONG_DOUBLE_ROUNDING (); \
+ \
+    T retval = T (static_cast<long double> (x.value ()) OP y); \
  \
     END_LONG_DOUBLE_ROUNDING (); \
  \
     return retval; \
   }
 
-#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)
+#define OCTAVE_LONG_DOUBLE_OPS(T) \
+  OCTAVE_LONG_DOUBLE_OP (T, +, add); \
+  OCTAVE_LONG_DOUBLE_OP (T, -, sub); \
+  OCTAVE_LONG_DOUBLE_OP (T, *, mul); \
+  OCTAVE_LONG_DOUBLE_OP (T, /, div)
 
 OCTAVE_LONG_DOUBLE_OPS(octave_int64);
 OCTAVE_LONG_DOUBLE_OPS(octave_uint64);
--- a/liboctave/util/oct-inttypes.h	Mon Nov 25 22:32:13 2013 -0800
+++ b/liboctave/util/oct-inttypes.h	Tue Nov 26 02:04:10 2013 -0500
@@ -175,8 +175,14 @@
   { return xop::op (x, static_cast<double> (y)); }
 
 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
-  template <class xop> static OCTAVE_API bool
-  external_mop (long double, long double);
+#define DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS(T) \
+  template <class xop> static OCTAVE_API bool \
+  external_mop (double, T); \
+  template <class xop> static OCTAVE_API bool \
+  external_mop (T, double)
+
+  DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (int64_t);
+  DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (uint64_t);
 #endif
 
   // Typecasting to doubles won't work properly for 64-bit integers --
@@ -184,19 +190,31 @@
   // If we have long doubles, use them...
 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
-#define DEFINE_LONG_DOUBLE_CMP_OP(T1, T2) \
+#define DEFINE_LONG_DOUBLE_CMP_OP(T) \
+  template <class xop> \
+  static bool \
+  mop (double x, T y) \
+  { \
+    return external_mop<xop> (x, y); \
+  } \
   template <class xop> \
   static bool \
-  mop (T1 x, T2 y) \
+  mop (T x, double y) \
   { \
-    return external_mop<xop> (static_cast<long double> (x), \
-                              static_cast<long double> (y)); \
+    return external_mop<xop> (x, y); \
   }
 #else
-#define DEFINE_LONG_DOUBLE_CMP_OP(T1, T2) \
+#define DEFINE_LONG_DOUBLE_CMP_OP(T) \
   template <class xop> \
   static bool \
-  mop (T1 x, T2 y) \
+  mop (double x, T y) \
+  { \
+    return xop::op (static_cast<long double> (x), \
+                    static_cast<long double> (y)); \
+  } \
+  template <class xop> \
+  static bool \
+  mop (T x, double y) \
   { \
     return xop::op (static_cast<long double> (x), \
                     static_cast<long double> (y)); \
@@ -208,21 +226,27 @@
   // FIXME: We could declare directly the mop methods as external,
   // but we can't do this because bugs in gcc (<= 4.3) prevent
   // explicit instantiations later in that case.
-#define DEFINE_LONG_DOUBLE_CMP_OP(T1, T2) \
+#define DEFINE_LONG_DOUBLE_CMP_OP(T) \
   template <class xop> static OCTAVE_API bool \
-  emulate_mop (T1, T2); \
+  emulate_mop (double, T); \
   template <class xop> \
   static bool \
-  mop (T1 x, T2 y) \
+  mop (double x, T y) \
+    { \
+      return emulate_mop<xop> (x, y); \
+    } \
+  template <class xop> static OCTAVE_API bool \
+  emulate_mop (T, double); \
+  template <class xop> \
+  static bool \
+  mop (T x, double y) \
     { \
       return emulate_mop<xop> (x, y); \
     }
 #endif
 
-  DEFINE_LONG_DOUBLE_CMP_OP(double, uint64_t)
-  DEFINE_LONG_DOUBLE_CMP_OP(double, int64_t)
-  DEFINE_LONG_DOUBLE_CMP_OP(int64_t, double)
-  DEFINE_LONG_DOUBLE_CMP_OP(uint64_t, double)
+  DEFINE_LONG_DOUBLE_CMP_OP(int64_t)
+  DEFINE_LONG_DOUBLE_CMP_OP(uint64_t)
 
 #undef DEFINE_LONG_DOUBLE_CMP_OP
 };
@@ -1039,15 +1063,17 @@
 
 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
 
-#define DECLARE_EXTERNAL_LONG_DOUBLE_OP(RT, OP) \
-  extern OCTAVE_API RT \
-  RT ## _external_long_double_ ## OP (long double x, long double y)
+#define DECLARE_EXTERNAL_LONG_DOUBLE_OP(T, OP) \
+  extern OCTAVE_API T \
+  external_double_ ## T ## _ ## OP (double x, T y); \
+  extern OCTAVE_API T \
+  external_ ## T ## _double_ ## OP (T x, 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)
+#define DECLARE_EXTERNAL_LONG_DOUBLE_OPS(T) \
+  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, add); \
+  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, sub); \
+  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, mul); \
+  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, div)
 
 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_int64);
 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_uint64);
@@ -1073,33 +1099,25 @@
   inline octave_int64 \
   operator OP (const double& x, const octave_int64& y) \
   { \
-    return octave_int64_external_long_double_ ## NAME \
-     (static_cast<long double> (x), \
-      static_cast<long double> (y.value ())); \
+    return external_double_octave_int64_ ## NAME (x, y); \
   } \
   template <> \
   inline octave_uint64 \
   operator OP (const double& x, const octave_uint64& y) \
   { \
-    return octave_uint64_external_long_double_ ## NAME \
-     (static_cast<long double> (x), \
-      static_cast<long double> (y.value ())); \
+    return external_double_octave_uint64_ ## NAME (x, y); \
   } \
   template <> \
   inline octave_int64 \
   operator OP (const octave_int64& x, const double& y) \
   { \
-    return octave_int64_external_long_double_ ## NAME \
-     (static_cast<long double> (x.value ()), \
-      static_cast<long double> (y)); \
+    return external_octave_int64_double_ ## NAME (x, y); \
   } \
   template <> \
   inline octave_uint64 \
   operator OP (const octave_uint64& x, const double& y) \
   { \
-    return octave_uint64_external_long_double_ ## NAME \
-     (static_cast<long double> (x.value ()), \
-      static_cast<long double> (y)); \
+    return external_octave_uint64_double_ ## NAME (x, y); \
   }
 #else
 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \