Newsletters |

By Stuart McGarrity, MathWorks

MATLAB 7 now provides integer and single-precision math. This new capability enables processing of integer and single-precision data in its native type, resulting in more efficient memory usage and the ability to process larger, nondouble data sets. This article describes the new MATLAB integer and single-precision math features with application examples for each case.

Before MATLAB 7, all numerical operations in MATLAB were performed in double precision. Double-precision variables, which use 64 bits (8 bytes) of memory storage, accurately represent values to approximately 15 decimal places. Double-precision is a floating-point data type with a large dynamic range.

MATLAB 7 now supports arithmetic on the integers including unsigned integer types `uint8`

, `uint16`

, and `uint32`

, and the signed types `int8`

, `int16`

, and `int32`

. These data types require 8 to 32 bits to be stored in memory. Examples of integer data include output from sensors measuring real-world values, such as audio signals using 8 or 16 bits per sample, or image files using 8 or 24 bits per pixel.

MATLAB supports all arithmetic operators such as +, -, .*, . ⁄, and .^ on these integer data types, as well as some elementary functions such as `sum`

and `sort`

. Other functions that are useful when dealing with integer data types are `intmax`

, `intmin`

, `isinteger(x)`

, `isa(x,'integer')`

, `cast`

, `ones`

, `zeros`

, `eye`

and `intwarning`

.

Like any computer application, MATLAB has a finite amount of addressable memory to store data. For example, on Windows XP in Release 14 the largest variable MATLAB can store is approximately 1.2GB. By leaving data in its native format and not requiring the conversion to doubles, MATLAB can now handle integer data sets up to eight times larger without running out of memory.

Storing real numbers as integers usually results in much larger conversion and arithmetic round-off errors than if they had been stored as doubles. In MATLAB 7 when variables are converted from another data type, the value is rounded to the nearest integer instead of always truncating (as in C), resulting in less round-off error.

To convert a variable to an integer data type, you must pass it to the appropriate function, for example:`>> a=6.4;`

>> aint=uint8(a)`aint =``6`

Integer data types also have less dynamic range than floating-point data types, therefore the result of an operation can go out of range more easily. In MATLAB 7, if the result of an arithmetic operation is greater that the upper bound of the data type, the variable saturates (it is set to the upper bound). If the result is less than the lower bound of the data type, the variable is set to the lower bound. This is different from C, which wraps around through zero.

When performing arithmetic on integer data types, issues such as round-off error and saturation must be managed by the programmer. One technique is to ensure the data set stays within the data type’s range throughout the execution of the algorithm.

In order to precisely match the overflow and rounding effects that occur in the integer or fixed-point arithmetic of any C compiler or embedded processor, you can use the Fixed-Point Toolbox.

You can combine numbers of an integer data type with numbers of the same integer data type or type scalar double. MATLAB performs arithmetic as if both inputs had type double and then converts the result to the same integer data type. The complete set of rules describing how integer types interact with other data is described in the MATLAB documentation.

The following M-code shows how to perform integer math on some sample signal data. (This section of the article was generated from an M-file using the new MATLAB Editor automatic publishing features.)

Load a data set comprising signals from four instruments that use 8-bit and 16-bit analog to digital converters. Here we see the data is saved as `int8`

, `int16`

, and `uint16`

, and time is stored as `int16`

.

`load integersignal;`

% Look at variables

whos Signal1 Signal2 Signal3 Signal4 Time1

Name | Size | Bytes | Class |

Signal1 | 7550x1 | 7550 | int8 array |

Signal2 | 7550x1 | 7550 | int8 array |

Signal3 | 7550x1 | 15100 | uint16 array |

Signal4 | 7550x1 | 15100 | uint16 array |

Time1 | 7550x1 | 15100 | uint16 array |

`Grand total is 37750 elements using 60400 bytes`

Plot two of the signals to see the signal ranges:

`plot(Time1, Signal1, Time1, Signal2);`

grid;

legend('Signal1','Signal2');

Here we see the values are in the range –128 to 127, which is as we would expect for int8. It is likely that these values would need to be scaled to calculate the actual physical value that the signal represents, for example, volts.

Let’s say we want to calculate the sum of Signal1 and Signal2.

`SumSig = Signal1 + Signal2; % Here we sum the integer signals.`

The resulting variable SumSig is of type int8. We can turn on a warning to alert us if the arithmetic overflows. In the case of int8, overflow will occur if the result of an operation is outside the range –128 to 127. We use the `intwarning`

command to turn on the warning, and re-execute.

`intwarning on;`

SumSig = Signal1 + Signal2; % Here we sum the integer signals again.`Warning: Out of range value or NaN computed in integer arithmetic.`

Performing this checking greatly slows down execution. It is best to turn it on during algorithm development and disable it during final execution to maximize performance.

Plot the sum signal and see where it may have saturated:

`intwarning off`

plot(Time1, SumSig);

hold on;

% Find where it may have saturated

Saturated = (SumSig == intmin('int8')) | (SumSig == intmax('int8'));

plot(Time1(Saturated),SumSig(Saturated),'rd');grid;

hold off;

The markers show where the signal may have saturated.

First, load in two JPEG images:

`street1=imread('street1.jpg');`

street2=imread('street2.jpg');

whos street1 street2

Name | Size | Bytes | Class |

street1 | 480x640x3 | 921600 | uint8 array |

street2 | 480x640x3 | 921600 | uint8 array |

`Grand total is 1843200 elements using 1843200 bytes`

Here we see the images are 24-bit color, stored as three planes of `uint8`

data.

Next, display the images:

`image(street1); % Display image`

axis equal; axis off

`image(street2); % Display image`

axis equal; axis off

We can scale an image by a double-precision constant while keeping the result image stored as integers. For example:

`duller = 0.5 * street2; % Scale image with a double constant`

whos duller

Name | Size | Bytes | Class |

duller | 480x640x3 | 921600 | uint8 array |

`Grand total is 921600 elements using 921600 bytes`

Here we display the images side by side.

`subplot(1,2,1);`

image(street2);

axis off equal tight

title('Original'); % Display image

subplot(1,2,2);

image(duller);

axis off equal tight

title('Duller'); % Display image

Finally, add the two street images together and plot the ghostly result.

`combined = street1 + duller; % Add |uint8| images`

clf;

image(combined); % Display image

title('Combined');

axis equal; axis off

MATLAB 7 does not support complex integer operations and 64-bit integer operations. If you need such features please let us know.

The single-precision data type requires 32 bits to store in memory and is ideal for storing and processing real number values when you don’t require the same level of accuracy as that provided by double precision.

Most of the built-in MATLAB functions that perform mathematical operations on type double now support inputs of type single. This includes arithmetic operators, linear algebra, elementary and trig functions, filtering, and FFT s. Other functions that are useful when dealing with floating-point data types (both single-precision and double-precision) are `realmax`

, `realmin`

, `isfloat(x)`

, `isa(x,'float')`

, `cast`

, `ones`

, `zeros`

, `eye`

, `inf`

, `nan`

and `eps`

. The single data type was available in versions before MATLAB 7, however, no mathematical functions or operators to process them were provided.

By using singles to represent data instead of converting to doubles, you can process single-precision data sets twice the size that could be processed in earlier MATLAB versions. Single-precision values can also simulate the precision used in an embedded system, such as a 32-bit floating-point DSP.

32-bit single-precision variables represent data to about seven decimal places, which is less accurate than doubles. This inaccuracy results in a greater round-off error in representing values and during arithmetic that compounds during complicated algorithms involving many operations. The programmer should be aware of this issue and address it in his or her program.

To convert a variable to a single data type, you must pass it to the `single`

or `cast`

function:

`>> As=single(A) % or`

>> As=cast(A,'single');

You can combine numbers of type single with numbers of type double or single. MATLAB performs arithmetic as if both inputs had type single and returns a result of type single. (The complete set of rules describing how single types interact with other data is described in the MATLAB documentation.)

The following M-code provides examples of arithmetic and linear algebra using single-precision data.

Create a data set, which is double-precision by default:

` Ad = [1 2 0; 2 5 -1; 4 10 -1]`

`Ad =`

1 | 2 | 0 | |

2 | 5 | -1 | |

4 | 10 | -1 |

Convert data to single-precision with the `single`

function.

`A = single(Ad);`

B = single(rand(3,3));

We can also create single-precision zeros and ones with their respective functions.

`n=1000;`

Z=zeros(n,1,'single');

O=ones(n,1,'single');

Let’s look at the variables in the workspace.

`whos A B Ad O Z n`

Name | Size | Bytes | Class |

A | 3x3 | 36 | single array |

B | 3x3 | 36 | single array |

Ad | 3x3 | 72 | double array |

O | 1000x1 | 4000 | single array |

Z | 1000x1 | 4000 | single array |

n | 1x1 | 8 | double array |

`Grand total is 2028 elements using 8152 bytes `

We can see that some of the variables are of type single and that the variable A (the single-precision version of Ad) takes half the number of bytes of memory to store because singles require only 4 bytes (32 bits), whereas doubles require 8 bytes (64 bits).

We can perform arithmetic and linear algebra on singles.

`C = A .* B % Elementwise arithmetic`

`C =`

0.4103 | 0.7057 | 0 | |

1.7873 | 4.0658 | -0.2028 | |

0.2316 | 0.0986 | -0.1987 |

`whos C`

Name | Size | Bytes | Class |

C | 3x3 | 36 | single array |

`Grand total is 9 elements using 36 bytes`

We see the result of this operation, C, is a single. The following operations show more examples of MATLAB processing single-precision data.

`C = A * B % Matrix multiplication`

`C =`

2.1976 | 1.9792 | 0.5444 | |

5.2309 | 4.7617 | 1.0929 | |

10.5197 | 9.5333 | 2.3845 |

`A = C / B % Matrix division`

`A =`

1.0000 | 2.0000 | -0.0000 | |

2.0000 | 5.0000 | -1.0000 | |

4.0000 | 10.0000 | -1.0000 |

`E = eig(A) % Eigenvalues`

`E =`

3.7320 | |

0.2680 | |

0.9999 |

`F = fft(A(:,1)) % FFT`

`F =`

7.0000 | |

-2.0000 + 1.7321i | |

-2.0000 - 1.7321i |

`P = round(poly(A)) % The characteristic polynomial of a matrix`

`P =`

1 | -5 | 5 | -1 |

`Q = conv(P,P) % Convolve two vectors`

`Q =`

1 | -10 | 35 | -52 | 35 | -10 | 1 |

`stem(Q); % Plot the result`

In summary, now that MATLAB 7 supports math on integer and single-precision data, you can store such data more efficiently and avoid having to convert it to doubles before processing. You can handle data sets that are twice as large in the case of single-precision data and up to 8 times as large in the case of integer data. You can now stay in the MATLAB environment to perform such work without resorting to C, C++ or Fortran.

Published 2004