From: Steinar H. Gunderson Date: Wed, 12 Mar 2014 00:24:39 +0000 (+0100) Subject: Add more unit tests for fp16. X-Git-Tag: 1.0~14 X-Git-Url: https://git.sesse.net/?p=movit;a=commitdiff_plain;h=4b2ecf9112a34baf2b41aeb4dffeaa698bb9f79a Add more unit tests for fp16. This tests a few edge cases that are not adequately covered by the random fp32 tests; in particular, the round-to-even logic had no test coverage, which is bad. --- diff --git a/fp16_test.cpp b/fp16_test.cpp index d5d7fc0..3deb74b 100644 --- a/fp16_test.cpp +++ b/fp16_test.cpp @@ -16,9 +16,19 @@ TEST(FP16Test, Simple) { EXPECT_DOUBLE_EQ(0.333251953125, fp16_to_fp64(0x3555)); } -TEST(FP16Test, NaN) { - EXPECT_EQ(0xfe00, fp64_to_fp16(0.0 / 0.0)); - EXPECT_TRUE(isnan(fp16_to_fp64(0xfe00))); +TEST(FP16Test, RoundToNearestEven) { + ASSERT_DOUBLE_EQ(1.0, fp16_to_fp64(0x3c00)); + + double x0 = fp16_to_fp64(0x3c00); + double x1 = fp16_to_fp64(0x3c01); + double x2 = fp16_to_fp64(0x3c02); + double x3 = fp16_to_fp64(0x3c03); + double x4 = fp16_to_fp64(0x3c04); + + EXPECT_EQ(0x3c00, fp64_to_fp16(0.5 * (x0 + x1))); + EXPECT_EQ(0x3c02, fp64_to_fp16(0.5 * (x1 + x2))); + EXPECT_EQ(0x3c02, fp64_to_fp16(0.5 * (x2 + x3))); + EXPECT_EQ(0x3c04, fp64_to_fp16(0.5 * (x3 + x4))); } union fp64 { @@ -30,6 +40,44 @@ union fp32 { unsigned int u; }; +TEST(FP16Test, NaN) { + EXPECT_EQ(0xfe00, fp64_to_fp16(0.0 / 0.0)); + EXPECT_TRUE(isnan(fp16_to_fp64(0xfe00))); + + fp64 borderline_inf; + borderline_inf.ll = 0x7ff0000000000000ull; + fp64 borderline_nan; + borderline_nan.ll = 0x7ff0000000000001ull; + + ASSERT_FALSE(isfinite(borderline_inf.f)); + ASSERT_FALSE(isnan(borderline_inf.f)); + + ASSERT_FALSE(isfinite(borderline_nan.f)); + ASSERT_TRUE(isnan(borderline_nan.f)); + + double borderline_inf_roundtrip = fp16_to_fp64(fp64_to_fp16(borderline_inf.f)); + double borderline_nan_roundtrip = fp16_to_fp64(fp64_to_fp16(borderline_nan.f)); + + EXPECT_FALSE(isfinite(borderline_inf_roundtrip)); + EXPECT_FALSE(isnan(borderline_inf_roundtrip)); + + EXPECT_FALSE(isfinite(borderline_nan_roundtrip)); + EXPECT_TRUE(isnan(borderline_nan_roundtrip)); +} + +TEST(FP16Test, Denormals) { + const double smallest_fp16_denormal = 5.9604644775390625e-08; + EXPECT_EQ(0x0001, fp64_to_fp16(smallest_fp16_denormal)); + EXPECT_EQ(0x0000, fp64_to_fp16(0.5 * smallest_fp16_denormal)); // Round-to-even. + EXPECT_EQ(0x0001, fp64_to_fp16(0.51 * smallest_fp16_denormal)); + EXPECT_EQ(0x0002, fp64_to_fp16(1.5 * smallest_fp16_denormal)); + + const double smallest_fp16_non_denormal = 6.103515625e-05; + EXPECT_EQ(0x0400, fp64_to_fp16(smallest_fp16_non_denormal)); + EXPECT_EQ(0x0400, fp64_to_fp16(smallest_fp16_non_denormal - 0.5 * smallest_fp16_denormal)); // Round-to-even. + EXPECT_EQ(0x03ff, fp64_to_fp16(smallest_fp16_non_denormal - smallest_fp16_denormal)); +} + // Randomly test a large number of fp64 -> fp32 conversions, comparing // against the FPU. TEST(FP16Test, FP32ReferenceDownconvert) {