# HG changeset patch # User Rik # Date 1587840303 25200 # Node ID ef7bc64a604b6ca1f444cf3682d07ebc35fa4e39 # Parent 2fb684dc2ec2f1ec171741f2ea454db262b0c887 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. diff -r 2fb684dc2ec2 -r ef7bc64a604b scripts/strings/dec2bin.m --- 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 dec2bin (2 * double (intmin ("int64"))) +%!error dec2bin (- flintmax ())