Error in generating C/C++ codes: Cannot assign a complex value into a non-complex location

Codegen is giving the same error for this line:
state.icaweights = V / sqrt(D) * V' * state.icaweights;
When I tried the codegen again by writing:
state.icaweights = complex(V / sqrt(D) * V' * state.icaweights);
OR
state.icaweights = double(V / sqrt(D) * V' * state.icaweights);
it still provided the same error. Can anyone please help in rectification of this error?

回答 (1 件)

Walter Roberson
Walter Roberson 2021 年 9 月 13 日

1 投票

state.icaweights has been created as non-complex, but either V is complex or D is suspected of being negative so code generation figures that the right hand side is generating a complex value.
If you are expecting complex values, then you need to initialize state.icaweights to complex.
For example if you initialized it to 0 before, then initialize it to complex(0,0)

6 件のコメント

PIYUSH SWAMI
PIYUSH SWAMI 2021 年 9 月 13 日
編集済み: PIYUSH SWAMI 2021 年 9 月 14 日
Thanks, I intialized the value to complex and it worked. But now, the output being generated using the MEX is complex and different even though the output using the .m file is still double. Does anyone know why this is occuring and how can I get the same outputs?
Walter Roberson
Walter Roberson 2021 年 9 月 14 日
Are you taking roots of a polynomial of degree more than 2 ? And you are expecting real-valued outputs ?
roots here could possibly include eigenvalues for this purpose.
PIYUSH SWAMI
PIYUSH SWAMI 2021 年 9 月 16 日
編集済み: Walter Roberson 2021 年 9 月 16 日
% orthogonalize weight matrix
[V, D] = eig(state.icaweights * state.icaweights');
state.icaweights = V/sqrt(D)*V' * state.icaweights;
Yes, I am calculating eigen values just before the last line. To my surprise, when I run the program in matlab, it does not produce complex weights. It is gives this error only when I use coder.
1) Can you please tell me why is it required to initilize state.icaweights as complex location when it is actually non-complex values?
2) Can you please let me know how can I rectify this error to generate MEX and C++ codes which provides the same outputs as running the .m file in matlab?
Walter Roberson
Walter Roberson 2021 年 9 月 16 日
If your system is larger than 2 x 2, then the eigenvalues involve numeric solutions of polynomials of degree 3 or higher. There are exact solutions for degree 3 and 4, but both of those involve intermediate complex values that where algebraically the complex portions happen to cancel out in cases that the eigenvalues should be real-valued.
However, when you generate code, you are not using the exact same eigenvalue code as is used by regular MATLAB: regular MATLAB calls upon high-performance MKL (Math Kernel Library) or LAPACK external libraries, And because the two cases use different code, you can get slightly different rounding, leading to the complex parts not exactly balancing. Those last few bits of difference can then get multiplied by large coefficients, so the overall differences can end up large.
Even if the exact same code were being used, MKL and LAPACK are compiled by vendors for high performance, and if you do not use exactly the same compiler flags, you could get differences in outcomes.
So... try taking real(V) and real(D) (but print max(abs(imag(V))) and max(abs(imag(D))) to see how much you are throwing away.) .
PIYUSH SWAMI
PIYUSH SWAMI 2021 年 9 月 17 日
編集済み: Walter Roberson 2021 年 9 月 18 日
Ok, thanks for the explanation :)
Based on your advise, I changed the code to this:
% Orthogonalize weight matrix
[V, D] = eig(state.icaweights * state.icaweights');
% Original V, D
Voriginal = V;
Doriginal = D;
% Real V, D
Vreal = real(V);
Dreal = real(D);
% Thrown V, D
Vthrow = max(abs(imag(Voriginal)));
Dthrow = max(abs(imag(Doriginal)));
state.icaweights = Vreal/sqrt(Dreal)*Vreal' * state.icaweights;
Vthrow and Dthrow returns zero matrix (1 x number of channels). But, when I run the successfully generated MEX file, it is now giving this error:
Error using sqrt (line 13)
Domain error. To compute complex results from real x, use 'sqrt(complex(x))'.
Error in QCAlgo_main>dynamicOrica_modified (line 185)
state.icaweights = Vreal/sqrt(Dreal)*Vreal' * state.icaweights;
Note that the outputs are still non-complex while running the .m file. So when I do as mentioned in the error message, it again shows the original problem as mentioned in the subject :( Can anyone please let me know how to correct this?
Walter Roberson
Walter Roberson 2021 年 9 月 18 日
Compute the whole thing as complex, assigned into a local variable. Extract real() part of that to assign into icaweights .
Simulink appears to be predicting that Dreal is potentially negative. There might be Good Reasons in your case why it cannot be negative for you, but Simulink either does not have sufficient evidence of that or else Simulink just was not able to follow the flow well enough to prove it.

サインインしてコメントする。

製品

質問済み:

2021 年 9 月 13 日

コメント済み:

2021 年 9 月 18 日

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by