# HG changeset patch # User Nicholas R. Jankowski # Date 1587596031 25200 # Node ID 5bb1c0cbb27ed51ac8554357dbc82b027a53f9f8 # Parent a6edb8097ec6967d3b563bf2692992357fbf87b4 dec2bin.m: Allow negative number inputs (bug #58147). * dec2bin.m: Document that negative numbers are converted according to 2's complement convention. Add example to documentation of converting a negative number. Add algorithm to detect negative inputs and add the appropriate offset for 2's complement notation. Add BIST tests. diff -r a6edb8097ec6 -r 5bb1c0cbb27e scripts/strings/dec2bin.m --- a/scripts/strings/dec2bin.m Wed Apr 22 13:23:05 2020 +0200 +++ b/scripts/strings/dec2bin.m Wed Apr 22 15:53:51 2020 -0700 @@ -25,8 +25,9 @@ ## -*- texinfo -*- ## @deftypefn {} {} dec2bin (@var{d}, @var{len}) -## Return a binary number corresponding to the non-negative integer @var{d}, -## as a string of ones and zeros. +## Return a binary number corresponding to the integer @var{d} as a string of +## ones and zeros. If @var{d} is negative, return the two's complement binary +## value of @var{d}. ## ## For example: ## @@ -34,6 +35,9 @@ ## @group ## dec2bin (14) ## @result{} "1110" +## +## dec2bin (-14) +## @result{} "11110010" ## @end group ## @end example ## @@ -43,11 +47,37 @@ ## ## The optional second argument, @var{len}, specifies the minimum number of ## digits in the result. +## ## @seealso{bin2dec, dec2base, dec2hex} ## @end deftypefn function b = dec2bin (d, len) +## dec2base does cell->mat conversion, this allows easier content comparison +if (iscell (d)) + d = cell2mat (d); +endif + +d = d(:); ## output is always a column vector, (:) simplifies value checks + +if (any (d < intmin ("int64"))) + error ("dec2bin: negative inputs cannot be less than intmin('int64')"); +endif + +if (any (d < 0)) + if (any (d < intmin ("int64"))) + error ("out of range"); + elseif (any (d < intmin ("int32"))) + d(d < 0) += double (intmax ("uint64")) + 1 ; + elseif (any (d < intmin ("int16"))) + d(d < 0) += double (intmax ("uint32")) + 1; + elseif (any (d < intmin ("int8"))) + d(d < 0) += double (intmax ("uint16"))+ 1; + else + d(d < 0) += double (intmax ("uint8")) +1; + endif +endif + if (nargin == 1) b = dec2base (d, 2); elseif (nargin == 2) @@ -59,10 +89,27 @@ endfunction +%!assert (dec2bin (3), "11") %!assert (dec2bin (14), "1110") %!assert (dec2bin (14, 6), "001110") +%!assert (dec2bin ([1, 2; 3, 4]), ["001"; "011"; "010"; "100"]) %!assert (dec2bin ({1, 2; 3, 4}), ["001"; "011"; "010"; "100"]) +%!assert (dec2bin ({1, 2; 3, 4}, 4), ["0001"; "0011"; "0010"; "0100"]) + +## Test negative inputs +%!assert (dec2bin (-3), "11111101") +%!assert (dec2bin (-3, 3), "11111101") +%!assert (dec2bin (-3, 9), "011111101") +%!assert (dec2bin (-129), "1111111101111111") +%!assert (dec2bin (-2^15 -1), "11111111111111110111111111111111") +%!assert (dec2bin (-2^31 -1), "1111111111111111111111111111111101111111111111111111111111111111") +%!assert (dec2bin (-2^63), "1000000000000000000000000000000000000000000000000000000000000000") +%!assert (dec2bin (-2^63-1), "1000000000000000000000000000000000000000000000000000000000000000") +%!assert (dec2bin ([-1, -2; -3, -4]), ["11111111"; "11111101"; "11111110"; "11111100"]) +%!assert (dec2bin ([1, 2; 3, -4]), ["00000001"; "00000011"; "00000010"; "11111100"]) +%!assert (dec2bin ({1, 2; 3, -4}), ["00000001"; "00000011"; "00000010"; "11111100"]) ## Test input validation %!error dec2bin () %!error dec2bin (1, 2, 3) +%!error dec2bin (2 * double (intmin ("int64")))