Passage of the Difficult real and imaginary

Problem: C ++ 11 has made some changes to complex numbers so that real()

both imag()

can no longer be used or abused like member variables. I have some code that I convert that transmits real()

and imag()

in sincosf()

the link. It looks something like this:

sincosf(/*...*/, &cplx.real(), &cplx.imag());

      

Now it gives error: lvalue required as unary '&' operand

what error was not received until c ++ 11.

My question is: Is there a lightweight inline fix? or do I need to create temporary variables to get the result and then pass them to a complex number via setters?

thank

+3


source to share


3 answers


Just do



cplx = std::polar(1.0f, /*...*/);

      

+2


source


As TC mentions in the comments, the standard allows you reinterpret_cast

std::complex

to your heart's content.

From N3337, §26.4 / 4 [complex.numbers]

If z

is an lvalue expression of type cv std::complex<T>

, then:
- the expression reinterpret_cast<cv T(&)[2]>(z)

must be well formed,
- reinterpret_cast<cv T(&)[2]>(z)[0]

must denote the real part, z

and
- reinterpret_cast<cv T(&)[2]>(z)[1]

denotes the imaginary part z

.
Moreover, if it a

is an expression of type cv std::complex<T>*

, and the expression is a[i]

well defined for an integer expression i

, then:
- reinterpret_cast<cv T*>(a)[2*i]

must denote real part a[i]

and
- reinterpret_cast<cv T*>(a)[2*i + 1]

must denote imaginary part a[i]

.



So, do the following replacement in your code

sincosf(/*...*/, 
        &reinterpret_cast<T*>(&cplx)[0], 
        &reinterpret_cast<T*>(&cplx)[1]);

      

+3


source


Don't argue that time series is still a good option and should be as efficient as what you've done before, given a good optimizing compiler (say gcc -O3

).

See the final build from gcc -O3

here: https://goo.gl/uCPAa9

Using this code:

#include<complex>

std::complex<float> scf1(float x) {
  float r = 0., i = 0.;
  sincosf(x, &r, &i);
  return std::complex<float>(r, i);
}

void scf2(std::complex<float>& cmp, float x) {
  float r = 0., i = 0.;
  sincosf(x, &r, &i);
  cmp.real(r);
  cmp.imag(i);
}

void scf3(std::complex<float>& cmp, float x) {
  float r = 0., i = 0.;
  sincosf(x, &cmp.real(), &cmp.imag());
}

      

Where is scf2

equivalent to your statement, you can see a very similar assembly in three cases.

scf1(float):
    subq    $24, %rsp
    leaq    8(%rsp), %rsi
    leaq    12(%rsp), %rdi
    call    sincosf
    movss   12(%rsp), %xmm0
    movss   %xmm0, (%rsp)
    movss   8(%rsp), %xmm0
    movss   %xmm0, 4(%rsp)
    movq    (%rsp), %xmm0
    addq    $24, %rsp
    ret
scf2(std::complex<float>&, float):
    pushq   %rbx
    movq    %rdi, %rbx
    subq    $16, %rsp
    leaq    8(%rsp), %rsi
    leaq    12(%rsp), %rdi
    call    sincosf
    movss   12(%rsp), %xmm0
    movss   %xmm0, (%rbx)
    movss   8(%rsp), %xmm0
    movss   %xmm0, 4(%rbx)
    addq    $16, %rsp
    popq    %rbx
    ret
scf3(std::complex<float>&, float):
    pushq   %rbx
    movq    %rdi, %rbx
    subq    $16, %rsp
    leaq    8(%rsp), %rsi
    leaq    12(%rsp), %rdi
    call    sincosf
    movss   12(%rsp), %xmm0
    movss   %xmm0, (%rbx)
    movss   8(%rsp), %xmm0
    movss   %xmm0, 4(%rbx)
    addq    $16, %rsp
    popq    %rbx
    ret

      

0


source







All Articles