Main Content

This example shows how to set fixed point math attributes in MATLAB® code.

You can control fixed-point math attributes for assignment, addition, subtraction, and multiplication using the `fimath`

object. You can attach a `fimath`

object to a `fi`

object using `setfimath`

. You can remove a `fimath`

object from a `fi`

object using `removefimath`

.

You can generate C code from the examples if you have MATLAB Coder™ software.

You can insulate your fixed-point operations from global and local `fimath`

settings by using the `setfimath`

and `removefimath`

functions. You can also return from functions with no `fimath`

attached to output variables. This gives you local control over fixed-point math settings without interfering with the settings in other functions.

**MATLAB Code**

function y = user_written_sum(u) % Setup F = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'SumMode','KeepLSB',... 'SumWordLength',32); u = setfimath(u,F); y = fi(0,true,32,get(u,'FractionLength'),F); % Algorithm for i=1:length(u) y(:) = y + u(i); end % Cleanup y = removefimath(y); end

**Output has no Attached FIMATH**

When you run the code, the `fimath`

controls the arithmetic inside the function, but the return value has no attached `fimath`

. This is due to the use of `setfimath`

and `removefimath`

inside the function `user_written_sum`

.

>> u = fi(1:10,true,16,11); >> y = user_written_sum(u)

```
y =
55
DataTypeMode: Fixed-point: binary point scaling
Signedness: Signed
WordLength: 32
FractionLength: 11
```

**Generated C Code**

If you have MATLAB Coder software, you can generate C code using the following commands.

>> u = fi(1:10,true,16,11); >> codegen user_written_sum -args {u} -config:lib -launchreport

Functions `fimath`

, `setfimath`

and `removefimath`

control the fixed-point math, but the underlying data contained in the variables does not change and so the generated C code does not produce any data copies.

int32_T user_written_sum(const int16_T u[10]) { int32_T y; int32_T i; /* Setup */ y = 0; /* Algorithm */ for (i = 0; i < 10; i++) { y += u[i]; } /* Cleanup */ return y; }

When you operate on `fi`

objects, their `fimath`

properties must be equal, or you get an error.

>> A = fi(pi,'ProductMode','KeepLSB'); >> B = fi(2,'ProductMode','SpecifyPrecision'); >> C = A * B

Error using embedded.fi/mtimes The embedded.fimath of both operands must be equal.

To avoid this error, you can remove `fimath`

from one of the variables in the expression. In this example, the `fimath`

is removed from `B`

in the context of the expression without modifying `B`

itself, and the product is computed using the `fimath`

attached to `A`

.

>> C = A * removefimath(B)

C =

6.283203125

DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 32 FractionLength: 26

RoundingMethod: Nearest OverflowAction: Saturate ProductMode: KeepLSB ProductWordLength: 32 SumMode: FullPrecision

If you have variables with no attached `fimath`

, but you want to control a particular operation, then you can attach a `fimath`

in the context of the expression without modifying the variables.

For example, the product is computed with the `fimath`

defined by `F`

.

>> F = fimath('ProductMode','KeepLSB','OverflowAction','Wrap','RoundingMethod','Floor'); >> A = fi(pi); >> B = fi(2); >> C = A * setfimath(B,F)

C =

6.2832

DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 32 FractionLength: 26

RoundingMethod: Floor OverflowAction: Wrap ProductMode: KeepLSB ProductWordLength: 32 SumMode: FullPrecision MaxSumWordLength: 128

Note that variable `B`

is not changed.

>> B

B =

2

DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13

You can compute products and sums to match the accumulator of a DSP with floor rounding and wrap overflow, and use nearest rounding and saturate overflow on the output. To avoid mismatched `fimath`

errors, you can remove the `fimath`

on the output variable when it is used in a computation with the other variables.

**MATLAB Code**

In this example, the products are 32-bits, and the accumulator is 40-bits, keeping the least-significant-bits with floor rounding and wrap overflow like C's native integer rules. The output uses nearest rounding and saturate overflow.

function [y,z] = setfimath_removefimath_in_a_loop(b,a,x,z) % Setup F_floor = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'ProductMode','KeepLSB',... 'ProductWordLength',32,... 'SumMode','KeepLSB',... 'SumWordLength',40); F_nearest = fimath('RoundingMethod','Nearest',... 'OverflowAction','Wrap'); % Set fimaths that are local to this function b = setfimath(b,F_floor); a = setfimath(a,F_floor); x = setfimath(x,F_floor); z = setfimath(z,F_floor); % Create y with nearest rounding y = coder.nullcopy(fi(zeros(size(x)),true,16,14,F_nearest)); % Algorithm for j=1:length(x) % Nearest assignment into y y(j) = b(1)*x(j) + z(1); % Remove y's fimath conflict with other fimaths z(1) = (b(2)*x(j) + z(2)) - a(2) * removefimath(y(j)); z(2) = b(3)*x(j) - a(3) * removefimath(y(j)); end % Cleanup: Remove fimath from outputs y = removefimath(y); z = removefimath(z); end

**Code Generation Instructions**

If you have MATLAB Coder software, you can generate C code with the specified hardware characteristics using the following commands.

N = 256; t = 1:N; xstep = [ones(N/2,1);-ones(N/2,1)]; num = [0.0299545822080925 0.0599091644161849 0.0299545822080925]; den = [1 -1.4542435862515900 0.5740619150839550];

b = fi(num,true,16); a = fi(den,true,16); x = fi(xstep,true,16,15); zi = fi(zeros(2,1),true,16,14);

B = coder.Constant(b); A = coder.Constant(a);

config_obj = coder.config('lib'); config_obj.GenerateReport = true; config_obj.LaunchReport = true; config_obj.TargetLang = 'C'; config_obj.GenerateComments = true; config_obj.GenCodeOnly = true; config_obj.HardwareImplementation.ProdBitPerChar=8; config_obj.HardwareImplementation.ProdBitPerShort=16; config_obj.HardwareImplementation.ProdBitPerInt=32; config_obj.HardwareImplementation.ProdBitPerLong=40;

codegen -config config_obj setfimath_removefimath_in_a_loop -args {B,A,x,zi} -launchreport

**Generated C Code**

Functions `fimath`

, `setfimath`

and `removefimath`

control the fixed-point math, but the underlying data contained in the variables does not change and so the generated C code does not produce any data copies.

void setfimath_removefimath_in_a_loop(const int16_T x[256], int16_T z[2], int16_T y[256]) { int32_T j; int40_T i0; int16_T b_y;

/* Setup */ /* Set fimaths that are local to this function */ /* Create y with nearest rounding */ /* Algorithm */ for (j = 0; j < 256; j++) { /* Nearest assignment into y */ i0 = 15705 * x[j] + ((int40_T)z[0] << 20); b_y = (int16_T)((int32_T)(i0 >> 20) + ((i0 & 524288L) != 0L));

/* Remove y's fimath conflict with other fimaths */ z[0] = (int16_T)(((31410 * x[j] + ((int40_T)z[1] << 20)) - ((int40_T)(-23826 * b_y) << 6)) >> 20); z[1] = (int16_T)((15705 * x[j] - ((int40_T)(9405 * b_y) << 6)) >> 20); y[j] = b_y; }

/* Cleanup: Remove fimath from outputs */ }

You can write MATLAB code that can be used for both floating-point and fixed-point types using `setfimath`

and `removefimath`

.

function y = user_written_function(u) % Setup F = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'SumMode','KeepLSB'); u = setfimath(u,F); % Algorithm y = u + u; % Cleanup y = removefimath(y); end

**Fixed Point Inputs**

When the function is called with fixed-point inputs, then `fimath`

`F`

is used for the arithmetic, and the output has no attached `fimath`

.

>> u = fi(pi/8,true,16,15,'RoundingMethod','Convergent'); >> y = user_written_function(u)

y =

0.785400390625

DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 32 FractionLength: 15

**Generated C Code for Fixed Point**

If you have MATLAB Coder software, you can generate C code using the following commands.

>> u = fi(pi/8,true,16,15,'RoundingMethod','Convergent'); >> codegen user_written_function -args {u} -config:lib -launchreport

Functions `fimath`

, `setfimath`

and `removefimath`

control the fixed-point math, but the underlying data contained in the variables does not change and so the generated C code does not produce any data copies.

int32_T user_written_function(int16_T u) { /* Setup */ /* Algorithm */ /* Cleanup */ return u + u; }

**Double Inputs**

Since `setfimath`

and `removefimath`

are pass-through for floating-point types, the `user_written_function`

example works with floating-point types, too.

function y = user_written_function(u) % Setup F = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'SumMode','KeepLSB'); u = setfimath(u,F); % Algorithm y = u + u; % Cleanup y = removefimath(y); end

**Generated C Code for Double**

When compiled with floating-point input, you get the following generated C code.

>> codegen user_written_function -args {0} -config:lib -launchreport

real_T user_written_function(real_T u) { return u + u; }

Where the `real_T`

type is defined as a `double`

:

typedef double real_T;

This function is written so that the output is created to be the same type as the input, so both floating-point and fixed-point can be used with it.

function y = user_written_sum_polymorphic(u) % Setup F = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'SumMode','KeepLSB',... 'SumWordLength',32);

u = setfimath(u,F);

if isfi(u) y = fi(0,true,32,get(u,'FractionLength'),F); else y = zeros(1,1,class(u)); end

% Algorithm for i=1:length(u) y(:) = y + u(i); end

% Cleanup y = removefimath(y);

```
end
```

**Fixed Point Generated C Code**

If you have MATLAB Coder software, you can generate fixed-point C code using the following commands.

>> u = fi(1:10,true,16,11); >> codegen user_written_sum_polymorphic -args {u} -config:lib -launchreport

`fimath`

, `setfimath`

and `removefimath`

control the fixed-point math, but the underlying data contained in the variables does not change and so the generated C code does not produce any data copies.

int32_T user_written_sum_polymorphic(const int16_T u[10]) { int32_T y; int32_T i;

/* Setup */ y = 0;

/* Algorithm */ for (i = 0; i < 10; i++) { y += u[i]; }

/* Cleanup */ return y; }

**Floating Point Generated C Code**

If you have MATLAB Coder software, you can generate floating-point C code using the following commands.

>> u = 1:10; >> codegen user_written_sum_polymorphic -args {u} -config:lib -launchreport

real_T user_written_sum_polymorphic(const real_T u[10]) { real_T y; int32_T i;

/* Setup */ y = 0.0;

/* Algorithm */ for (i = 0; i < 10; i++) { y += u[i]; }

/* Cleanup */ return y; }

Where the `real_T`

type is defined as a `double`

:

typedef double real_T;

Following the established pattern of treating built-in integers like `fi`

objects, `setfimath`

converts integer input to the equivalent `fi`

with attached `fimath`

.

>> u = int8(5); >> codegen user_written_u_plus_u -args {u} -config:lib -launchreport

function y = user_written_u_plus_u(u) % Setup F = fimath('RoundingMethod','Floor',... 'OverflowAction','Wrap',... 'SumMode','KeepLSB',... 'SumWordLength',32); u = setfimath(u,F); % Algorithm y = u + u; % Cleanup y = removefimath(y); end

The output type was specified by the `fimath`

to be 32-bit.

int32_T user_written_u_plus_u(int8_T u) { /* Setup */ /* Algorithm */ /* Cleanup */ return u + u; }