# HG changeset patch # User John W. Eaton # Date 1385449450 18000 # Node ID 0cd39f7f2409e2101d422b531897c65719a73cad # Parent 683f9c39da0680117eecd38aa807754cae985ecf 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. diff -r 683f9c39da06 -r 0cd39f7f2409 liboctave/util/oct-inttypes.cc --- 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 -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 \ + 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 (x), \ + static_cast (y)); \ + \ + END_LONG_DOUBLE_ROUNDING (); \ + \ + return retval; \ + } \ + \ + template \ + 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 (x), \ + static_cast (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 (double, T); \ template OCTAVE_API bool \ - octave_int_cmp_op::external_mop (long double, \ - long double) + octave_int_cmp_op::external_mop (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 (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 (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); diff -r 683f9c39da06 -r 0cd39f7f2409 liboctave/util/oct-inttypes.h --- 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 (y)); } #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED - template static OCTAVE_API bool - external_mop (long double, long double); +#define DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS(T) \ + template static OCTAVE_API bool \ + external_mop (double, T); \ + template 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 \ + static bool \ + mop (double x, T y) \ + { \ + return external_mop (x, y); \ + } \ template \ static bool \ - mop (T1 x, T2 y) \ + mop (T x, double y) \ { \ - return external_mop (static_cast (x), \ - static_cast (y)); \ + return external_mop (x, y); \ } #else -#define DEFINE_LONG_DOUBLE_CMP_OP(T1, T2) \ +#define DEFINE_LONG_DOUBLE_CMP_OP(T) \ template \ static bool \ - mop (T1 x, T2 y) \ + mop (double x, T y) \ + { \ + return xop::op (static_cast (x), \ + static_cast (y)); \ + } \ + template \ + static bool \ + mop (T x, double y) \ { \ return xop::op (static_cast (x), \ static_cast (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 static OCTAVE_API bool \ - emulate_mop (T1, T2); \ + emulate_mop (double, T); \ template \ static bool \ - mop (T1 x, T2 y) \ + mop (double x, T y) \ + { \ + return emulate_mop (x, y); \ + } \ + template static OCTAVE_API bool \ + emulate_mop (T, double); \ + template \ + static bool \ + mop (T x, double y) \ { \ return emulate_mop (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 (x), \ - static_cast (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 (x), \ - static_cast (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 (x.value ()), \ - static_cast (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 (x.value ()), \ - static_cast (y)); \ + return external_octave_uint64_double_ ## NAME (x, y); \ } #else #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \