Mercurial > hg > octave-nkf
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 +++ b/liboctave/util/oct-inttypes.cc @@ -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 +++ b/liboctave/util/oct-inttypes.h @@ -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 +++ b/oct-conf-post.in.h @@ -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