11#ifndef EIGEN_COMPLEX_CLANG_H
12#define EIGEN_COMPLEX_CLANG_H
15#include "../../InternalHeaderCheck.h"
20template <
typename RealScalar,
int N>
21struct complex_packet_wrapper {
22 using RealPacketT = detail::VectorType<RealScalar, 2 * N>;
23 complex_packet_wrapper() =
default;
24 EIGEN_STRONG_INLINE
explicit complex_packet_wrapper(
const RealPacketT& a) : v(a) {}
25 EIGEN_STRONG_INLINE
constexpr std::complex<RealScalar> operator[](Index i)
const {
26 return std::complex<RealScalar>(v[2 * i], v[2 * i + 1]);
32constexpr int kComplexFloatSize = kFloatPacketSize / 2;
33constexpr int kComplexDoubleSize = kDoublePacketSize / 2;
34using PacketXcf = complex_packet_wrapper<float, kComplexFloatSize>;
35using PacketXcd = complex_packet_wrapper<double, kComplexDoubleSize>;
37struct generic_complex_packet_traits : default_packet_traits {
61struct packet_traits<std::complex<float>> : generic_complex_packet_traits {
62 using type = PacketXcf;
63 using half = PacketXcf;
65 size = kComplexFloatSize,
70struct unpacket_traits<PacketXcf> : generic_unpacket_traits {
71 using type = std::complex<float>;
72 using half = PacketXcf;
73 using as_real = PacketXf;
75 size = kComplexFloatSize,
80struct packet_traits<std::complex<double>> : generic_complex_packet_traits {
81 using type = PacketXcd;
82 using half = PacketXcd;
84 size = kComplexDoubleSize,
89struct unpacket_traits<PacketXcd> : generic_unpacket_traits {
90 using type = std::complex<double>;
91 using half = PacketXcd;
92 using as_real = PacketXd;
94 size = kComplexDoubleSize,
99#define EIGEN_CLANG_COMPLEX_LOAD_STORE(PACKET_TYPE) \
101 EIGEN_STRONG_INLINE PACKET_TYPE ploadu<PACKET_TYPE>(const unpacket_traits<PACKET_TYPE>::type* from) { \
102 return PACKET_TYPE(ploadu<typename unpacket_traits<PACKET_TYPE>::as_real>(&numext::real_ref(*from))); \
105 EIGEN_STRONG_INLINE PACKET_TYPE pload<PACKET_TYPE>(const unpacket_traits<PACKET_TYPE>::type* from) { \
106 return PACKET_TYPE(pload<typename unpacket_traits<PACKET_TYPE>::as_real>(&numext::real_ref(*from))); \
109 EIGEN_STRONG_INLINE void pstoreu<typename unpacket_traits<PACKET_TYPE>::type, PACKET_TYPE>( \
110 typename unpacket_traits<PACKET_TYPE>::type * to, const PACKET_TYPE& from) { \
111 pstoreu(&numext::real_ref(*to), from.v); \
114 EIGEN_STRONG_INLINE void pstore<typename unpacket_traits<PACKET_TYPE>::type, PACKET_TYPE>( \
115 typename unpacket_traits<PACKET_TYPE>::type * to, const PACKET_TYPE& from) { \
116 pstore(&numext::real_ref(*to), from.v); \
119EIGEN_CLANG_COMPLEX_LOAD_STORE(PacketXcf);
120EIGEN_CLANG_COMPLEX_LOAD_STORE(PacketXcd);
121#undef EIGEN_CLANG_COMPLEX_LOAD_STORE
127template <
typename ComplexPacket>
128using complex_real_indices = vector_indices<typename ComplexPacket::RealPacketT>;
130template <
typename ComplexPacket, std::size_t... Is>
131EIGEN_STRONG_INLINE ComplexPacket complex_pset1_impl(
const typename unpacket_traits<ComplexPacket>::type& from,
132 std::index_sequence<Is...>) {
133 using RealPacket =
typename ComplexPacket::RealPacketT;
134 using RealScalar = scalar_type_of_vector_t<RealPacket>;
135 const RealScalar re = numext::real(from);
136 const RealScalar im = numext::imag(from);
137 return ComplexPacket(RealPacket{(Is % 2 == 0 ? re : im)...});
142template <
typename ComplexPacket, std::size_t... Is>
143EIGEN_STRONG_INLINE ComplexPacket complex_pconj_impl(
const ComplexPacket& a, std::index_sequence<Is...>) {
144 using RealScalar = scalar_type_of_vector_t<typename ComplexPacket::RealPacketT>;
145 using IntScalar = std::conditional_t<
sizeof(RealScalar) == 4, int32_t, int64_t>;
146 using IntPacket = VectorType<IntScalar,
sizeof...(Is)>;
147 const IntPacket sign_mask = {(Is % 2 == 0 ? IntScalar(0) : (std::numeric_limits<IntScalar>::min)())...};
148 return ComplexPacket(
149 reinterpret_cast<typename ComplexPacket::RealPacketT
>(
reinterpret_cast<IntPacket
>(a.v) ^ sign_mask));
153template <
typename ComplexPacket, std::size_t... Is>
154EIGEN_STRONG_INLINE ComplexPacket complex_pcplxflip_impl(
const ComplexPacket& a, std::index_sequence<Is...>) {
155 return ComplexPacket(__builtin_shufflevector(a.v, a.v, (2 * (Is / 2) + (1 - Is % 2))...));
159template <
typename ComplexPacket, std::size_t... Is>
160EIGEN_STRONG_INLINE ComplexPacket complex_pdupreal_impl(
const ComplexPacket& a, std::index_sequence<Is...>) {
161 return ComplexPacket(__builtin_shufflevector(a.v, a.v, (2 * (Is / 2))...));
165template <
typename ComplexPacket, std::size_t... Is>
166EIGEN_STRONG_INLINE ComplexPacket complex_pdupimag_impl(
const ComplexPacket& a, std::index_sequence<Is...>) {
167 return ComplexPacket(__builtin_shufflevector(a.v, a.v, (2 * (Is / 2) + 1)...));
176template <
typename ComplexPacket, std::size_t... Is>
177EIGEN_STRONG_INLINE ComplexPacket complex_pmul_impl(
const ComplexPacket& x,
const ComplexPacket& y,
178 std::index_sequence<Is...> is) {
179 using RealPacket =
typename ComplexPacket::RealPacketT;
180 const RealPacket x_re = complex_pdupreal_impl(x, is).v;
181 const RealPacket t = complex_pdupimag_impl(x, is).v * complex_pcplxflip_impl(y, is).v;
182 const RealPacket sub = x_re * y.v - t;
183 const RealPacket add = x_re * y.v + t;
184 return ComplexPacket(__builtin_shufflevector(sub, add, (Is % 2 == 0 ? Is :
sizeof...(Is) + Is)...));
189template <std::size_t Repeat,
typename ComplexPacket, std::size_t... Is>
190EIGEN_STRONG_INLINE ComplexPacket complex_loadrepeat_impl(
const typename unpacket_traits<ComplexPacket>::type* from,
191 std::index_sequence<Is...>) {
192 using RealPacket =
typename ComplexPacket::RealPacketT;
193 return ComplexPacket(
194 RealPacket{(Is % 2 == 0 ? numext::real(from[Is / (2 * Repeat)]) : numext::imag(from[Is / (2 * Repeat)]))...});
198template <
typename ComplexPacket, std::size_t... Is>
199EIGEN_STRONG_INLINE ComplexPacket complex_preverse_impl(
const ComplexPacket& a, std::index_sequence<Is...>) {
200 constexpr std::size_t kLastValue =
sizeof...(Is) - 2;
201 return ComplexPacket(__builtin_shufflevector(a.v, a.v, (kLastValue - 2 * (Is / 2) + Is % 2)...));
207#define EIGEN_CLANG_COMPLEX_SET1(PACKET_TYPE) \
209 EIGEN_STRONG_INLINE PACKET_TYPE pset1<PACKET_TYPE>(const unpacket_traits<PACKET_TYPE>::type& from) { \
210 return detail::complex_pset1_impl<PACKET_TYPE>(from, detail::complex_real_indices<PACKET_TYPE>{}); \
213EIGEN_CLANG_COMPLEX_SET1(PacketXcf)
214EIGEN_CLANG_COMPLEX_SET1(PacketXcd)
215#undef EIGEN_CLANG_COMPLEX_SET1
218#define DELEGATE_UNARY_TO_REAL_OP(PACKET_TYPE, OP) \
220 EIGEN_STRONG_INLINE PACKET_TYPE OP<PACKET_TYPE>(const PACKET_TYPE& a) { \
221 return PACKET_TYPE(OP(a.v)); \
224#define EIGEN_CLANG_COMPLEX_UNARY_CWISE_OPS(PACKET_TYPE) \
225 DELEGATE_UNARY_TO_REAL_OP(PACKET_TYPE, pnegate) \
226 DELEGATE_UNARY_TO_REAL_OP(PACKET_TYPE, pzero) \
228 EIGEN_STRONG_INLINE unpacket_traits<PACKET_TYPE>::type pfirst<PACKET_TYPE>(const PACKET_TYPE& a) { \
231 EIGEN_INSTANTIATE_COMPLEX_MATH_FUNCS(PACKET_TYPE)
233EIGEN_CLANG_COMPLEX_UNARY_CWISE_OPS(PacketXcf);
234EIGEN_CLANG_COMPLEX_UNARY_CWISE_OPS(PacketXcd);
236#undef DELEGATE_UNARY_TO_REAL_OP
237#undef EIGEN_CLANG_COMPLEX_UNARY_CWISE_OPS
240#define EIGEN_CLANG_COMPLEX_LANE_OPS(PACKET_TYPE) \
242 EIGEN_STRONG_INLINE PACKET_TYPE pconj<PACKET_TYPE>(const PACKET_TYPE& a) { \
243 return detail::complex_pconj_impl(a, detail::complex_real_indices<PACKET_TYPE>{}); \
246 EIGEN_STRONG_INLINE PACKET_TYPE pcplxflip<PACKET_TYPE>(const PACKET_TYPE& a) { \
247 return detail::complex_pcplxflip_impl(a, detail::complex_real_indices<PACKET_TYPE>{}); \
250 EIGEN_STRONG_INLINE PACKET_TYPE pdupreal<PACKET_TYPE>(const PACKET_TYPE& a) { \
251 return detail::complex_pdupreal_impl(a, detail::complex_real_indices<PACKET_TYPE>{}); \
254 EIGEN_STRONG_INLINE PACKET_TYPE pdupimag<PACKET_TYPE>(const PACKET_TYPE& a) { \
255 return detail::complex_pdupimag_impl(a, detail::complex_real_indices<PACKET_TYPE>{}); \
258EIGEN_CLANG_COMPLEX_LANE_OPS(PacketXcf)
259EIGEN_CLANG_COMPLEX_LANE_OPS(PacketXcd)
260#undef EIGEN_CLANG_COMPLEX_LANE_OPS
263#define EIGEN_CLANG_COMPLEX_LOAD_REPEAT(PACKET_TYPE) \
265 EIGEN_STRONG_INLINE PACKET_TYPE ploaddup<PACKET_TYPE>(const unpacket_traits<PACKET_TYPE>::type* from) { \
266 return detail::complex_loadrepeat_impl<2, PACKET_TYPE>(from, detail::complex_real_indices<PACKET_TYPE>{}); \
269 EIGEN_STRONG_INLINE PACKET_TYPE ploadquad<PACKET_TYPE>(const unpacket_traits<PACKET_TYPE>::type* from) { \
270 return detail::complex_loadrepeat_impl<4, PACKET_TYPE>(from, detail::complex_real_indices<PACKET_TYPE>{}); \
273EIGEN_CLANG_COMPLEX_LOAD_REPEAT(PacketXcf)
274EIGEN_CLANG_COMPLEX_LOAD_REPEAT(PacketXcd)
275#undef EIGEN_CLANG_COMPLEX_LOAD_REPEAT
279EIGEN_STRONG_INLINE PacketXcf preverse<PacketXcf>(
const PacketXcf& a) {
280 return detail::complex_preverse_impl(a, detail::complex_real_indices<PacketXcf>{});
283EIGEN_STRONG_INLINE PacketXcd preverse<PacketXcd>(
const PacketXcd& a) {
284 return detail::complex_preverse_impl(a, detail::complex_real_indices<PacketXcd>{});
288#define DELEGATE_BINARY_TO_REAL_OP(PACKET_TYPE, OP) \
290 EIGEN_STRONG_INLINE PACKET_TYPE OP<PACKET_TYPE>(const PACKET_TYPE& a, const PACKET_TYPE& b) { \
291 return PACKET_TYPE(OP(a.v, b.v)); \
294#define EIGEN_CLANG_COMPLEX_BINARY_CWISE_OPS(PACKET_TYPE) \
295 DELEGATE_BINARY_TO_REAL_OP(PACKET_TYPE, padd) \
296 DELEGATE_BINARY_TO_REAL_OP(PACKET_TYPE, psub) \
297 DELEGATE_BINARY_TO_REAL_OP(PACKET_TYPE, pand) \
298 DELEGATE_BINARY_TO_REAL_OP(PACKET_TYPE, por) \
299 DELEGATE_BINARY_TO_REAL_OP(PACKET_TYPE, pxor) \
300 DELEGATE_BINARY_TO_REAL_OP(PACKET_TYPE, pandnot) \
302 EIGEN_STRONG_INLINE PACKET_TYPE pdiv<PACKET_TYPE>(const PACKET_TYPE& a, const PACKET_TYPE& b) { \
303 return pdiv_complex(a, b); \
306 EIGEN_STRONG_INLINE PACKET_TYPE pcmp_eq<PACKET_TYPE>(const PACKET_TYPE& a, const PACKET_TYPE& b) { \
307 const PACKET_TYPE t = PACKET_TYPE(pcmp_eq(a.v, b.v)); \
308 return PACKET_TYPE(pand(pdupreal(t).v, pdupimag(t).v)); \
311EIGEN_CLANG_COMPLEX_BINARY_CWISE_OPS(PacketXcf);
312EIGEN_CLANG_COMPLEX_BINARY_CWISE_OPS(PacketXcd);
316#define EIGEN_CLANG_COMPLEX_PMUL(PACKET_TYPE) \
318 EIGEN_STRONG_INLINE PACKET_TYPE pmul<PACKET_TYPE>(const PACKET_TYPE& a, const PACKET_TYPE& b) { \
319 return detail::complex_pmul_impl(a, b, detail::complex_real_indices<PACKET_TYPE>{}); \
322EIGEN_CLANG_COMPLEX_PMUL(PacketXcf);
323EIGEN_CLANG_COMPLEX_PMUL(PacketXcd);
325#define EIGEN_CLANG_PACKET_SCATTER_GATHER(PACKET_TYPE) \
327 EIGEN_STRONG_INLINE void pscatter(unpacket_traits<PACKET_TYPE>::type* to, const PACKET_TYPE& from, Index stride) { \
328 constexpr int size = unpacket_traits<PACKET_TYPE>::size; \
329 for (int i = 0; i < size; ++i) { \
330 to[i * stride] = from[i]; \
334 EIGEN_STRONG_INLINE PACKET_TYPE pgather<typename unpacket_traits<PACKET_TYPE>::type, PACKET_TYPE>( \
335 const unpacket_traits<PACKET_TYPE>::type* from, Index stride) { \
336 constexpr int size = unpacket_traits<PACKET_TYPE>::size; \
337 PACKET_TYPE result; \
338 for (int i = 0; i < size; ++i) { \
339 const unpacket_traits<PACKET_TYPE>::type from_i = from[i * stride]; \
340 result.v[2 * i] = numext::real(from_i); \
341 result.v[2 * i + 1] = numext::imag(from_i); \
346EIGEN_CLANG_PACKET_SCATTER_GATHER(PacketXcf);
347EIGEN_CLANG_PACKET_SCATTER_GATHER(PacketXcd);
348#undef EIGEN_CLANG_PACKET_SCATTER_GATHER
350#undef DELEGATE_BINARY_TO_REAL_OP
351#undef EIGEN_CLANG_COMPLEX_BINARY_CWISE_OPS
352#undef EIGEN_CLANG_COMPLEX_PMUL
358EIGEN_STRONG_INLINE PacketXcf pselect<PacketXcf>(
const PacketXcf& mask,
const PacketXcf& a,
const PacketXcf& b) {
359 return PacketXcf(pselect(mask.v, a.v, b.v));
362EIGEN_STRONG_INLINE PacketXcd pselect<PacketXcd>(
const PacketXcd& mask,
const PacketXcd& a,
const PacketXcd& b) {
363 return PacketXcd(pselect(mask.v, a.v, b.v));
372EIGEN_ALWAYS_INLINE
void zip_in_place<PacketXcf>(PacketXcf& p1, PacketXcf& p2) {
373 zip_in_place_impl<2>(p1.v, p2.v, complex_real_indices<PacketXcf>{});
376#if EIGEN_GENERIC_VECTOR_SIZE_BYTES >= 32
379EIGEN_ALWAYS_INLINE
void zip_in_place<PacketXcd>(PacketXcd& p1, PacketXcd& p2) {
380 zip_in_place_impl<2>(p1.v, p2.v, complex_real_indices<PacketXcd>{});
388EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void ptranspose(PacketBlock<PacketXcf, 2>& kernel) {
389 detail::ptranspose_impl(kernel);
391#if EIGEN_GENERIC_VECTOR_SIZE_BYTES >= 32
392EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void ptranspose(PacketBlock<PacketXcf, 4>& kernel) {
393 detail::ptranspose_impl(kernel);
396#if EIGEN_GENERIC_VECTOR_SIZE_BYTES >= 64
397EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void ptranspose(PacketBlock<PacketXcf, 8>& kernel) {
398 detail::ptranspose_impl(kernel);
403#if EIGEN_GENERIC_VECTOR_SIZE_BYTES >= 32
404EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void ptranspose(PacketBlock<PacketXcd, 2>& kernel) {
405 detail::ptranspose_impl(kernel);
408#if EIGEN_GENERIC_VECTOR_SIZE_BYTES >= 64
409EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void ptranspose(PacketBlock<PacketXcd, 4>& kernel) {
410 detail::ptranspose_impl(kernel);
414EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(PacketXcf, PacketXf)
415EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(PacketXcd, PacketXd)