Fix Half NaN definition and test.

The `half_float` test was failing with `-mcpu=cortex-a55` (native `__fp16`) due
to a bad NaN bit-pattern comparison (in the case of casting a float to `__fp16`,
the signaling `NaN` is quieted). There was also an inconsistency between
`numeric_limits<half>::quiet_NaN()` and `NumTraits::quiet_NaN()`.  Here we
correct the inconsistency and compare NaNs according to the IEEE 754
definition.

Also modified the `bfloat16_float` test to match.

Tested with `cortex-a53` and `cortex-a55`.
This commit is contained in:
Antonio Sanchez
2020-11-23 14:13:59 -08:00
parent 4cf01d2cf5
commit 38abf2be42
3 changed files with 35 additions and 11 deletions

View File

@@ -274,9 +274,23 @@ void test_numtraits()
VERIFY_IS_EQUAL(
numext::bit_cast<numext::uint16_t>(std::numeric_limits<bfloat16>::infinity()),
numext::bit_cast<numext::uint16_t>(bfloat16(std::numeric_limits<float>::infinity())) );
VERIFY_IS_EQUAL(
numext::bit_cast<numext::uint16_t>(std::numeric_limits<bfloat16>::quiet_NaN()),
numext::bit_cast<numext::uint16_t>(bfloat16(std::numeric_limits<float>::quiet_NaN())) );
// There is no guarantee that casting a 32-bit NaN to bfloat16 has a precise
// bit pattern. We test that it is in fact a NaN, then test the signaling
// bit (msb of significand is 1 for quiet, 0 for signaling).
const numext::uint16_t BFLOAT16_QUIET_BIT = 0x0040;
VERIFY(
(numext::isnan)(std::numeric_limits<bfloat16>::quiet_NaN())
&& (numext::isnan)(bfloat16(std::numeric_limits<float>::quiet_NaN()))
&& ((numext::bit_cast<numext::uint16_t>(std::numeric_limits<bfloat16>::quiet_NaN()) & BFLOAT16_QUIET_BIT) > 0)
&& ((numext::bit_cast<numext::uint16_t>(bfloat16(std::numeric_limits<float>::quiet_NaN())) & BFLOAT16_QUIET_BIT) > 0) );
// After a cast to bfloat16, a signaling NaN may become non-signaling. Thus,
// we check that both are NaN, and that only the `numeric_limits` version is
// signaling.
VERIFY(
(numext::isnan)(std::numeric_limits<bfloat16>::signaling_NaN())
&& (numext::isnan)(bfloat16(std::numeric_limits<float>::signaling_NaN()))
&& ((numext::bit_cast<numext::uint16_t>(std::numeric_limits<bfloat16>::signaling_NaN()) & BFLOAT16_QUIET_BIT) == 0) );
VERIFY( (std::numeric_limits<bfloat16>::min)() > bfloat16(0.f) );
VERIFY( (std::numeric_limits<bfloat16>::denorm_min)() > bfloat16(0.f) );
VERIFY_IS_EQUAL( (std::numeric_limits<bfloat16>::denorm_min)()/bfloat16(2), bfloat16(0.f) );