Default Behaviors of Automated Fixed-Point Conversion
This page describes the default behaviors of automated fixed point conversion in MATLAB®. Use this information to understand the underlying processes that effect your generated fixed-point code.
Minimize fi-casts to Improve Code Readability
Automated conversion reduces the number of fi-casts when it is possible
by analyzing the floating-point code. If an arithmetic operation is comprised of only
compile-time constants, the conversion process does not cast the operands to fixed point
individually. Instead, it casts the entire expression to fixed point. Reducing the number of
fi-casts makes the code more readable and can improve the efficiency of
generated code.
For example, here is the fixed-point code generated for the constant expression x
= 1/sqrt(2) when the selected word length is 14.
| Original MATLAB Code | Generated Fixed-Point Code |
|---|---|
x = 1/sqrt(2); |
x = fi(1/sqrt(2), 0, 14, 14, fm);
|
Avoid Overflows in Generated Fixed-Point Code
Automated conversion avoids overflows by:
Using full-precision arithmetic unless you specify otherwise.
Avoiding arithmetic operations that involve both double and
fidata types. These operations are avoided because overflows occur if the word length of thefidata type is not able to represent the value in the double constant expression.Avoiding overflows when adding and subtracting non fixed-point variables and fixed-point variables by casting non-
fiexpressions to the correspondingfitype.For example, consider the following MATLAB algorithm.
% A = 5; % B = ones(300, 1); function y = fi_plus_non_fi(A, B) % '1024' is non-fi, cast it y = A + 1024; % 'size(B, 1)*length(A)' is a non-fi, cast it y = A + size(B, 1)*length(A); end
The generated fixed-point code is:
%#codegen function y = fi_plus_non_fi_fixpt(A, B) fm = get_fimath(); y = fi(A + fi(1024, 0, 11, 0, fm), 0, 11, 0, fm); y(:) = A + size(B, fi(1, 0, 1, 0, fm))*length(A); end function fm = get_fimath() fm = fimath('RoundingMethod', 'Floor',... 'OverflowAction', 'Wrap',... 'ProductMode','FullPrecision',... 'MaxProductWordLength', 128,... 'SumMode','FullPrecision',... 'MaxSumWordLength', 128); end
Control Bit Growth
The conversion process controls bit growth by using subscripted assignments, that is, assignments that use the colon (:) operator, in the generated code. When you use subscripted assignments, MATLAB overwrites the value of the left-hand side argument but retains the existing data type and array size. Using subscripted assignment keeps fixed-point variables fixed point rather than turning them into doubles. Maintaining the fixed-point type reduces the number of type declarations in the generated code. Subscripted assignment also prevents bit growth which is useful when you want to maintain a particular data type for the output.
Avoid Loss of Range or Precision
Avoid Loss of Range or Precision in Unsigned Subtraction Operations
When the result of a subtraction is negative, automated conversion promotes the left operand to a signed type to ensure that the result can represent negative numbers.
For example, consider the following MATLAB algorithm.
% A = 1; % B = 5 function y = unsigned_subtraction(A,B) y = A - B; end
In the original code, both A and B have unsigned
data types. Then the result of A-B also has an unsigned type that cannot
accurately represent the negative value 1 minus 5. To
resolve this, in the generated fixed-point code, A is promoted to signed.
%#codegen function y = unsigned_subtraction_fixpt(A,B) fm = get_fimath(); y = fi(fi_signed(A) - B, 1, 3, 0, fm); end function y = fi_signed(a) coder.inline( 'always' ); if isfi( a ) && ~(issigned( a )) nt = numerictype( a ); new_nt = numerictype( 1, nt.WordLength + 1, nt.FractionLength ); y = fi( a, new_nt, fimath( a ) ); else y = a; end end function fm = get_fimath() fm = fimath('RoundingMethod', 'Floor',... 'OverflowAction', 'Wrap',... 'ProductMode','FullPrecision',... 'MaxProductWordLength', 128,... 'SumMode','FullPrecision',... 'MaxSumWordLength', 128); end
Avoid Loss of Range When Concatenating Arrays of Fixed-Point Numbers
If you concatenate matrices using vertcat and
horzcat, automated conversion uses the largest numerictype among the
expressions of a row and casts the leftmost element to that type. This type is then used for
the concatenated matrix to avoid loss of range.
For example, consider the following MATLAB algorithm.
% A = 1, B = 100, C = 1000 function [y, z] = lb_node(A, B, C) %% single rows y = [A B C]; %% multiple rows z = [A 5; A B; A C]; end
In the generated fixed-point code:
For the expression
y = [A B C], the leftmost element,A, is cast to the type ofCbecauseChas the largest type in the row.For the expression
[A 5; A B; A C]:In the first row,
Ais cast to the type ofCbecauseChas the largest type of the whole expression.In the second row,
Ais cast to the type ofBbecauseBhas the larger type in the row.In the third row,
Ais cast to the type ofCbecauseChas the larger type in the row.
%#codegen function [y, z] = lb_node_fixpt(A, B, C) %% single rows fm = get_fimath(); y = fi([fi(A, 0, 10, 0, fm) B C], 0, 10, 0, fm); %% multiple rows z = fi([fi(A, 0, 10, 0, fm) 5; fi(A, 0, 7, 0, fm) B; fi(A, 0, 10, 0, fm) C], 0, 10, 0, fm); end function fm = get_fimath() fm = fimath('RoundingMethod', 'Floor',... 'OverflowAction', 'Wrap',... 'ProductMode','FullPrecision',... 'MaxProductWordLength', 128,... 'SumMode','FullPrecision',... 'MaxSumWordLength', 128); end
Handling Non-Constant mpower Exponents
If the function that you are converting has a scalar input, and the
mpower exponent input is not constant, automated conversion sets the
fimath
ProductMode to SpecifyPrecision in the generated code.
With this setting , the output data type can be determined at compile time.
For example, consider the following MATLAB algorithm.
% a = 1 % b = 3 function y = exp_operator(a, b) % exponent is a constant so no need to specify precision y = a^3; % exponent is not a constant, use 'SpecifyPrecision' for 'ProductMode' y = b^a; end
In the generated fixed-point code, for the expression y = a^3 , the
exponent is a constant, so there is no need to specify
precision. For the expression, y = b^a, the exponent is not constant, so
the ProductMode is set to SpecifyPrecision.
%#codegen % a = 1 % b = 3 function y = exp_operator_fixpt(a, b) % exponent is a constant so no need to specify precision fm = get_fimath(); y = fi(a^3, 0, 2, 0, fm); % exponent is not a constant, use 'SpecifyPrecision' for 'ProductMode' y(:) = fi(b, 'ProductMode', 'SpecifyPrecision', 'ProductWordLength', 2, 'ProductFractionLength', 0, 'SumMode', 'SpecifyPrecision', 'SumWordLength', 2, 'SumFractionLength', 0, 'Signedness', 'Unsigned', 'WordLength', 2, 'FractionLength', 0)^a; end function fm = get_fimath() fm = fimath('RoundingMethod', 'Floor',... 'OverflowAction', 'Wrap',... 'ProductMode','FullPrecision',... 'MaxProductWordLength', 128,... 'SumMode','FullPrecision',... 'MaxSumWordLength', 128); end