diff --git a/Eigen/src/Core/arch/AVX/PacketMath.h b/Eigen/src/Core/arch/AVX/PacketMath.h index 33a4dee8b..1b104cfbc 100644 --- a/Eigen/src/Core/arch/AVX/PacketMath.h +++ b/Eigen/src/Core/arch/AVX/PacketMath.h @@ -544,11 +544,13 @@ template<> EIGEN_STRONG_INLINE Packet8i psub(const Packet8i& a, const template<> EIGEN_STRONG_INLINE Packet8f pnegate(const Packet8f& a) { - return _mm256_sub_ps(_mm256_set1_ps(0.0),a); + const Packet8f mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000)); + return _mm256_xor_ps(a, mask); } template<> EIGEN_STRONG_INLINE Packet4d pnegate(const Packet4d& a) { - return _mm256_sub_pd(_mm256_set1_pd(0.0),a); + const Packet4d mask = _mm256_castsi256_pd(_mm256_set1_epi64x(0x8000000000000000ULL)); + return _mm256_xor_pd(a, mask); } template<> EIGEN_STRONG_INLINE Packet8i pnegate(const Packet8i& a) { diff --git a/Eigen/src/Core/arch/AVX512/PacketMath.h b/Eigen/src/Core/arch/AVX512/PacketMath.h index c210f2f6b..159ae3e0f 100644 --- a/Eigen/src/Core/arch/AVX512/PacketMath.h +++ b/Eigen/src/Core/arch/AVX512/PacketMath.h @@ -346,11 +346,13 @@ EIGEN_STRONG_INLINE Packet16i psub(const Packet16i& a, template <> EIGEN_STRONG_INLINE Packet16f pnegate(const Packet16f& a) { - return _mm512_sub_ps(_mm512_set1_ps(0.0), a); + const __m512i mask = _mm512_set1_epi32(0x80000000); + return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a), mask)); } template <> EIGEN_STRONG_INLINE Packet8d pnegate(const Packet8d& a) { - return _mm512_sub_pd(_mm512_set1_pd(0.0), a); + const __m512i mask = _mm512_set1_epi64(0x8000000000000000ULL); + return _mm512_castsi512_pd(_mm512_xor_epi64(_mm512_castpd_si512(a), mask)); } template <> EIGEN_STRONG_INLINE Packet16i pnegate(const Packet16i& a) { diff --git a/test/packetmath.cpp b/test/packetmath.cpp index d7c7c9cad..f0829858b 100644 --- a/test/packetmath.cpp +++ b/test/packetmath.cpp @@ -790,9 +790,19 @@ void packetmath_real() { const int PacketSize = internal::unpacket_traits::size; const int size = PacketSize * 4; - EIGEN_ALIGN_MAX Scalar data1[PacketSize * 4]; - EIGEN_ALIGN_MAX Scalar data2[PacketSize * 4]; - EIGEN_ALIGN_MAX Scalar ref[PacketSize * 4]; + EIGEN_ALIGN_MAX Scalar data1[PacketSize * 4] = {}; + EIGEN_ALIGN_MAX Scalar data2[PacketSize * 4] = {}; + EIGEN_ALIGN_MAX Scalar ref[PacketSize * 4] = {}; + + // Negate with -0. + if (PacketTraits::HasNegate) { + test::packet_helper h; + data1[0] = Scalar{-0}; + h.store(data2, internal::pnegate(h.load(data1))); + typedef typename internal::make_unsigned::type>::type Bits; + Bits bits = numext::bit_cast(data2[0]); + VERIFY_IS_EQUAL(bits, static_cast(Bits(1)<<(sizeof(Scalar)*CHAR_BIT - 1))); + } for (int i = 0; i < size; ++i) { data1[i] = Scalar(internal::random(0, 1) * std::pow(10., internal::random(-6, 6)));