diff liboctave/util/oct-inttypes.h @ 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 79653c5b6147
children 8e056300994b 284e5c87f27b
line wrap: on
line diff
--- 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) \