From 4cb563a01e0619ea1798c7927f1909755ead2dd8 Mon Sep 17 00:00:00 2001 From: Antonio Sanchez Date: Mon, 12 Oct 2020 12:24:08 +0100 Subject: Fix ldexp implementations. The previous implementations produced garbage values if the exponent did not fit within the exponent bits. See #2131 for a complete discussion, and !375 for other possible implementations. Here we implement the 4-factor version. See `pldexp_impl` in `GenericPacketMathFunctions.h` for a full description. The SSE `pcmp*` methods were moved down since `pcmp_le` requires `por`. Left as a "TODO" is to delegate to a faster version if we know the exponent does fit within the exponent bits. Fixes #2131. --- test/packetmath.cpp | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'test/packetmath.cpp') diff --git a/test/packetmath.cpp b/test/packetmath.cpp index b7562e6a1..c388f3a31 100644 --- a/test/packetmath.cpp +++ b/test/packetmath.cpp @@ -573,10 +573,41 @@ void packetmath_real() { data2[i] = Scalar(internal::random(-1, 1)); } for (int i = 0; i < PacketSize; ++i) { - data1[i+PacketSize] = Scalar(internal::random(0, 4)); - data2[i+PacketSize] = Scalar(internal::random(0, 4)); + data1[i+PacketSize] = Scalar(internal::random(-4, 4)); + data2[i+PacketSize] = Scalar(internal::random(-4, 4)); } CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + if (PacketTraits::HasExp) { + data1[0] = Scalar(-1); + // underflow to zero + data1[PacketSize] = Scalar(std::numeric_limits::min_exponent-10); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + // overflow to inf + data1[PacketSize] = Scalar(std::numeric_limits::max_exponent+10); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + // NaN stays NaN + data1[0] = NumTraits::quiet_NaN(); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + VERIFY((numext::isnan)(data2[0])); + // inf stays inf + data1[0] = NumTraits::infinity(); + data1[PacketSize] = Scalar(std::numeric_limits::min_exponent-10); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + // zero stays zero + data1[0] = Scalar(0); + data1[PacketSize] = Scalar(std::numeric_limits::max_exponent+10); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + // Small number big exponent. + data1[0] = Scalar(std::ldexp(Scalar(1.0), std::numeric_limits::min_exponent-1)); + data1[PacketSize] = Scalar(-std::numeric_limits::min_exponent + +std::numeric_limits::max_exponent); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + // Big number small exponent. + data1[0] = Scalar(std::ldexp(Scalar(1.0), std::numeric_limits::max_exponent-1)); + data1[PacketSize] = Scalar(+std::numeric_limits::min_exponent + -std::numeric_limits::max_exponent); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + } for (int i = 0; i < size; ++i) { data1[i] = Scalar(internal::random(-1, 1) * std::pow(10., internal::random(-6, 6))); -- cgit v1.2.3