diff options
author | Antonio Sanchez <cantonios@google.com> | 2020-10-12 12:24:08 +0100 |
---|---|---|
committer | Rasmus Munk Larsen <rmlarsen@google.com> | 2021-02-10 22:45:41 +0000 |
commit | 4cb563a01e0619ea1798c7927f1909755ead2dd8 (patch) | |
tree | f1a1c213a13ad6320fa86ebb144af777568eeeea /test/packetmath.cpp | |
parent | 7eb07da538ecc1b8937bfb5dac0d071067728397 (diff) |
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<Packet4i>`
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.
Diffstat (limited to 'test/packetmath.cpp')
-rw-r--r-- | test/packetmath.cpp | 35 |
1 files changed, 33 insertions, 2 deletions
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<double>(-1, 1)); } for (int i = 0; i < PacketSize; ++i) { - data1[i+PacketSize] = Scalar(internal::random<int>(0, 4)); - data2[i+PacketSize] = Scalar(internal::random<double>(0, 4)); + data1[i+PacketSize] = Scalar(internal::random<int>(-4, 4)); + data2[i+PacketSize] = Scalar(internal::random<double>(-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<Scalar>::min_exponent-10); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + // overflow to inf + data1[PacketSize] = Scalar(std::numeric_limits<Scalar>::max_exponent+10); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + // NaN stays NaN + data1[0] = NumTraits<Scalar>::quiet_NaN(); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + VERIFY((numext::isnan)(data2[0])); + // inf stays inf + data1[0] = NumTraits<Scalar>::infinity(); + data1[PacketSize] = Scalar(std::numeric_limits<Scalar>::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<Scalar>::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<Scalar>::min_exponent-1)); + data1[PacketSize] = Scalar(-std::numeric_limits<Scalar>::min_exponent + +std::numeric_limits<Scalar>::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<Scalar>::max_exponent-1)); + data1[PacketSize] = Scalar(+std::numeric_limits<Scalar>::min_exponent + -std::numeric_limits<Scalar>::max_exponent); + CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp); + } for (int i = 0; i < size; ++i) { data1[i] = Scalar(internal::random<double>(-1, 1) * std::pow(10., internal::random<double>(-6, 6))); |