# Set Fixed-Point Math Attributes

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

Use the `fimath` object to control fixed-point math attributes for assignment, addition, subtraction, and multiplication. Use the `setfimath` function to attach a `fimath` object to a `fi` object. Use the `removefimath` function to remove a `fimath` object from a `fi` object.

You can use the MATLAB Coder™ software to generate C code from these examples.

### Set and Remove Fixed Point Math Attributes

The `user_written_sum` function shows an example of how to insulate 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.

```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 ```

The `fimath` controls the arithmetic inside the function, but the returned value has no attached `fimath`. This is due to the use of `setfimath` and `removefimath` inside the `user_written_sum` function.

```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 ```

#### Generate C Code

If you have a MATLAB Coder license, you can run these commands to generate C code.

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

The `fimath`, `setfimath`, and `removefimath` functions 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.

```int user_written_sum(const short u[10]) { int i; int y; y = 0; /* Algorithm */ for (i = 0; i < 10; i++) { y += u[i]; } /* Cleanup */ return y; } ```

### Mismatched `fimath`

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'); try C = A*B catch me disp(me.message) end```
```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. The product is computed using the `fimath` attached to `A`.

`C = A * removefimath(B)`
```C = 6.2832 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 32 FractionLength: 26 RoundingMethod: Nearest OverflowAction: Saturate ProductMode: KeepLSB ProductWordLength: 32 SumMode: FullPrecision ```

### Change `fimath` on Temporary Variables

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, compute the product using 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 ```

The variable `B` is not changed.

`B`
```B = 2 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 13 ```

### Remove `fimath` Conflict in a Loop

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.

In the `setfimath_removefimath_in_a_loop` function, 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,zi) % 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(zi,F_floor); % Create y with nearest rounding y = setfimath(zeros(size(x),'like',zi),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 ```

#### Generate C Code

If you have a MATLAB Coder license, you can run these commands to generate C code using the specified hardware characteristics.

```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.DataTypeReplacement = 'CoderTypedefs'; 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} ```

The `fimath`, `setfimath` and `removefimath` functions 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], const int16_T zi[2], int16_T y[256], int16_T z[2]) { int32_T j; int16_T i; int16_T i1; /* Set fimaths that are local to this function */ /* Create y with nearest rounding */ /* Algorithm */ i = zi[0]; i1 = zi[1]; for (j = 0; j < 256; j++) { int64_T i3; int32_T y_tmp; int16_T i2; int16_T i4; /* Nearest assignment into y */ i2 = x[j]; y_tmp = 15705 * i2; i3 = y_tmp + ((int64_T)i << 20); i4 = (int16_T)((i3 >> 20) + ((i3 & 524288L) != 0L)); y[j] = i4; /* Remove y's fimath conflict with other fimaths */ i = (int16_T)(((31410 * i2 + ((int64_T)i1 << 20)) - ((int64_T)(-23826 * i4) << 6)) >> 20); i1 = (int16_T)((y_tmp - ((int64_T)(9405 * i4) << 6)) >> 20); } z[1] = i1; z[0] = i; /* Cleanup: Remove fimath from outputs */ } ```

### Polymorphic Code

You can use the `setfimath` and `removefimath` functions to write MATLAB code that can be used for both floating-point and fixed-point types.

```function y = user_written_function(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 ```

#### 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.7854 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 32 FractionLength: 15 ```

If you have a MATLAB Coder license, you can run these commands to generate C code.

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

The `fimath`, `setfimath` and `removefimath` functions 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.

```int user_written_function(short u) { /* Algorithm */ return u + u; /* Cleanup */ } ```

#### Floating-Point Double Inputs

The `user_written_function` example works with floating-point types because the `setfimath` and `removefimath` functions are pass-through for floating-point types.

```u = double(pi/8); codegen user_written_function -args {0} -config:lib -launchreport ```

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

```double user_written_function(double u) { /* Algorithm */ return u + u; /* Cleanup */ } ```

### More Polymorphic Code

The `user_written_sum_polymorphic` function is written so that the output is created to be the same type as the input. Both floating-point and fixed-point inputs can be used with the `user_written_sum_polymorphic` function.

```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 ```

#### Generate Fixed-Point C Code

If you have a MATLAB Coder license, you can run these commands to generate C code.

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

The `fimath`, `setfimath` and `removefimath` functions 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.

```int user_written_sum_polymorphic(const short u[10]) { int i; int y; y = 0; /* Algorithm */ for (i = 0; i < 10; i++) { y += u[i]; } /* Cleanup */ return y; } ```

#### Generate Floating-Point C Code

If you have a MATLAB Coder license, you can run these commands to generate C code.

```u = 1:10; codegen user_written_sum_polymorphic -args {u} -config:lib -launchreport ```
```double user_written_sum_polymorphic(const double u[10]) { double y; int i; y = 0.0; /* Algorithm */ for (i = 0; i < 10; i++) { y += u[i]; } /* Cleanup */ return y; } ```

### `setfimath` on Integer Types

Following the established pattern of treating built-in integers like `fi` objects, `setfimath` converts integer input to the equivalent `fi` with attached `fimath`.

```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 ```

If you have a MATLAB Coder license, you can run these commands to generate C code.

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

The output type was specified by the `fimath` to be 32-bit.

```int user_written_u_plus_u(signed char u) { /* Algorithm */ return u + u; /* Cleanup */ } ```

Disable editor warnings.

` %#ok<*NASGU>`