# HG changeset patch # User John W. Eaton # Date 1385414687 18000 # Node ID 79653c5b614716e9cda49be6b639de9f3ffe2d93 # Parent b001d9e9fd1730802ebbb4d1d118561090d1c698 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. diff -r b001d9e9fd17 -r 79653c5b6147 liboctave/util/oct-inttypes.cc --- 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 diff -r b001d9e9fd17 -r 79653c5b6147 liboctave/util/oct-inttypes.h --- 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 octave_uint32; typedef octave_int 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 \ @@ -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 (x), \ - static_cast (y.value ()))); \ + return octave_int64_external_long_double_ ## NAME \ + (static_cast (x), \ + static_cast (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 (x), \ - static_cast (y.value ()))); \ + return octave_uint64_external_long_double_ ## NAME \ + (static_cast (x), \ + static_cast (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 (x.value ()), \ - static_cast (y))); \ + return octave_int64_external_long_double_ ## NAME \ + (static_cast (x.value ()), \ + static_cast (y)); \ } \ template <> \ inline octave_uint64 \ operator OP (const octave_uint64& x, const double& y) \ { \ - return octave_uint64 \ - (octave_external_long_double_ ## NAME \ - (static_cast (x.value ()), \ - static_cast (y))); \ + return octave_uint64_external_long_double_ ## NAME \ + (static_cast (x.value ()), \ + static_cast (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 \ diff -r b001d9e9fd17 -r 79653c5b6147 oct-conf-post.in.h --- 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