Mercurial > octave
changeset 25838:26c41d8bf170 stable
fix min-val saturation for 64-bit integer addition (bug #54572)
* oct-inttypes.h (octave_int_arith_base<T,true>::__signbit):
Simplify.
(octave_int_arith_base<T,true>::add): In overflow case, set negative
limit directly instead of adding signbit to max value.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 29 Aug 2018 14:03:45 -0400 |
parents | 07cb3e098c0a |
children | 7094f73d4ece |
files | liboctave/util/oct-inttypes.h |
diffstat | 1 files changed, 16 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/util/oct-inttypes.h Wed Aug 29 09:52:08 2018 -0700 +++ b/liboctave/util/oct-inttypes.h Wed Aug 29 14:03:45 2018 -0400 @@ -544,11 +544,7 @@ static T __signbit (T x) { -#if defined (OCTAVE_HAVE_FAST_INT_OPS) - return static_cast<UT> (x) >> std::numeric_limits<T>::digits; -#else return (x < 0) ? 1 : 0; -#endif } static T @@ -627,40 +623,42 @@ 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; - if ((ux & uy) < 0) - { - u = octave_int_base<T>::max_val () + __signbit (~u); - } - return u; + + return ((ux & uy) < 0 + ? (u < 0 + ? octave_int_base<T>::max_val () + : octave_int_base<T>::min_val ()) + : u); + #else + // 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 (); - } + 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 (); - } + u = octave_int_base<T>::max_val (); else u = x + y; } return u; + #endif } @@ -677,7 +675,9 @@ T uy = u ^ ~y; if ((ux & uy) < 0) { - u = octave_int_base<T>::max_val () + __signbit (~u); + u = (__signbit (~u) + ? octave_int_base<T>::min_val () + : octave_int_base<T>::max_val ()); } return u; #else