Code covered by the BSD License

### Highlights fromByte manipulation and Endian conversion in MATLAB

from Byte manipulation and Endian conversion in MATLAB by Gautam Vallabha
A demonstration of MATLAB's built-in facilities for unpacking integers into individual bytes (and vi

Numeric and byte order (endian) conversions in MATLAB

# Numeric and byte order (endian) conversions in MATLAB

## Creating an integer variable

Say I want to create a variable of type uint16, with value 100.

Method 1

```val1 = uint16(100);
```

Method 2

```val2 = cast(100, 'uint16');
```

Method 3

```val3 = zeros(1,1,'uint16');
val3(1) = 100;

whos val1 val2 val3
```
```  Name      Size            Bytes  Class     Attributes

val1      1x1                 2  uint16
val2      1x1                 2  uint16
val3      1x1                 2  uint16

```

Incorrect method

The following won't work, since val4 will be reinitialized to have the type of the number '100', i.e., it will be a double.

```val4 = zeros(1,1,'uint16');
val4 = 100;

whos val4
```
```  Name      Size            Bytes  Class     Attributes

val4      1x1                 8  double

```

## Destructive casting - I

If I have a variable of type uint16 and would like to convert it to a uint8, I can use the CAST or UINT8 commands.

First create a variable of type uint16

```aval = uint16(10000);
```

Conversion to int16 is safe, since 10000 is within the valid range for an int16.

```bval = int16(aval)
```
```bval =
10000
```

Convert to uint8 is not safe since the 10000 doesn't fit in the new type. Hence, the value gets clipped.

```cval = uint8(aval)
```
```cval =
255
```

It is not possible to recover the original aval from the uint8 variable cval

```new_aval = uint16(cval);
aval,new_aval
```
```aval =
10000
new_aval =
255
```

## Destructive casting - II

The behavior of CAST and functions like UINT16 or INT8 can be frustrating if I have a signed integer that I want to treat as an unsigned number, or vice versa (i.e., I want to convert to/from the two's-complement representation of the number).

```aval = int16(-200);
bval = uint16(aval);
whos aval bval, bval
```
```  Name      Size            Bytes  Class     Attributes

aval      1x1                 2  int16
bval      1x1                 2  uint16

bval =
0
```

bval is 0 since the allowable range for a uint16 is [0,65535], and the value of -100 gets clipped to 0. Hence, it is not possible to recover the original number, even though aval and bval have the same size (two bytes):

```new_aval = int16(bval);
aval, new_aval
```
```aval =
-200
new_aval =
0
```

## Non-destructive casting

The way to do non-destructive casting is with the TYPECAST command.

```aval = int16(-200);
bval = typecast(aval, 'uint16');
whos aval bval, bval
```
```  Name      Size            Bytes  Class     Attributes

aval      1x1                 2  int16
bval      1x1                 2  uint16

bval =
65336
```

Now convert back from uint16 to int16

```new_aval = typecast(bval, 'int16');
aval, new_aval
```
```aval =
-200
new_aval =
-200
```

## Converting an integer to a sequence of bytes

Say I want to convert a mulitbyte number to a sequence of bytes (e.g., I want to save the data in a custom binary format, or want to send it over a communications channel that only takes a sequence of bytes).

Make a 4-byte signed integer

```aval = int32(-314159);
whos aval, aval
```
```  Name      Size            Bytes  Class    Attributes

aval      1x1                 4  int32

aval =
-314159
```

Convert the 4-byte integer to a sequence of four unsigned bytes

```bval = typecast(aval, 'uint8');
whos bval, bval
```
```  Name      Size            Bytes  Class    Attributes

bval      1x4                 4  uint8

bval =
209   52  251  255
```

Now convert from the sequence of bytes back to a multibyte value

```new_aval = typecast(bval, 'int32');
aval, new_aval
```
```aval =
-314159
new_aval =
-314159
```

## Converting a floating-point value to a sequence of bytes

Create an 8-byte floating point value (i.e., of type double)

```aval = 3.14159; % equivalent to double(3.14159)
whos aval, aval
```
```  Name      Size            Bytes  Class     Attributes

aval      1x1                 8  double

aval =
3.1416
```

This becomes a sequence of 8 unsigned bytes

```bval = typecast(aval, 'uint8');
whos bval, bval
```
```  Name      Size            Bytes  Class    Attributes

bval      1x8                 8  uint8

bval =
110  134   27  240  249   33    9   64
```

Now convert back:

```new_aval = typecast(bval, 'double');
aval, new_aval
```
```aval =
3.1416
new_aval =
3.1416
```

## Converting a sequence of bytes to an integer

Sometimes I have a sequence of bytes that I want to convert to a multibyte integer. This example shows how to go from an array of four bytes to a uint32.

Define a byte array of length 4

```byteArray = zeros(1,4,'uint8');
byteArray(1) = 2;
byteArray(2) = 1;
whos byteArray, byteArray
```
```  Name           Size            Bytes  Class    Attributes

byteArray      1x4                 4  uint8

byteArray =
2    1    0    0
```

Another way of specifying byteArray

```byteArray = uint8([2 1 0 0]);
```

Now convert to a uint32 (the bytes will be interpreted in Little-endian order on my system).

```integerValue = typecast(byteArray, 'uint32');
whos integerValue, integerValue
```
```  Name              Size            Bytes  Class     Attributes

integerValue      1x1                 4  uint32

integerValue =
258
```

## Checking the Endianness of the system

The COMPUTER command returns the current endian-ness (the value of endian is 'L' if the system is Little-endian, and 'B' if it is Big-endian).

```[computerType, maxSize, endian] = computer;
isLittleEndian = (endian == 'L')
```
```isLittleEndian =
1
```

Another way of testing the endianness

```testNumber = uint32(1);
byteSeq = typecast(testNumber, 'uint8');
isLittleEndian = (byteSeq(1) == 1)
```
```isLittleEndian =
1
```

## Little-endian and Big-endian conversions

The TYPECAST operator makes it easy to do byte-order conversions, such as from Little-endian to Big-endian. For example, I may need to save to a binary file that needs to be read on big-endian system, or may need to send data over a communications channel that assumes big-endian representation.

Create a little-endian number (I know it is little-endian since my computer is a Little-endian system; see the section on checking endianness).

```leNumber = uint32(258);
```

Get the bytes in the 32-bit little-endian number (note that the leftmost byte is the least-significant one).

```byteSeq = typecast(leNumber, 'uint8')
```
```byteSeq =
2    1    0    0
```

See each byte as a binary number (each row is one byte)

```dec2bin(byteSeq,8)
```
```ans =
00000010
00000001
00000000
00000000
```

There are two ways to convert the little-endian value to a big-endian value

Method 1: Use the SWAPBYTES command

```beNumber = swapbytes(leNumber)
newByteSeq = typecast(beNumber, 'uint8')
```
```beNumber =
33619968
newByteSeq =
0    0    1    2
```

Method 2: Do the conversion myself

```newByteSeq = byteSeq(end:-1:1)
beNumber = typecast(newByteSeq, 'uint32')
```
```newByteSeq =
0    0    1    2
beNumber =
33619968
```

## Help on functions

```help class
```
``` CLASS  Create object or return object class.
C = CLASS(OBJ) returns the class of the object OBJ.
Possibilities are:
double          -- Double precision floating point number array
(this is the traditional MATLAB matrix or array)
single          -- Single precision floating point number array
logical         -- Logical array
char            -- Character array
cell            -- Cell array
struct          -- Structure array
function_handle -- Function Handle
int8            -- 8-bit signed integer array
uint8           -- 8-bit unsigned integer array
int16           -- 16-bit signed integer array
uint16          -- 16-bit unsigned integer array
int32           -- 32-bit signed integer array
uint32          -- 32-bit unsigned integer array
int64           -- 64-bit signed integer array
uint64          -- 64-bit unsigned integer array
<class_name>    -- Custom object class
<java_class>    -- Java class name for java objects

All other uses of CLASS must be invoked within a constructor method,
in a file named <class_name>.m in a directory named @<class_name>.
Further, 'class_name' must be the second argument to CLASS.

O = CLASS(S,'class_name') creates an object of class 'class_name'
from the structure S.

O = CLASS(S,'class_name',PARENT1,PARENT2,...) also inherits the
methods and fields of the parent objects PARENT1, PARENT2, ...

O = CLASS(struct([]),'class_name',PARENT1,PARENT2,...), specifying
an empty structure S, creates an object that inherits from one or
more parent classes, but which does not have any additional fields
not inherited from the parents.

scribehandle/class
serial/class
digitalio/class
analogoutput/class
visa/class
udp/class
tcpip/class
icgroup/class
icdevice/class
gpib/class

doc class

```
```help cast
```
``` CAST  Cast a variable to a different data type or class.
B = CAST(A,NEWCLASS) casts A to class NEWCLASS. A must be convertible to
class NEWCLASS. NEWCLASS must be the name of one of the builtin data types.

Example:
a = int8(5);
b = cast(a,'uint8');

ccspointer/cast
ccsnumeric/cast
ccsenum/cast
ccsbitfield/cast
darray/cast

doc cast

```
```help typecast
```
``` TYPECAST Convert datatypes without changing underlying data.
Y = TYPECAST(X, DATATYPE) convert X to DATATYPE.  If DATATYPE has
fewer bits than the class of X, Y will have more elements than X.  If
DATATYPE has more bits than the class of X, Y will have fewer
elements than X.  X must be a scalar or vector.  DATATYPE must be one
of 'UINT8', 'INT8', 'UINT16', 'INT16', 'UINT32', 'INT32', 'UINT64',
'INT64', 'SINGLE', or 'DOUBLE'.

Note: An error is issued if X contains fewer values than are needed
to make an output value.

Example:

X = uint32([1 255 256]);
Y = typecast(X, 'uint8');

On little-endian architectures Y will be

[1   0   0   0   255 0   0   0   0   1   0   0]

darray/typecast

doc typecast

```
```help swapbytes
```
``` SWAPBYTES Swap byte ordering, changing endianness.
Y = SWAPBYTES(X) reverses the byte ordering of the matrix X,
converting little-endian values to big-endian (and vice versa).

Example:

X = uint16([0 1 128 65535]);
Y = swapbytes(X);

Y will have the following uint16 values:

[0    256  32768  65535]

Examining the output in hex notation shows the byte swapping:

format hex
X, Y
format