Mercurial > octave
changeset 25844:dd10eea0be97
maint: Merge stable to default.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 30 Aug 2018 10:45:51 -0400 |
parents | e9910742d968 (current diff) 144820478378 (diff) |
children | aa4e0ca9873b |
files | configure.ac liboctave/util/oct-inttypes.h m4/acinclude.m4 |
diffstat | 5 files changed, 34 insertions(+), 234 deletions(-) [+] |
line wrap: on
line diff
--- a/build-aux/mk-octave-config-h.sh Wed Aug 29 14:34:24 2018 -0700 +++ b/build-aux/mk-octave-config-h.sh Thu Aug 30 10:45:51 2018 -0400 @@ -196,7 +196,6 @@ $SED -n 's/#\(\(undef\|define\) OCTAVE_ENABLE_ATOMIC_REFCOUNT.*$\)/# \1/p' $config_h_file $SED -n 's/#\(\(undef\|define\) OCTAVE_ENABLE_BOUNDS_CHECK.*$\)/# \1/p' $config_h_file $SED -n 's/#\(\(undef\|define\) OCTAVE_ENABLE_OPENMP.*$\)/# \1/p' $config_h_file -$SED -n 's/#\(\(undef\|define\) OCTAVE_HAVE_FAST_INT_OPS.*$\)/# \1/p' $config_h_file $SED -n 's/#\(\(undef\|define\) OCTAVE_HAVE_LONG_LONG_INT.*$\)/# \1/p' $config_h_file $SED -n 's/#\(\(undef\|define\) OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT.*$\)/# \1/p' $config_h_file $SED -n 's/#\(\(undef\|define\) OCTAVE_HAVE_OVERLOAD_CHAR_INT8_TYPES.*$\)/# \1/p' $config_h_file
--- a/configure.ac Wed Aug 29 14:34:24 2018 -0700 +++ b/configure.ac Thu Aug 30 10:45:51 2018 -0400 @@ -1120,9 +1120,6 @@ ## Are there functions to access real/imag parts of numbers via references? OCTAVE_CXX_COMPLEX_REFERENCE_ACCESSORS -## Check if fast integer arithmetics based on bit tricks is available. -OCTAVE_FAST_INT_OPS - ## Does the C compiler handle alloca and const correctly? AC_FUNC_ALLOCA
--- a/liboctave/util/oct-inttypes.cc Wed Aug 29 14:34:24 2018 -0700 +++ b/liboctave/util/oct-inttypes.cc Thu Aug 30 10:45:51 2018 -0400 @@ -363,12 +363,12 @@ int64_t octave_int_arith_base<int64_t, true>::mul_internal (int64_t x, int64_t y) { - // The signed case is far worse. The problem is that even if neither integer - // fits into signed 32-bit range, the result may still be OK. Uh oh. + // The signed case is far worse. The problem is that even if neither + // integer fits into signed 32-bit range, the result may still be OK. + // Uh oh. // Essentially, what we do is compute sign, multiply absolute values // (as above) and impose the sign. - // FIXME: can we do something faster if we OCTAVE_HAVE_FAST_INT_OPS? uint64_t usx = octave_int_abs (x); uint64_t usy = octave_int_abs (y);
--- a/liboctave/util/oct-inttypes.h Wed Aug 29 14:34:24 2018 -0700 +++ b/liboctave/util/oct-inttypes.h Thu Aug 30 10:45:51 2018 -0400 @@ -497,32 +497,6 @@ #endif -// Signed integer arithmetic. -// -// Rationale: If OCTAVE_HAVE_FAST_INT_OPS is defined, the following -// conditions should hold: -// -// 1. Signed numbers are represented by twos complement (see -// <http://en.wikipedia.org/wiki/Two%27s_complement>) -// -// 2. static_cast to unsigned int counterpart works like -// interpreting the signed bit pattern as unsigned (and is thus -// zero-cost). -// -// 3. Signed addition and subtraction yield the same bit results as -// unsigned. (We use casts to prevent optimization interference, -// so there is no need for things like -ftrapv). -// -// 4. Bit operations on signed integers work like on unsigned -// integers, except for the shifts. Shifts are arithmetic. -// -// The above conditions are satisfied by most modern platforms. If -// OCTAVE_HAVE_FAST_INT_OPS is defined, bit tricks and wraparound -// arithmetics are used to avoid conditional jumps as much as -// possible, thus being friendly to modern pipeline processor -// architectures. Otherwise, we fall back to a bullet-proof code that -// only uses assumptions guaranteed by the standard. - template <typename T> class octave_int_arith_base<T, true> : octave_int_base<T> { @@ -540,32 +514,16 @@ static T abs (T x) { -#if defined (OCTAVE_HAVE_FAST_INT_OPS) - // This is close to how GCC does std::abs, but we can't just use std::abs, - // because its behavior for INT_MIN is undefined and the compiler could - // discard the following test. - T m = x >> std::numeric_limits<T>::digits; - T y = (x ^ m) - m; - if (y < 0) - { - y = octave_int_base<T>::max_val (); - } - return y; -#else - // -INT_MAX is safe because C++ actually allows only three implementations - // of integers: sign & magnitude, ones complement and twos complement. - // The first test will, with modest optimizations, evaluate at compile - // time, and maybe eliminate the branch completely. - T y; - if (octave_int_base<T>::min_val () < -octave_int_base<T>::max_val () - && x == octave_int_base<T>::min_val ()) - { - y = octave_int_base<T>::max_val (); - } - else - y = (x < 0) ? -x : x; - return y; -#endif + // -INT_MAX is safe because C++ actually allows only three + // implementations of integers: sign & magnitude, ones complement + // and twos complement. The first test will, with modest + // optimizations, evaluate at compile time, and maybe eliminate + // the branch completely. + + return ((octave_int_base<T>::min_val () < -octave_int_base<T>::max_val () + && x == octave_int_base<T>::min_val ()) + ? octave_int_base<T>::max_val () + : ((x < 0) ? -x : x)); } static T @@ -586,114 +544,42 @@ lshift (T x, int n) { return x << n; } // Minus has problems similar to abs. + static T minus (T x) { -#if defined (OCTAVE_HAVE_FAST_INT_OPS) - T y = -x; - if (y == octave_int_base<T>::min_val ()) - { - --y; - } - return y; -#else - T y; - if (octave_int_base<T>::min_val () < -octave_int_base<T>::max_val () - && x == octave_int_base<T>::min_val ()) - { - y = octave_int_base<T>::max_val (); - } - else - y = -x; - return y; -#endif + return ((octave_int_base<T>::min_val () < -octave_int_base<T>::max_val () + && x == octave_int_base<T>::min_val ()) + ? octave_int_base<T>::max_val () + : -x); } static T add (T x, T y) { -#if defined (OCTAVE_HAVE_FAST_INT_OPS) - - // The typecasts do nothing, but they are here to prevent an optimizing - // compiler from interfering. Also, the signed operations on small types - // actually return int. - T u = static_cast<UT> (x) + static_cast<UT> (y); - T ux = u ^ x; - T uy = u ^ y; - - return ((ux & uy) < 0 - ? (u < 0 - ? octave_int_base<T>::max_val () - : octave_int_base<T>::min_val ()) - : u); - -#else + // Avoid anything that may overflow. - // We shall carefully avoid anything that may overflow. - T u; - - if (y < 0) - { - if (x < octave_int_base<T>::min_val () - y) - u = octave_int_base<T>::min_val (); - else - u = x + y; - } - else - { - if (x > octave_int_base<T>::max_val () - y) - u = octave_int_base<T>::max_val (); - else - u = x + y; - } - - return u; - -#endif + return (y < 0 + ? (x < octave_int_base<T>::min_val () - y + ? octave_int_base<T>::min_val () + : x + y) + : (x > octave_int_base<T>::max_val () - y + ? octave_int_base<T>::max_val () + : x + y)); } - // This is very similar to addition. static T sub (T x, T y) { -#if defined (OCTAVE_HAVE_FAST_INT_OPS) - // The typecasts do nothing, but they are here to prevent an optimizing - // compiler from interfering. Also, the signed operations on small types - // actually return int. - T u = static_cast<UT> (x) - static_cast<UT> (y); - T ux = u ^ x; - T uy = u ^ ~y; - if ((ux & uy) < 0) - { - u = (__signbit (~u) - ? octave_int_base<T>::min_val () - : octave_int_base<T>::max_val ()); - } - return u; -#else - // We shall carefully avoid anything that may overflow. - T u; - if (y < 0) - { - if (x > octave_int_base<T>::max_val () + y) - { - u = octave_int_base<T>::max_val (); - } - else - u = x - y; - } - else - { - if (x < octave_int_base<T>::min_val () + y) - { - u = octave_int_base<T>::min_val (); - } - else - u = x - y; - } + // Avoid anything that may overflow. - return u; -#endif + return (y < 0 + ? (x > octave_int_base<T>::max_val () + y + ? octave_int_base<T>::max_val () + : x - y) + : (x < octave_int_base<T>::min_val () + y + ? octave_int_base<T>::min_val () + : x - y)); } // Multiplication is done using promotion to wider integer type. If there is @@ -793,9 +679,6 @@ long double p = static_cast<long double> (x) * static_cast<long double> (y); - // NOTE: We could maybe do it with a single branch if - // OCTAVE_HAVE_FAST_INT_OPS, but it would require one more runtime - // conversion, so the question is whether it would really be faster. if (p > static_cast<long double> (octave_int_base<int64_t>::max_val ())) retval = octave_int_base<int64_t>::max_val (); else if (p < static_cast<long double> (octave_int_base<int64_t>::min_val ()))
--- a/m4/acinclude.m4 Wed Aug 29 14:34:24 2018 -0700 +++ b/m4/acinclude.m4 Thu Aug 30 10:45:51 2018 -0400 @@ -2463,85 +2463,6 @@ fi ]) dnl -dnl Check whether fast signed integer arithmetic using bit tricks -dnl can be used in oct-inttypes.h. -dnl -dnl Defines OCTAVE_HAVE_FAST_INT_OPS if the following conditions hold: -dnl -dnl 1. Signed numbers are represented by twos complement (see -dnl <http://en.wikipedia.org/wiki/Two%27s_complement>) -dnl -dnl 2. static_cast to unsigned int counterpart works like -dnl interpreting the signed bit pattern as unsigned (and is thus -dnl zero-cost). -dnl -dnl 3. Signed addition and subtraction yield the same bit results -dnl as unsigned. (We use casts to prevent optimization -dnl interference, so there is no need for things like -ftrapv). -dnl -dnl 4. Bit operations on signed integers work like on unsigned -dnl integers, except for the shifts. Shifts are arithmetic. -dnl -AC_DEFUN([OCTAVE_FAST_INT_OPS], [ - AC_CACHE_CHECK([whether fast integer arithmetics is usable], - [octave_cv_fast_int_ops], - [AC_LANG_PUSH(C++) - AC_RUN_IFELSE([AC_LANG_PROGRAM([[ - #include <limits> - template<class UT, class ST> - static bool - do_test (UT, ST) - { - volatile ST s = std::numeric_limits<ST>::min () / 3; - volatile UT u = static_cast<UT> (s); - if (*(reinterpret_cast<volatile ST *> (&u)) != s) return true; - - u = 0; u = ~u; - if (*(reinterpret_cast<volatile ST *> (&u)) != -1) return true; - - ST sx, sy; - sx = std::numeric_limits<ST>::max () / 2 + 1; - sy = std::numeric_limits<ST>::max () / 2 + 2; - if (static_cast<ST> (static_cast<UT> (sx) + static_cast<UT> (sy)) - != std::numeric_limits<ST>::min () + 1) return true; - if (static_cast<ST> (static_cast<UT> (sx) - static_cast<UT> (sy)) - != -1) return true; - - if ((sx & sy) != (static_cast<UT> (sx) & static_cast<UT> (sy))) - return true; - if ((sx | sy) != (static_cast<UT> (sx) | static_cast<UT> (sy))) - return true; - if ((sx ^ sy) != (static_cast<UT> (sx) ^ static_cast<UT> (sy))) - return true; - if ((-1 >> 1) != -1) return true; - return false; - } - - #define DO_TEST(T) \ - if (do_test (static_cast<unsigned T> (0), static_cast<signed T> (0)))\ - return sizeof (T); - - ]],[[ - - DO_TEST(char) - DO_TEST(short) - DO_TEST(int) - DO_TEST(long) - #if (defined(OCTAVE_HAVE_LONG_LONG_INT) && defined(OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)) - DO_TEST(long long) - #endif - ]])], - octave_cv_fast_int_ops=yes, - octave_cv_fast_int_ops=no, - octave_cv_fast_int_ops=yes) - AC_LANG_POP(C++) - ]) - if test $octave_cv_fast_int_ops = yes; then - AC_DEFINE(OCTAVE_HAVE_FAST_INT_OPS, 1, - [Define to 1 if signed integers use two's complement.]) - fi -]) -dnl dnl Check to see if the compiler and the linker can handle the flags dnl "-framework $1" for the given prologue $2 and the given body $3 of dnl a source file. Arguments 2 and 3 optionally can also be empty.