Correct pnegate for floating-point zero.

This commit is contained in:
Antonio Sánchez 2022-11-15 18:07:23 +00:00
parent 5eacb9e117
commit 8588d8c74b
3 changed files with 21 additions and 7 deletions

View File

@ -544,11 +544,13 @@ template<> EIGEN_STRONG_INLINE Packet8i psub<Packet8i>(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)
{

View File

@ -346,11 +346,13 @@ EIGEN_STRONG_INLINE Packet16i psub<Packet16i>(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) {

View File

@ -790,9 +790,19 @@ void packetmath_real() {
const int PacketSize = internal::unpacket_traits<Packet>::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<PacketTraits::HasNegate,Packet> h;
data1[0] = Scalar{-0};
h.store(data2, internal::pnegate(h.load(data1)));
typedef typename internal::make_unsigned<typename internal::make_integer<Scalar>::type>::type Bits;
Bits bits = numext::bit_cast<Bits>(data2[0]);
VERIFY_IS_EQUAL(bits, static_cast<Bits>(Bits(1)<<(sizeof(Scalar)*CHAR_BIT - 1)));
}
for (int i = 0; i < size; ++i) {
data1[i] = Scalar(internal::random<double>(0, 1) * std::pow(10., internal::random<double>(-6, 6)));