MATLAB Answers

0

[bug] boolean to uint8

Asked by Nathan Zimmerman on 9 Aug 2017
Latest activity Edited by Walter Roberson
on 8 Feb 2018
To my knowledge, matlab is the only coding language on the planet cannot convert a boolean to a byte.
typecast(boolean(0),'uint8')
or
typecast(logical(0),'uint8')
yields:
Error using typecast
The first input argument must be a full, non-complex numeric value.
Granted, there are easy hack-a-rounds to get past this but its frustrating to have to use them. I am using 2016A. Will/has matlab ever addressed this?

  6 Comments

Jan
on 14 Aug 2017
@Philip: typecast creates a shared data copy, such that this can be much more efficient.
@Nathan: This is definitely not a bug, but it differs from your expectations only.
The use case for this is packing a structure into a byte array for storage and reading on embedded platforms. One would concat an array via
x = [x;typecast(myStructField,'uint8')];
Granted one has to iterate through the elements of the struct as well as flatten any data that is in an array format for this to work. Also, the inevitable work-a-round for booleans.
Not surprisingly, in octave:
typecast(logical(0),'uint8')
ans = 0
Walter Roberson
on 16 Aug 2017
If the structure to be packed has components that are not constant size or not constant type, then perhaps you should use one of the serialization routines from the File Exchange.

Sign in to comment.

4 Answers

Walter Roberson
Answer by Walter Roberson
on 14 Aug 2017
 Accepted Answer

No, MATLAB is not going to address this. typecast() involves re-interpreting representation, but MATLAB does not publicly define the representation of logical (or boolean). As far as the user is concerned, a vector of logical values might be internally implemented as a packed array of bits, or might be implemented as bytes where 0 is false and all-ones is true, or where 0 is false and true has only the top bit set in the byte, or by some other method.
MATLAB also does not permit typecast between numeric values and char. This ambiguity allowed them to move from 8 bit characters to 16 bit characters without change to the user interface; at some point Mathworks might switch to 32 bit characters to permit full Unicode.
Historically, PASCAL did not offer any typecast operation, and logical values were an enumerated type. In the implementation I programmed in (decades ago), logical true was internally represented as a byte of all 1's, because the processor family we were using (Motorola MC68020) was one cycle faster at Test For Negative than it was for Test For Non Zero.

  5 Comments

Image Analyst
on 15 Aug 2017
So what was the problem with simply calling cast() instead of typecast() like I suggested? It worked. Didn't throw an error and did what you wanted.
Walter Roberson
on 15 Aug 2017
uint8 or int8 for boolean values is not standard.
C11-§6.5.9/3:
The == (equal to) and != (not equal to) operators are analogous to the relational operators except for their lower precedence.108) Each of the operators yields 1 if the specified relation is true and 0 if it is false. The result has type int.
If you follow through the various standards historically, type int is never less than 16 (signed) bits.
Historically there was no int8 or uint8, and in order to get them you had to use type "signed char" (very rare to see in practice unless you were working with early Sun computers) or "unsigned char", as char was defined as being the smallest addressable integer type -- which explicitly does mean that char is 16 bits on some platforms, since some DSPs cannot address individual bytes.
James Tursa
on 16 Aug 2017
"... MATLAB does not publicly define the representation of logical (or boolean)..."
Actually they do expose that publicly (sort of) at the mex level, since they explicitly document the mxLogical macro (or typedef) as the element type used in MATLAB logical variables. So that probably eliminates the possibility that packed arrays of bits could be the underlying storage method used. As to the supported "values" of these underlying bits in MATLAB functions, I don't know if that is explicitly documented anywhere. See my comment to Jan's answer.
Similar comments for char variables since MATLAB exposes that in the mex API interface with the mxChar macro (or typedef).

Sign in to comment.


Jan
Answer by Jan
on 14 Aug 2017

If you need to typecast logical to uint8, use https://www.mathworks.com/matlabcentral/fileexchange/17476-typecast-and-typecastx-c-mex-functions. This creates a shared data copy as modern versions of typecast, but allows char,logical and non-vector arrays also.
If Matlab changes the internal format of logicals, this function might crash tremendously, but this is not expected yet.

  3 Comments

James Tursa
on 15 Aug 2017
Current version of typecastx does have char and logical bytes-per-element hard coded to 2 and 1 respectively for output ... the input bytes-per-element is obtained dynamically from the API function mxGetElementSize. So yes, if things change in the future, then typecastx would produce incorrect results for the output. I can look into making this more robust with sizeof(mxChar) and sizeof(mxLogical) (although I can't imagine why the logical type would ever change from 1 byte).
James Tursa
on 16 Aug 2017
I will add another comment here about the behavior of typecastx when producing logical values. The bit pattern carries over intact since it is a shared data copy, so the resulting class will be logical, but the underlying bit patterns will display and be used as unsigned integers (at least in the MATLAB versions that I have used). E.g.,
>> g = typecastx(int8(-3:3),'logical')
g =
253 254 255 0 1 2 3
>> class(g)
ans =
logical
>> g == true
ans =
0 0 0 0 1 0 0
>> g(1) == 253
ans =
1
>> if( g(1) ); disp('g(1) is true'); end
g(1) is true
>> if( g(6) ); disp('g(6) is true'); end
g(6) is true
>> g * 2
ans =
506 508 510 0 2 4 6
>> class(ans)
ans =
double
So, only the particular element of g that is exactly 1 (i.e., g(5)) will equate exactly with the "true" function result. But when used in control statements all of the non-zero values are regarded as logically "true".
Of course, in a mex routine one could simply create a logical variable with element values other than 0 or 1 directly ... no shared data copy stuff needed for that. But I would have to think that all of the MATLAB functions dealing with logical variables assume the underlying element values are either 0 or 1 explicitly. So using logical variables with other underlying element values should probably be regarded as undocumented behavior and should not relied on. Avoiding this type of behavior may be the exact reason MATLAB does not allow conversion to logical in their typecast function.
Jan
on 16 Aug 2017
@James: In my opinion, typecastx works perfect and it is not a problem, that the implementation does not consider a potential change of logicals to packed binary variables. It need not to be fixed, because it is not broken.
It is interesting, that the conversion
L = typecastx(int8(2), 'logical')
is not recognized as true. This is a pitfall when using typecastx without the required care. This might be one of the reasons why MathWorks decided not to accept logicals in the built-in typecast.

Sign in to comment.


Answer by Jayaram Theegala on 14 Aug 2017
Edited by Jayaram Theegala on 14 Aug 2017

If you want to convert any numeric class type to "uint8" datatype, you can use the "uint8" function. For more information, click on the following MATLAB documentation: https://www.mathworks.com/help/matlab/ref/uint8.html
logicalArr = logical([1,0,0,1,1]);
typecastedArr = uint8(logicalArr);
You may find the above MATLAB code snippet helpful.

  0 Comments

Sign in to comment.


Image Analyst
Answer by Image Analyst
on 14 Aug 2017

Use cast() instead of typecast():
output = cast(logical(0),'uint8')

  0 Comments

Sign in to comment.