VcDevel / Vc

SIMD Vector Classes for C++
BSD 3-Clause "New" or "Revised" License
1.45k stars 151 forks source link

Support for complex numbers? #197

Open twesterhout opened 6 years ago

twesterhout commented 6 years ago

A question: are there any plans to add support for complex numbers?

For example, Vc::simd<std::complex<float>, Vc::simd_abi::sse> would still use __m128 as underlying type, but size() would return 2 rather than 4.

mattkretz commented 6 years ago

I'd like to support simd for user-defined T at some point when the C++ reflection capabilities are good enough. However, what you're really looking for is std::complex<Vc::simd>. It almost works, except for the places where the implementation requires compares to return something boolean. I believe the required changes to std::complex, to make it work all the way, are not very large. Once we now what it takes, I'd like to propose simd support for std::complex inside WG21. If you're interested in helping out, let me know.

twesterhout commented 6 years ago

Not really, std::complex<Vc::simd<T,...>> would give me a SoA layout (or am I missing something?). Nowadays, however, most linear algebra libraries, for example, use AoS layout for complex numbers. So I really want Vc::simd<std::complex<T>,...> to e.g. pass in to functions like https://software.intel.com/sites/landingpage/IntrinsicsGuide/#!=undefined&text=clog&expand=661 without extra shuffling.

P.S. Definitely interested in helping out with the proposal.

mattkretz commented 6 years ago

True, but consider that std::log/exp/sin/... are defined on std::complex and thus would automatically exist for std::complex<simd>. Intel certainly did some heroics to support simd in their instruction set. But I believe that effort is misguided. I.e. one simd object should store only values that are the same scalar variable in the math formula, just filled from different input data. Thus real and imag need to be in different simd objects. So

struct complex {
  simd<float> real, imag;
};

is, in my experience, the best you can get for speeding up your computation. Because that way you won't need any horizontal operations (which effectively reduce you're achievable parallelism by >=2). I understand your argument for compatibility to existing Intel APIs. But let's just force Intel to support complex by blessing it through the C++ standard. ;-)

The only thing complex<simd> doesn't support without some extra help, is the transition between complex and complex<simd> objects. That's the main reason for me to invest into simd. This would also create a struct of simd objects. For a proof of concept you can look at Vc::simdize in Vc 1.3.