comparison scripts/strings/dec2bin.m @ 31239:dd6b37f67db2

Accept negative inputs to -2^63 for dec2bin and dec2hex (bug #63089) dec2bin.m: Accept negative inputs lower than -flintmax down to -2^63 Return 64-bit string in certain cases for Matlab compatibility Activate BISTs commented out earlier dec2hex.m: Remove repeated code and call dec2bin instead Accept negative inputs lower than -flintmax down to -2^63 Update and activate BISTs commented out earlier
author Arun Giridhar <arungiridhar@gmail.com>
date Sun, 25 Sep 2022 06:22:25 -0400
parents 5d3faba0342e
children 7018819318d1
comparison
equal deleted inserted replaced
31238:67cad4e8f866 31239:dd6b37f67db2
27 ## @deftypefn {} {@var{bstr} =} dec2bin (@var{d}) 27 ## @deftypefn {} {@var{bstr} =} dec2bin (@var{d})
28 ## @deftypefnx {} {@var{bstr} =} dec2bin (@var{d}, @var{len}) 28 ## @deftypefnx {} {@var{bstr} =} dec2bin (@var{d}, @var{len})
29 ## Return a string of ones and zeros representing the conversion of the integer 29 ## Return a string of ones and zeros representing the conversion of the integer
30 ## @var{d} to a binary number. 30 ## @var{d} to a binary number.
31 ## 31 ##
32 ## If @var{d} is negative, return the two's complement binary value of @var{d}.
33 ## If @var{d} is a matrix or cell array, return a string matrix with one row 32 ## If @var{d} is a matrix or cell array, return a string matrix with one row
34 ## for each element in @var{d}, padded with leading zeros to the width of the 33 ## for each element in @var{d}, padded with leading zeros to the width of the
35 ## largest value. 34 ## largest value.
36 ## 35 ##
37 ## The optional second argument, @var{len}, specifies the minimum number of 36 ## The optional second argument, @var{len}, specifies the minimum number of
38 ## digits in the result. 37 ## digits in the result.
38 ##
39 ## For negative elements of @var{d}, return the binary value of the two's
40 ## complement. The result is padded with leading ones to 8, 16, 32, or 64
41 ## bits as appropriate for the magnitude of the input. Positive input
42 ## elements are padded with leading zeros to the same width. If the second
43 ## argument @var{len} exceeds that calculated width, the result is further
44 ## padded with leading zeros, for compatibility with @sc{matlab}.
39 ## 45 ##
40 ## Examples: 46 ## Examples:
41 ## 47 ##
42 ## @example 48 ## @example
43 ## @group 49 ## @group
46 ## 52 ##
47 ## dec2bin (-14) 53 ## dec2bin (-14)
48 ## @result{} "11110010" 54 ## @result{} "11110010"
49 ## @end group 55 ## @end group
50 ## @end example 56 ## @end example
51 ##
52 ## Programming Notes: The largest negative value that can be converted into
53 ## two's complement is @code{- (flintmax () / 2)}.
54 ## 57 ##
55 ## Known @sc{matlab} Incompatibility: @sc{matlab}'s @code{dec2bin} allows 58 ## Known @sc{matlab} Incompatibility: @sc{matlab}'s @code{dec2bin} allows
56 ## non-integer values for @var{d}, truncating the value using the equivalent 59 ## non-integer values for @var{d}, truncating the value using the equivalent
57 ## of @code{fix (@var{d})} for positive values, but, as of R2020b and in 60 ## of @code{fix (@var{d})} for positive values, but, as of R2020b and in
58 ## conflict with published documentation, appears to use 61 ## conflict with published documentation, appears to use
73 d = cell2mat (d); 76 d = cell2mat (d);
74 endif 77 endif
75 ## Create column vector for algorithm (output is always col. vector anyways) 78 ## Create column vector for algorithm (output is always col. vector anyways)
76 d = d(:); 79 d = d(:);
77 80
78 lt_zero_idx = (d < 0); 81 neg = (d < 0); # keep track of which elements are negative
79 if (any (lt_zero_idx)) 82 if (any (neg)) # must be a signed type
80 ## FIXME: Need an algorithm that works with larger values such as int64. 83 ## Cast to a suitable signed integer type, then to unsigned.
81 if (any (d(lt_zero_idx) < -2^52)) 84 ## Ensure that the left-most bit of the unsigned number is 1,
82 error ("dec2bin: negative inputs cannot be less than -flintmax () / 2"); 85 ## to signify negative input.
83 elseif (any (d(lt_zero_idx) < intmin ("int32"))) 86 tmp = int64 (d);
84 d(lt_zero_idx) += flintmax (); 87 if (all (tmp >= -128 & tmp <= 127))
85 elseif (any (d < intmin ("int16"))) 88 d = int8 (d);
86 d(lt_zero_idx) += double (intmax ("uint32")) + 1; 89 d(neg) = (d(neg) + intmax (d)) + 1;
87 elseif (any (d < intmin ("int8"))) 90 d = uint8 (d);
88 d(lt_zero_idx) += double (intmax ("uint16"))+ 1; 91 d(neg) += uint8 (128);
92 elseif (all (tmp >= -32768 & tmp <= 32767))
93 d = int16 (d);
94 d(neg) = (d(neg) + intmax (d)) + 1;
95 d = uint16 (d);
96 d(neg) += uint16 (32768);
97 elseif (all (tmp >= -2147483648 & tmp <= 2147483647))
98 d = int32 (d);
99 d(neg) = (d(neg) + intmax (d)) + 1;
100 d = uint32 (d);
101 d(neg) += uint32 (2147483648);
89 else 102 else
90 d(lt_zero_idx) += double (intmax ("uint8")) + 1; 103 d = int64 (d);
104 d(neg) = (d(neg) + intmax (d)) + 1;
105 d = uint64 (d);
106 d(neg) += uint64 (9223372036854775808);
91 endif 107 endif
92 endif 108 endif
93 109
94 if (nargin == 1) 110 if (nargin == 1)
95 bstr = dec2base (d, 2); 111 bstr = dec2base (d, 2);
109 125
110 ## Test negative inputs 126 ## Test negative inputs
111 %!assert (dec2bin (-3), "11111101") 127 %!assert (dec2bin (-3), "11111101")
112 %!assert (dec2bin (-3, 3), "11111101") 128 %!assert (dec2bin (-3, 3), "11111101")
113 %!assert (dec2bin (-3, 9), "011111101") 129 %!assert (dec2bin (-3, 9), "011111101")
114 %!assert (dec2bin (-2^7 -1), "1111111101111111") 130 %!assert (dec2bin (-2^7 - 1), "1111111101111111")
115 %!assert (dec2bin (-2^15 -1), "11111111111111110111111111111111") 131 %!assert (dec2bin (-2^15 - 1), "11111111111111110111111111111111")
116 ## FIXME: Matlab generates a string that is 64 characters long 132 %!assert (dec2bin (-2^31 - 1),
117 %!assert (dec2bin (-2^31 -1), 133 %! "1111111111111111111111111111111101111111111111111111111111111111")
118 %! "11111111111111111111101111111111111111111111111111111")
119 %!assert (dec2bin (-2^52), 134 %!assert (dec2bin (-2^52),
120 %! "10000000000000000000000000000000000000000000000000000") 135 %! "1111111111110000000000000000000000000000000000000000000000000000")
121 ## FIXME: Uncomment when support for int64 is added 136 %!assert (dec2bin (-2^63),
122 %!#assert (dec2bin (-2^63),
123 %! "1000000000000000000000000000000000000000000000000000000000000000") 137 %! "1000000000000000000000000000000000000000000000000000000000000000")
124 %!#test 138 %!assert (dec2bin (int64 (-2) ^ 63),
125 %! assert (dec2bin (int64 (-2^63)), 139 %! "1000000000000000000000000000000000000000000000000000000000000000")
126 %! "1000000000000000000000000000000000000000000000000000000000000000"); 140 %!assert (dec2bin (int64 (-2) ^ 63 - 1),
127 %!#test 141 %! "1000000000000000000000000000000000000000000000000000000000000000")
128 %! assert (dec2bin (int64 (-2^63) -1), 142 %!assert (dec2bin (int64 (-2) ^ 63 + 1),
129 %! "1000000000000000000000000000000000000000000000000000000000000000"); 143 %! "1000000000000000000000000000000000000000000000000000000000000001")
130 %!#test
131 %! assert (dec2bin (int64 (-2^63) +1),
132 %! "1000000000000000000000000000000000000000000000000000000000000001");
133 %!assert (dec2bin ([-1, -2; -3, -4]), 144 %!assert (dec2bin ([-1, -2; -3, -4]),
134 %! ["11111111"; "11111101"; "11111110"; "11111100"]) 145 %! ["11111111"; "11111101"; "11111110"; "11111100"])
135 %!assert (dec2bin ([1, 2; 3, -4]), 146 %!assert (dec2bin ([1, 2; 3, -4]),
136 %! ["00000001"; "00000011"; "00000010"; "11111100"]) 147 %! ["00000001"; "00000011"; "00000010"; "11111100"])
137 %!assert (dec2bin ({1, 2; 3, -4}), 148 %!assert (dec2bin ({1, 2; 3, -4}),
138 %! ["00000001"; "00000011"; "00000010"; "11111100"]) 149 %! ["00000001"; "00000011"; "00000010"; "11111100"])
139 150
140 ## Test input validation 151 ## Test input validation
141 %!error <Invalid call> dec2bin () 152 %!error <Invalid call> dec2bin ()
142 %!error <negative inputs cannot be less than> dec2bin (- flintmax ()) 153