This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[Intrinsics] _complex_conjugate_mpysp specification ?

Hello,

My customer would like to confirm the spec of _complex_conjugate_mpysp intinsics function for C66x core.

Please take a look at www.ti.com/.../spru187v.pdf

The following is a prototype for _complex_conjugate_mpysp. 

double _complex_conjugate_mpysp (double src1, double src2);

I believe the data type of arguments and return value should be __float2_t, rather than double. Correct, right ?
Also, which argument should be regarded as 'conjugate' ? I could not find any documentations about this.

Best Regards,
Naoki Kawada

  • Naoki Kawada said:
    I believe the data type of arguments and return value should be __float2_t, rather than double. Correct, right ?

    That's correct.  SDSCM00045110 is filed in the SDOWP system to get this changed.  It was not marked as externally visible.  I changed it.  In a few hours, you will be able to see it at the SDOWP link below in my signature.  Since __float2_t is typedef'd to double, this change has no effect on compiled code.  It only avoids the confusion you experienced here.

    Naoki Kawada said:
    Also, which argument should be regarded as 'conjugate' ? I could not find any documentations about this.

    I suggest you code a small example which uses the intrinsic, and see the code the compiler generates for it.  Use the build option --src_interlist to have the compiler keep the .asm file, and add comments which make it easier to understand the output.  Then look up the instructions used in the C66x CPU manual.  

    Another way to understand this ... Install the C66x DSPLIB library and read the source code which use the _complex_conjugate_mpysp intrinsic.  These files in the library use the intrinsic ...

    ./packages/ti/dsplib/src/DSPF_sp_cholesky_cmplx/c66/DSPF_sp_cholesky_cmplx.c
    ./packages/ti/dsplib/src/DSPF_sp_qrd_cmplx/c66/DSPF_sp_qrd_cmplx.c
    ./packages/ti/dsplib/src/DSPF_sp_svd_cmplx/c66/DSPF_sp_svd_cmplx.c
    

    Thanks and regards,

    -George

  • Hello George,

    Thanks for your help.
    I coded small example with _complex_mpysp and _complex_conjugate_mpysp.

    Here is a sample code for complex multiply by using _complex_mpysp and feeding arguments are 'conjugate' each other.

    a_cplx = _ftof2(5.0f, 2.0f);//5+2i
    b_cplx = _ftof2(5.0f, -2.0f);//5-2i
    result = _complex_mpysp(a_cplx,b_cplx);
    y_real = _hif2(result);//real part
    y_img = _lof2(result);//img part

    This formula results in y_real = 29.0 and y_img = 0.0. This is correct behavior, right ?

    Next, here is a sample code for 'conjugate' complex multiply by using _complex_conjugate_mpysp and feeding values are 'conjugate' each other.

    a_cplx = _ftof2(5.0f, 2.0f);//5+2i
    b_cplx = _ftof2(5.0f, -2.0f);//5-2i
    result = _complex_conjugate_mpysp(a_cplx,b_cplx);
    y_conjugate_real = _hif2(result);//real part
    y_conjugate_img = _lof2(result);//img part

    My assumption was the result of y_conjugate_real = 29.0 and y_conjugate_img = 0.0.
    But in fact, this formula leads to the result of y_conjugate_real = 21.0 and y_conjugate_img = -20.0.
    I confirmed the actual assembly code for _complex_conjugate_mpysp by using  --src_interlist and I found CMPSP and DSUBSP was being used.
    These assembly code looks working with the following scheme:

     (a + bi)(c+di) = (ac+bd) + (ad-bc)i

    Because I feed a=5.0, b=2.0, c=5.0, d=-2.0, the above formula results in 21.0 - 20.0i. So, the formula itself looks correct. 
    What I don't really understand is the usage of _complex_conjugate_mpysp. In other words, what value should be given to a_cplx and b_cplx to use _complex_conjugate_mpysp ? Can you answer to this ?

    FYI, If I tried the following values as arguments for _complex_conjugate_mpysp, I got the same result with _complex_mpysp.

    a_cplx = _ftof2(5.0f, 2.0f);//5+2i
    b_cplx = _ftof2(5.0f, 2.0f);//5+2i ==> regarded as 5-2i ???
    result = _complex_conjugate_mpysp(a_cplx,b_cplx);
    y_conjugate_real = _hif2(result);//real part
    y_conjugate_img = _lof2(result);//img part

    Now y_conjugate_real = 29.0 and y_conjugate_img = 0.0. 

    Best Regards,
    Naoki Kawada

  • I lack the expertise to help you.  Perhaps this thread will shed some light.  I'll ask for help from one expert.  However, he is out this week, and possibly next week too.

    Thanks and regards,

    -George

  • Here is another thread that may be helpful.

    Thanks and regards,

    -George

  • You should seriously consider writing your code with native C99 complex types.  Although the TI C compiler doesn't completely support C99, recent versions of this compiler fully support complex types:

    #include <complex.h>
    a_cplx = 5 + 2 * I;
    b_cplx = 5 - 2 * I;
    result = a_cplx * conjf(b_cplx);
    y_conjugate_real = crealf(result);
    y_conjugate_img = cimagf(result);

    In regards to your question, I studied how the compiler uses _complex_conjugate_mpysp, and the compiler is treating it as _complex_conjugate_mpysp(a,b) == _complex_mpysp(conj(a), b)); however, I don't know whether that's right or wrong.  We'll probably need to wait for the expert.

  • Hi George and Archaeologist,

    Thanks for your reply. I looked over the suggested posts, but unfortunately, these did not answer to my question.
    Do you have any updates from your expert ?
    _complex_mpysp is intuitive, but _complex_conjugate_mpysp usage is still unclear.
    In fact, I can't understand the purpose of _complex_conjugate_mpysp also...

    Best Regards,
    Naoki Kawada
  • _complex_conjugate_mpysp(x,y) is x * conj(y).

    That is, given

       result := _complex_conjugate_mpysp(x,y)

    then

       real(result)  := real(x)*real(y) + real(x)*imag(y)
       imag(result) := imag(x)*real(y) - real(x)*imag(y)

    It's the same as a normal complex multiply (_complex_mpysp) but with the imaginary part of y negated.

    I think this matches what you are seeing.

    -Alan

  • Hello,
    Though I could not provide you with any reliable reading, I do confirm findings of Archaeologist. In my older code I see remarks that _complex_conjugate_mpysp(a,b) == _complex_mpysp(conj(a), b)); as it was reported here. Just keep in mind, which argument is subject to conjugation.
    However, I'd like to draw your attention to another issue. While these modern intrisics assume imaginary part to come in lower part of complex container, DSPLIB functions are written in assumption that lower part is real.
  • Hello Alan and rrlagic,

    Thanks for your interest !
    rrlagic, I read some threads you posted. Thanks for your remark.

    >   real(result)  := real(x)*real(y) + real(x)*imag(y)
    >   imag(result) := imag(x)*real(y) - real(x)*imag(y)

    I think this is not correct. I summarized the formulas for both complex_mypsp and complex_conjugate_mpysp as below:

    1) complex_mypsp

    result = complex_mypsp (x, y), where, x=a+bi and y=c+di
    result(real) := ac-bd
    result(img) := ad+bc

    2) complex_conjugate_mpysp

    result = complex_conjugate_mpysp (x,y). where, x=a+bi and y=c+di
    result(real) := ac+bd
    result(img) := ad-bc

    Also, I confirmed the result of complex_mypsp and complex_conjugate_mpysp by feeding some values to 'a' to 'd', and it looks _complex_conjugate_mpysp(a,b) == _complex_mpysp(a, conj(b))); is incorrect. And as rrlagic suggested, _complex_conjugate_mpysp(a,b) == _complex_mpysp(conj(a), b)); looks correct.

    Can you confirm my understanding is correct ?

    Best Regards,
    Naoki Kawada 

  • Yes, it's _complex_conjugate_mpysp(a,b) == _complex_mpysp(conj(a), b));

    The _complex_mpysp() operation (without conjugate) is CMPYSP followed by DADDSP.

    suppose:

       A5:A4 == (a,b)
       A7:A6 == (c,d)

    CMPYSP A5:A4, A7:A6, A3:A2:A1:A0 gives

       (A3:A2:A1:A0) == (ac,ad,-bd, bc)

    DADD A3:A2, A1,A0, A9:A8 gives

       A9:A8 ==  (ac-bd, ad+bc)  which is (a+bi) * (c+di)

    The _complex_conjugate_mpysp() is CMPYSP followed by DSUBSP.

    DSUB A3:A2, A1,A0, A9:A8 gives

       A9:A8 == (ac+bd, ad-bc), which is (a-bi) * (c+di) == conj(a+bi) * (c+di)

    -Alan

  • Hello Alan,

    Thanks for your clarification. I'll suggest the same to the customer.

    Best Regards,
    Naoki Kawada