13 views (last 30 days)
Show older comments
Life is Wonderful on 14 Oct 2021
-
-
Link
Direct link to this question
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object
Edited: Life is Wonderful on 26 Oct 2021
Accepted Answer: Tom Bryan
Open in MATLAB Online
Hi
I am trying to make a fixed point calculation with below code. But I run into error , I don't understand what is wrong in my code.
Note : Error results
clearvars;clc;
% define ranage for input data
base = fi([-1:-1:-(2^3),1:1:(2^3)],1,32,27);
exp = fi([-(2^4-6):1:-1,1:1:(2^4-6)],1,32,27);
power = 1;
if (exp > 0)
while(exp~=0)
power = power * base;
exp = accumneg(exp, 1);
end
else
while(exp~=0)
power = power * 1/base;
exp = accumpos(exp , 1);
end
end
Error using embedded.fi/mrdivide>fidivide (line 56)
For fi objects, B must be a scalar in A/B.
Error in / (line 23)
c = fidivide(a,b);
Without fi object code, below code is fine
clearvars;clc;
% define ranage for input data
base = [-1:-1:-(2^3),1:1:(2^3)];
exp = [-(2^4-6):1:-1,1:1:(2^4-6)];
power = 1;
fprintf('%20s|%20s|%20s|%20s|%20s|%20s|\n','i','j','power','base','exponent','NBits')
for i = 1:length(base)
for j = 1:length(exp)
power(i,j) = power_flpt(base(i),exp(j));
Bits = power(i,j);
NBits = log2(Bits);
fprintf('%20d|%20d|%20f|%20f|%20f|%20f|\n',i,j,power(i,j),base(i),exp(j),NBits);
end
end
function power = power_flpt(base,exp)
power = 1;
if (exp > 0)
while(exp~=0)
power = power * base;
exp = accumneg(exp, 1);
end
else
while(exp~=0)
power = power * 1/base;
exp = accumpos(exp , 1);
end
end
end
0 Comments Show -2 older commentsHide -2 older comments
Show -2 older commentsHide -2 older comments
Sign in to comment.
Sign in to answer this question.
Accepted Answer
Tom Bryan on 14 Oct 2021
Open in MATLAB Online
The error is telling you that 1/base isn't supported in fi because base is a vector. The error is telling you that base must be a scalar for mrdivide (matrix right-divide). Element-wise division is 1./base, which would not have thrown an error, but the first code was logically incorrect anyway. The first code didn't give the right answer with double either. It was using things like "if (exp > 0)" where exp is a vector, so the if condition was never entered. Also the "while(exp~=0)" condition was never entered either.
The second code works with both fixed-point and floating-point becasue the power_fltpt function only uses scalars.
Also, both exp and power are builtin MATLAB functions, so you should think about renaming them. MATLAB is forgiving about overloading other functions, but it may interfere if you ever want to use the exp or power functions.
Enclosed below is your second code running with both fixed-point and floating point, and comparing the answers at the end.
clearvars;clc;
% define ranage for input data
base = fi([-1:-1:-(2^3),1:1:(2^3)],1,32,27);
exp = fi([-(2^4-6):1:-1,1:1:(2^4-6)],1,32,27);
fprintf('\n---------------------------------\n')
fprintf('Fixed Point\n')
power_fixedpoint = power_loop(base,exp);
fprintf('\n---------------------------------\n')
fprintf('Double\n')
power_float = power_loop(double(base),double(exp));
fprintf('\n---------------------------------\n')
fprintf('Difference\n')
difference = power_float - double(power_fixedpoint) %#ok<NOPTS>
max_difference = max(abs(difference(:))) %#ok<NOPTS>
function power = power_loop(base,exp)
power = ones(length(base),length(exp));
fprintf('%20s|%20s|%20s|%20s|%20s|%20s|\n','i','j','power','base','exponent','NBits')
for i = 1:length(base)
for j = 1:length(exp)
power(i,j) = power_scalar_function(base(i),exp(j));
Bits = power(i,j);
NBits = log2(Bits);
fprintf('%20d|%20d|%20f|%20f|%20f|%20f|\n',i,j,power(i,j),base(i),exp(j),NBits);
end
end
end
function power = power_scalar_function(base,exp)
power = 1;
if (exp > 0)
while(exp~=0)
power(:) = power * base;
exp = accumneg(exp, 1);
end
else
while(exp~=0)
power(:) = power * 1/base;
exp = accumpos(exp , 1);
end
end
end
Best wishes,
Tom Bryan
15 Comments Show 13 older commentsHide 13 older comments
Show 13 older commentsHide 13 older comments
Life is Wonderful on 14 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1784656
Open in MATLAB Online
Thanks for Nice and clear explanation !!
May be your right but it seems
power(:) = power * base;
is causing Error and i am stuck
In fi .* non-fi, or non-fi .* fi, the non-fi must be a constant.
Can you please share your input to resolve Error .
Thank you!!
Tom Bryan on 14 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1784726
I have a few follow up questions to know how to answer:
- Are you trying to do code generation? This error only occurs during code generation.
- You have defined the variable power to be floating-point double. Do you want the code to be purely fixed-point?
- Do you want to generate C code? or a MEX function to simulate in MATLAB?
Best wishes,
Tom Bryan
Life is Wonderful on 15 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1785216
Edited: Life is Wonderful on 15 Oct 2021
Please find inline answers ( Italics and Monospace)
Are you trying to do code generation? This error only occurs during code generation.
Yes, that's right requirement
You have defined the variable power to be floating-point double. Do you want the code to be purely fixed-point?
Yes, code is purely fixed point
Do you want to generate C code? or a MEX function to simulate in MATLAB?
Generate C Code
Thank you!!
Tom Bryan on 15 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1786316
I'm using the methods described in article Best Practices for Converting MATLAB Code to Fixed Point. I'm the person who created the fi object and the "cast-like" syntax described there. By using this method, your code can run both fixed-point and floating-point.
A few notes about the code listed below:
- The range of the magnitude of the output is between and . This means that you need at least 30 integer bits, and 30 fractional bits in the output. The output is also positive and negative. To accomodate this, I chose a signed fixed-point type with a 64 bit word length and 32 bit fraction length.
- You can see in the generated code that the large word length of the output means that multiple words of builtin C types were needed for intermediate products and sums.
- I changed the names of the variables from base, exp, power to b, e, p respectively so the builtin functions of the same name would not be overloaded.
- I separated out the functions that you want to generate code for from the test bench.
- The test bench compiles and runs fixed-point as a MATLAB Executable (MEX).
- The test bench also generates C code for the fixed-point function.
- Run MATLAB script test_bench to test and compile the code.
- Save each of the functions enclosed below in their own file.
Best wishes,
Tom Bryan
Tom Bryan on 15 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1786321
Open in MATLAB Online
%% test_bench
%% Define input data
b = fi([-1:-1:-(2^3),1:1:(2^3)],1,32,27);
e = fi([-(2^4-6):1:-1,1:1:(2^4-6)],1,32,27);
%% Generate a MEX function for fixed-point inputs
codegen power_scalar_function -args {b(1),e(1)} ...
-o power_scalar_function_fixedpoint_mex -config:mex
%% Run fixed point
fprintf('\n---------------------------------\n')
fprintf('Fixed Point\n')
power_fixedpoint = power_loop(b,e);
%% Run floating point
fprintf('\n---------------------------------\n')
fprintf('Double\n')
power_float = power_loop(double(b),double(e));
%% Compare fixed point to floating point
fprintf('\n---------------------------------\n')
fprintf('Difference\n')
difference = power_float - double(power_fixedpoint) %#ok<NOPTS>
max_difference = max(abs(difference(:))) %#ok<NOPTS>
%% Generate C code
codegen power_scalar_function -args {b(1),e(1)} -config:lib -launchreport
%% Look at the stored integer values of power_fixedpoint
stored_integer_values = storedInteger(power_fixedpoint) %#ok<NOPTS>
Tom Bryan on 15 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1786326
Open in MATLAB Online
function p = power_loop(b,e)
T = power_types(b);
p = ones(length(b),length(e),'like',T.p);
fprintf('%20s|%20s|%20s|%20s|%20s|%20s|\n','i','j','power','base','exponent','NBits')
for i = 1:length(b)
for j = 1:length(e)
if isfi(b)
p(i,j) = power_scalar_function_fixedpoint_mex(b(i),e(j));
else
p(i,j) = power_scalar_function(b(i),e(j));
end
Bits = p(i,j);
NBits = log2(double(Bits));
fprintf('%20d|%20d|%20f|%20f|%20f|%20f|\n',i,j,p(i,j),b(i),e(j),NBits);
end
end
end
Tom Bryan on 15 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1786331
Open in MATLAB Online
function p = power_scalar_function(b,e)
T = power_types(b);
p = cast(1,'like',T.p);
if (e > 0)
while(e~=0)
p(:) = p * b;
e = accumneg(e, 1);
end
else
while(e~=0)
p(:) = p * 1/b;
e = accumpos(e , 1);
end
end
end
Tom Bryan on 15 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1786336
Open in MATLAB Online
function T = power_types(prototype)
if isfi(prototype)
% The range of the magnitude of the output is between 2^30 and
% 2^-30. This means that you need at least 30 integer bits, and 30
% fractional bits in the output. The output is also positive and
% negative. To accomodate this, I chose a signed fixed-point type
% with a 64 bit word length and 32 bit fraction length.
T.p = fi([],1,64,32);
else
% If not fixed-point, cast the output to the same type as the
% input.
T.p = cast([],'like',prototype);
end
end
Life is Wonderful on 16 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1786926
Edited: Life is Wonderful on 16 Oct 2021
Dear @Tom Bryan,
Thanks a lot for sharing such flawless notes and implementation.
It's the best shared answer ( communication , making user understand/guidelines how to use code generation in a perfect way and technically correct soulution to match floating and fixed point implementation) . Personally, I haven't seen any thing exceeding current solution in the entire Mathworks community. It shows your experience and hard work to reach such heigths.
One request and recommendation, if you think current power implementation cover's all bases/corner cases, please replace existing power function Code generation in MathWorks. It is buggy - doesn't work.
I will do more test , share my feedback ( i see if can break it ) otherwise I will close/accept the answer.
Cheers,
best regards
Tom Bryan on 16 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1786991
Thanks. It's my pleasure.
Could you provide a reproduction step to show me a bug in code generation for the power function?
For example, it would be a function using power that has a bug when you do codegen on it.
Best wishes,
Tom Bryan
Life is Wonderful on 16 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1787226
Edited: Life is Wonderful on 16 Oct 2021
Open in MATLAB Online
Hi Tom,
It is simple , From the current / your proposal you can see with following changes ( no change in your proposed solution
function p = power_scalar_function(b,e)
T = power_types(b);
p = cast(1,'like',T.p);
p = power(b,e);
% if (e > 0)
% while(e~=0)
% p(:) = p * b;
% e = accumneg(e, 1);
% end
% else
% while(e~=0)
% p(:) = p * 1/b;
% e = accumpos(e , 1);
% end
% end
end
Error - Message
??? ProductMode must be SpecifyPrecision when the power exponent input is not constant. This assures that the output data type can be determined at compile time.
Error in ==> power_scalar_function Line: 4 Column: 9
Code generation failed: View Error Report
Error using codegen
Error in testbench (line 7)
codegen power_scalar_function -args {b(1),e(1)} ...
- Debugging data for your reference
>> testbench
Code generation successful.
---------------------------------
Fixed Point
i| j| power| base| exponent| NBits|
1| 1| 1.000000000000000| -1.000000| -10.000000| 0.000000|
K>> class(b)
ans =
'embedded.fi'
K>> class(e)
ans =
'embedded.fi'
K>> power(b,e)
Error using fixed.internal.power.validateK (line 13)
Exponent input to 'power' must be a real scalar and the value must be a non-negative integer.
Error in fixed.internal.power.powImpl>validateInputs (line 39)
fixed.internal.power.validateK(k);
Error in fixed.internal.power.powImpl (line 9)
validateInputs(a, k);
Error in .^ (line 32)
y = fixed.internal.power.powImpl(a, k);
Also , for your refernce, I have another issue open.
Link -
Issue Description
https://in.mathworks.com/matlabcentral/answers/1464099-stop-bit-growth-for-power-computation?s_tid=srchtitle
Test cases
https://in.mathworks.com/matlabcentral/answers/1464099-stop-bit-growth-for-power-computation#comment_1763044
It would nice , if you have a look and suggest MathWorks ( if you agree )
Thank you
best regards,
Life is Wonderful on 16 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1787241
Edited: Life is Wonderful on 26 Oct 2021
Open in MATLAB Online
function T = power_types(prototype)
https://in.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1786336
Need suggestion and advice on your Code generation ,
I have used "accumneg" and "accumpos" function to avoid MultiWord but I still see MultiWord~ ( making word length shorter 32 bit could lead to inaccuracies and lower total harmonic distortion ) therby I need your help and guidence.
I choose a signed fixed-point type with a 64 bit word length and 32 bit fraction length
- is generating MultiWord* , is there a suggestion to overcome this hurdle since it considerably slows down the DSP implementation [ i need 32 bit implementation and not higher ] and it take some efforts/ intelligence/ rework to make the code fast.
If you have guide/document link , tricks to eliminate or script , I welcome your inputs.
Note -
T.p = fi([],1,64,32); % original
T.p = fi([],1,32,32); % modified -Reducing WL, No MultiWord* is generated but accuracy suffers
Thank you in advance .
Tom Bryan on 16 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1787471
Can you tell me about the overall problem you're trying to solve? In what context are you using this function?
It may be possible to refactor the original problem into something that requires much less dynamic range. For example, it is often possible to work in the logarithmic domain instead of the exponential domain.
Best wishes,
Tom Bryan
tbryan@mathworks.com
Tom Bryan on 16 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1787511
The error with the builtin fi power method is a limitation but not a bug. The error message is telling you how to set the fimath to meet the requirements to use with a fi object: "Exponent input to 'power' must be a real scalar and the value must be a non-negative integer." See the documentation for fimath for how to use it with a fi object.
After setting fimath, you will run into another limitation with the builtin fi power method. It only works with positive exponents, and your example uses positive and negative exponents. Again, this is a limitation but not a bug.
Life is Wonderful on 17 Oct 2021
Direct link to this comment
https://support.mathworks.com/matlabcentral/answers/1563361-error-in-fi-divide-for-embedded-fi-object#comment_1787716
Many thanks . Yes , I can understand limitation !!
best regards
Sign in to comment.
More Answers (0)
Sign in to answer this question.
An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- Deutsch
- English
- Français
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)
Contact your local office