Mercurial > octave
diff scripts/strings/dec2bin.m @ 28241:ef7bc64a604b
dec2bin.m: Fix algorithm for numbers less than intmin ('int32') (bug #58147).
* dec2bin.m: Document that negative numbers are restricted to < -flintmax/2.
Validate input and error if negative numbers greater than -flintmax/2 are
present. Update BIST tests.
author | Rik <rik@octave.org> |
---|---|
date | Sat, 25 Apr 2020 11:45:03 -0700 |
parents | ac3a078e688f |
children | 2bb050267d74 |
line wrap: on
line diff
--- a/scripts/strings/dec2bin.m Fri Apr 24 13:16:09 2020 -0700 +++ b/scripts/strings/dec2bin.m Sat Apr 25 11:45:03 2020 -0700 @@ -49,6 +49,9 @@ ## @end group ## @end example ## +## Programming Notes: The largest negative value that can be converted in to +## two's complement is @code{- (flintmax () / 2)}. +## ## @seealso{bin2dec, dec2base, dec2hex} ## @end deftypefn @@ -66,10 +69,11 @@ lt_zero_idx = (d < 0); if (any (lt_zero_idx)) - if (any (d(lt_zero_idx) < intmin ("int64"))) - error ('dec2bin: negative inputs cannot be less than intmin ("int64")'); + ## FIXME: Need an algorithm that works with larger values such as int64. + if (any (d(lt_zero_idx) < -2^52)) + error ("dec2bin: negative inputs cannot be less than -flintmax () / 2"); elseif (any (d(lt_zero_idx) < intmin ("int32"))) - d(lt_zero_idx) += double (intmax ("uint64")) + 1; + d(lt_zero_idx) += flintmax (); elseif (any (d < intmin ("int16"))) d(lt_zero_idx) += double (intmax ("uint32")) + 1; elseif (any (d < intmin ("int8"))) @@ -101,21 +105,21 @@ %!assert (dec2bin (-3, 9), "011111101") %!assert (dec2bin (-2^7 -1), "1111111101111111") %!assert (dec2bin (-2^15 -1), "11111111111111110111111111111111") -## The expected value is correct, but not what Octave generates because -## floating point integer precision is 2^53. Matlab gets this right. -%!xtest -%! assert (dec2bin (-2^31 -1), -%! "1111111111111111111111111111111101111111111111111111111111111111"); -%!assert (dec2bin (-2^63), +## FIXME: Matlab generates a string that is 64 characters long +%!assert (dec2bin (-2^31 -1), +%! "11111111111111111111101111111111111111111111111111111") +%!assert (dec2bin (-2^52), +%! "10000000000000000000000000000000000000000000000000000") +## FIXME: Uncomment when support for int64 is added +%!#assert (dec2bin (-2^63), %! "1000000000000000000000000000000000000000000000000000000000000000") -## These tests also don't work because of floating point precision. -%!xtest +%!#test %! assert (dec2bin (int64 (-2^63)), %! "1000000000000000000000000000000000000000000000000000000000000000"); -%!xtest +%!#test %! assert (dec2bin (int64 (-2^63) -1), %! "1000000000000000000000000000000000000000000000000000000000000000"); -%!xtest +%!#test %! assert (dec2bin (int64 (-2^63) +1), %! "1000000000000000000000000000000000000000000000000000000000000001"); %!assert (dec2bin ([-1, -2; -3, -4]), @@ -128,4 +132,4 @@ ## Test input validation %!error dec2bin () %!error dec2bin (1, 2, 3) -%!error <negative inputs> dec2bin (2 * double (intmin ("int64"))) +%!error <negative inputs cannot be less than> dec2bin (- flintmax ())