From 92e3387f7c63e494ad6837e80a33e60acaf7e3bf Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sun, 28 Aug 2011 21:07:09 +0000 Subject: [PATCH] test: augment the half precision numbers testsuite. --- test/half.cpp | 172 +++++++++++++++++++++++++++++++++++++++------ test/lol-bench.cpp | 15 +++- 2 files changed, 163 insertions(+), 24 deletions(-) diff --git a/test/half.cpp b/test/half.cpp index e921fd22..739f67cb 100644 --- a/test/half.cpp +++ b/test/half.cpp @@ -28,7 +28,13 @@ class HalfTest : public CppUnit::TestCase CPPUNIT_TEST(test_half_makebits); CPPUNIT_TEST(test_half_makeslow); CPPUNIT_TEST(test_half_makefast); + CPPUNIT_TEST(test_half_isnan); + CPPUNIT_TEST(test_half_isinf); + CPPUNIT_TEST(test_half_isfinite); + CPPUNIT_TEST(test_half_isnormal); + CPPUNIT_TEST(test_half_classify); CPPUNIT_TEST(test_half_to_float); + CPPUNIT_TEST(test_half_to_int); CPPUNIT_TEST_SUITE_END(); public: @@ -52,53 +58,175 @@ public: void test_half_makeslow() { - for (size_t i = 0; i < 8; i++) + for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++) { - half a = half::makeslow(array1[i].f); - uint16_t b = array1[i].x; + half a = half::makeslow(pairs[i].f); + uint16_t b = pairs[i].x; CPPUNIT_ASSERT_EQUAL(a.bits(), b); } } void test_half_makefast() { - for (size_t i = 0; i < 8; i++) + for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++) { - half a = half::makefast(array1[i].f); - uint16_t b = array1[i].x; + half a = half::makefast(pairs[i].f); + uint16_t b = pairs[i].x; CPPUNIT_ASSERT_EQUAL(a.bits(), b); } } + void test_half_isnan() + { + CPPUNIT_ASSERT(half::makebits(0x7c01).isnan()); + CPPUNIT_ASSERT(half::makebits(0xfc01).isnan()); + CPPUNIT_ASSERT(half::makebits(0x7e00).isnan()); + CPPUNIT_ASSERT(half::makebits(0xfe00).isnan()); + + CPPUNIT_ASSERT(!half::makebits(0x7c00).isnan()); + CPPUNIT_ASSERT(!half::makebits(0xfc00).isnan()); + + CPPUNIT_ASSERT(!half(0.0f).isnan()); + CPPUNIT_ASSERT(!half(-0.0f).isnan()); + CPPUNIT_ASSERT(!half(2.0f).isnan()); + CPPUNIT_ASSERT(!half(-2.0f).isnan()); + } + + void test_half_isinf() + { + CPPUNIT_ASSERT(half(65536.0f).isinf()); + CPPUNIT_ASSERT(half(-65536.0f).isinf()); + + CPPUNIT_ASSERT(!half(0.0f).isinf()); + CPPUNIT_ASSERT(!half(-0.0f).isinf()); + CPPUNIT_ASSERT(!half(65535.0f).isinf()); + CPPUNIT_ASSERT(!half(-65535.0f).isinf()); + + CPPUNIT_ASSERT(half::makebits(0x7c00).isinf()); + CPPUNIT_ASSERT(half::makebits(0xfc00).isinf()); + + CPPUNIT_ASSERT(!half::makebits(0x7e00).isinf()); + CPPUNIT_ASSERT(!half::makebits(0xfe00).isinf()); + } + + void test_half_isfinite() + { + CPPUNIT_ASSERT(half(0.0f).isfinite()); + CPPUNIT_ASSERT(half(-0.0f).isfinite()); + CPPUNIT_ASSERT(half(65535.0f).isfinite()); + CPPUNIT_ASSERT(half(-65535.0f).isfinite()); + + CPPUNIT_ASSERT(!half(65536.0f).isfinite()); + CPPUNIT_ASSERT(!half(-65536.0f).isfinite()); + + CPPUNIT_ASSERT(!half::makebits(0x7c00).isfinite()); + CPPUNIT_ASSERT(!half::makebits(0xfc00).isfinite()); + + CPPUNIT_ASSERT(!half::makebits(0x7e00).isfinite()); + CPPUNIT_ASSERT(!half::makebits(0xfe00).isfinite()); + } + + void test_half_isnormal() + { + CPPUNIT_ASSERT(half(0.0f).isnormal()); + CPPUNIT_ASSERT(half(-0.0f).isnormal()); + CPPUNIT_ASSERT(half(65535.0f).isnormal()); + CPPUNIT_ASSERT(half(-65535.0f).isnormal()); + + CPPUNIT_ASSERT(!half(65536.0f).isnormal()); + CPPUNIT_ASSERT(!half(-65536.0f).isnormal()); + + CPPUNIT_ASSERT(!half::makebits(0x7c00).isnormal()); + CPPUNIT_ASSERT(!half::makebits(0xfc00).isnormal()); + + CPPUNIT_ASSERT(!half::makebits(0x7e00).isnormal()); + CPPUNIT_ASSERT(!half::makebits(0xfe00).isnormal()); + } + + void test_half_classify() + { + for (uint32_t i = 0; i < 0x10000; i++) + { + half h = half::makebits(i); + if (h.isnan()) + { + CPPUNIT_ASSERT(!h.isinf()); + CPPUNIT_ASSERT(!h.isnormal()); + CPPUNIT_ASSERT(!h.isfinite()); + } + else if (h.isinf()) + { + CPPUNIT_ASSERT(!h.isnormal()); + CPPUNIT_ASSERT(!h.isfinite()); + } + else + { + CPPUNIT_ASSERT(h.isfinite()); + } + } + } + void test_half_to_float() { -#if 0 - for (unsigned int i = 0; i < 0x10000; i++) + for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++) { - half a = half::makebits(i); - half b = half::makefast((float)a); - //CPPUNIT_ASSERT_EQUAL(a.bits(), b.bits()); + float a = (float)half::makebits(pairs[i].x); + float b = pairs[i].f; + CPPUNIT_ASSERT_EQUAL(a, b); + } + + for (uint32_t i = 0; i < 0x10000; i++) + { + half h = half::makebits(i); + float f = (float)h; + half g = (half)f; + if (h.isnan()) + { + CPPUNIT_ASSERT(isnan(f)); + CPPUNIT_ASSERT(g.isnan()); + } + else + { + CPPUNIT_ASSERT(!isnan(f)); + CPPUNIT_ASSERT_EQUAL(g.bits(), h.bits()); + } } } -#endif + + void test_half_to_int() + { + CPPUNIT_ASSERT_EQUAL((int)(half)(0.0f), 0); + CPPUNIT_ASSERT_EQUAL((int)(half)(-0.0f), 0); + CPPUNIT_ASSERT_EQUAL((int)(half)(0.9f), 0); + CPPUNIT_ASSERT_EQUAL((int)(half)(-0.9f), 0); + CPPUNIT_ASSERT_EQUAL((int)(half)(1.0f), 1); + CPPUNIT_ASSERT_EQUAL((int)(half)(-1.0f), -1); + CPPUNIT_ASSERT_EQUAL((int)(half)(1.9f), 1); + CPPUNIT_ASSERT_EQUAL((int)(half)(-1.9f), -1); + CPPUNIT_ASSERT_EQUAL((int)(half)(65504.0f), 65504); + CPPUNIT_ASSERT_EQUAL((int)(half)(-65504.0f), -65504); } private: struct TestPair { float f; uint16_t x; }; - static TestPair const array1[]; + static TestPair const pairs[11]; }; -HalfTest::TestPair const HalfTest::array1[] = +HalfTest::TestPair const HalfTest::pairs[] = { - { 0.0f, 0x0000 }, - { -0.0f, 0x8000 }, - { 1.0f, 0x3c00 }, - { -1.0f, 0xbc00 }, - { 2.0f, 0x4000 }, - { 0.5f, 0x3800 }, - { 0.125f, 0x3000 }, - { 15.9375f, 0x4bf8 }, + /* All these values have exact half representations */ + { 0.0f, 0x0000 }, + { -0.0f, 0x8000 }, /* negative zero */ + { 1.0f, 0x3c00 }, + { -1.0f, 0xbc00 }, + { 2.0f, 0x4000 }, + { 0.5f, 0x3800 }, + { 0.125f, 0x3000 }, + { 15.9375f, 0x4bf8 }, + { 0x1.fp-10, 0x17c0 }, + { 0x1.fp-14, 0x07c0 }, /* denormal */ + { 0x1.fp-15, 0x03e0 }, /* denormal */ }; CPPUNIT_TEST_SUITE_REGISTRATION(HalfTest); diff --git a/test/lol-bench.cpp b/test/lol-bench.cpp index 6ee7036a..e7e10fbc 100644 --- a/test/lol-bench.cpp +++ b/test/lol-bench.cpp @@ -22,8 +22,19 @@ int main(int argc, char **argv) { Timer timer; + float ftotal = 0.0f; + for (uint32_t i = 0; i < 0xffffffffu; i += 7) + { + union { float f; uint32_t x; } u; + u.x = i; + + float h = (float)half::makefast(u.f); + ftotal += h; + } + Log::Info("time for makeslow: %f (hash %f)\n", timer.GetMs(), ftotal); + uint16_t total = 0; - for (uint32_t i = 0; i < 0xffffffffu; i++) + for (uint32_t i = 0; i < 0xffffffffu; i += 7) { union { float f; uint32_t x; } u; u.x = i; @@ -33,7 +44,7 @@ int main(int argc, char **argv) } Log::Info("time for makeslow: %f (hash %04x)\n", timer.GetMs(), total); - for (uint32_t i = 0; i < 0xffffffffu; i++) + for (uint32_t i = 0; i < 0xffffffffu; i += 7) { union { float f; uint32_t x; } u; u.x = i;