diff --git a/Eigen/src/Core/arch/CUDA/Complex.h b/Eigen/src/Core/arch/CUDA/Complex.h index f3cc591a8..425e6c2b5 100644 --- a/Eigen/src/Core/arch/CUDA/Complex.h +++ b/Eigen/src/Core/arch/CUDA/Complex.h @@ -11,13 +11,24 @@ #ifndef EIGEN_COMPLEX_CUDA_H #define EIGEN_COMPLEX_CUDA_H -// clang-format off // Many std::complex methods such as operator+, operator-, operator* and // operator/ are not constexpr. Due to this, GCC and older versions of clang do // not treat them as device functions and thus Eigen functors making use of // these operators fail to compile. Here, we manually specialize these // operators and functors for complex types when building for CUDA to enable // their use on-device. +// +// NOTES: +// - Compound assignment operators +=,-=,*=,/=(Scalar) will not work on device, +// since they are already specialized in the standard. Using them will result +// in silent kernel failures. +// - Compiling with MSVC and using +=,-=,*=,/=(std::complex) will lead +// to duplicate definition errors, since these are already specialized in +// Visual Studio's header (contrary to the standard). This is +// preferable to removing such definitions, which will lead to silent kernel +// failures. +// - Compiling with ICC requires defining _USE_COMPLEX_SPECIALIZATION_ prior +// to the first inclusion of . #if defined(EIGEN_CUDACC) && defined(EIGEN_GPU_COMPILE_PHASE) diff --git a/test/gpu_basic.cu b/test/gpu_basic.cu index 4298da3bb..e424a93c9 100644 --- a/test/gpu_basic.cu +++ b/test/gpu_basic.cu @@ -138,10 +138,12 @@ struct complex_operators { out[out_idx++] = a / numext::real(b); out[out_idx++] = numext::real(a) / b; +#if !defined(EIGEN_COMP_MSVC) out[out_idx] = a; out[out_idx++] += b; out[out_idx] = a; out[out_idx++] -= b; out[out_idx] = a; out[out_idx++] *= b; out[out_idx] = a; out[out_idx++] /= b; +#endif const ComplexType true_value = ComplexType(ValueType(1), ValueType(0)); const ComplexType false_value = ComplexType(ValueType(0), ValueType(0)); @@ -188,6 +190,7 @@ struct complex_operators { res.segment(block_idx, size) = x1.real().array() / x2.array(); block_idx += size; +#if !defined(EIGEN_COMP_MSVC) res.segment(block_idx, size) = x1; res.segment(block_idx, size) += x2; block_idx += size; res.segment(block_idx, size) = x1; res.segment(block_idx, size) -= x2; @@ -196,6 +199,7 @@ struct complex_operators { block_idx += size; res.segment(block_idx, size) = x1; res.segment(block_idx, size).array() /= x2.array(); block_idx += size; +#endif const T true_vector = T::Constant(true_value); const T false_vector = T::Constant(false_value);