From 814a3b00fe6e6d9b52cd95d8a348b2ce632be168 Mon Sep 17 00:00:00 2001 From: Cary Phillips Date: Tue, 7 Sep 2021 12:46:27 -0400 Subject: [PATCH 1/6] Successor/predecessor functions use isnan() and isinf() isnan() and isinf() should more robust across different architectures than testing bit patterns. Also, the unions should use uint32_t/uint64_t since they're guaranteed to be the appropriate size. Signed-off-by: Cary Phillips --- src/Imath/ImathFun.cpp | 10 +++++----- src/ImathTest/testFun.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Imath/ImathFun.cpp b/src/Imath/ImathFun.cpp index da4af128..74799366 100644 --- a/src/Imath/ImathFun.cpp +++ b/src/Imath/ImathFun.cpp @@ -13,11 +13,11 @@ succf (float f) IMATH_NOEXCEPT union { float f; - unsigned int i; + uint32_t i; } u; u.f = f; - if ((u.i & 0x7f800000) == 0x7f800000) + if (isinf(f) || isnan (f)) { // Nan or infinity; don't change value. } @@ -51,11 +51,11 @@ predf (float f) IMATH_NOEXCEPT union { float f; - unsigned int i; + uint32_t i; } u; u.f = f; - if ((u.i & 0x7f800000) == 0x7f800000) + if (isinf(f) || isnan (f)) { // Nan or infinity; don't change value. } @@ -93,7 +93,7 @@ succd (double d) IMATH_NOEXCEPT } u; u.d = d; - if ((u.i & 0x7ff0000000000000LL) == 0x7ff0000000000000LL) + if (isinf(d) || isnan (d)) { // Nan or infinity; don't change value. } diff --git a/src/ImathTest/testFun.cpp b/src/ImathTest/testFun.cpp index 8b04f697..31f965c2 100644 --- a/src/ImathTest/testFun.cpp +++ b/src/ImathTest/testFun.cpp @@ -244,7 +244,7 @@ testFun() testf (7); testf (0.7); - union {float f; int i;} u; + union {float f; uint32_t i;} u; u.i = 0x7f800000; // inf testf (u.f, false); u.i = 0xff800000; // -inf @@ -264,7 +264,7 @@ testFun() testd (7); testd (0.7); - union {double d; Int64 i;} v; + union {double d; uint64_t i;} v; v.i = 0x7ff0000000000000ULL; // inf testd (v.d, false); v.i = 0xfff0000000000000ULL; // -inf From fec07ba4bea34620f75fafc3d9a841f9fa4e4399 Mon Sep 17 00:00:00 2001 From: Cary Phillips Date: Tue, 7 Sep 2021 16:34:48 -0400 Subject: [PATCH 2/6] Add debugging info to testf()/testd() Signed-off-by: Cary Phillips --- src/ImathTest/testFun.cpp | 58 +++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/src/ImathTest/testFun.cpp b/src/ImathTest/testFun.cpp index 31f965c2..64dc06b2 100644 --- a/src/ImathTest/testFun.cpp +++ b/src/ImathTest/testFun.cpp @@ -19,17 +19,12 @@ using namespace std; -#if ULONG_MAX == 18446744073709551615LU -typedef long unsigned int Int64; -#else - typedef long long unsigned int Int64; -#endif - #if __cplusplus < 202002L template static inline To bit_cast (From from) { +#warning "using custom bit_cast" static_assert (sizeof (From) == sizeof (To), "Type sizes do not match"); union { @@ -51,11 +46,17 @@ testf (float f, bool changeExpected = true) float spf = IMATH_INTERNAL_NAMESPACE::succf (IMATH_INTERNAL_NAMESPACE::predf (f)); float psf = IMATH_INTERNAL_NAMESPACE::predf (IMATH_INTERNAL_NAMESPACE::succf (f)); - printf ("f %.9g\n", f); - printf ("sf %.9g\n", sf); - printf ("pf %.9g\n", pf); - printf ("spf %.9g\n", spf); - printf ("psf %.9g\n", psf); + union {float f; uint32_t i;} u; + u.f = f; + printf ("f %.9g %x\n", f, u.i); + u.f = sf; + printf ("sf %.9g %x\n", sf, u.i); + u.f = pf; + printf ("pf %.9g %x\n", pf, u.i); + u.f = spf; + printf ("spf %.9g %x\n", spf, u.i); + u.f = psf; + printf ("psf %.9g %x\n", psf, u.i); fflush (stdout); @@ -67,8 +68,13 @@ testf (float f, bool changeExpected = true) else { // No bit change expected if input was inf or NaN - assert (bit_cast (pf) == bit_cast (f)); - assert (bit_cast (sf) == bit_cast (f)); + uint32_t bc_f = bit_cast (f); + uint32_t bc_pf = bit_cast (pf); + uint32_t bc_sf = bit_cast (sf); + printf ("no change expected: f=%x pf=%x sf=%x\n", bc_f, bc_pf, bc_sf); + + assert (bit_cast (pf) == bit_cast (f)); + assert (bit_cast (sf) == bit_cast (f)); } } @@ -82,11 +88,18 @@ testd (double d, bool changeExpected = true) double spd = IMATH_INTERNAL_NAMESPACE::succd (IMATH_INTERNAL_NAMESPACE::predd (d)); double psd = IMATH_INTERNAL_NAMESPACE::predd (IMATH_INTERNAL_NAMESPACE::succd (d)); - printf ("d %.18lg\n", d); - printf ("sd %.18lg\n", sd); - printf ("pd %.18lg\n", pd); - printf ("spd %.18lg\n", spd); - printf ("psd %.18lg\n", psd); + union {double d; uint64_t i;} u; + + u.d = d; + printf ("d %.18lg %lx\n", d, u.i); + u.d = sd; + printf ("sd %.18lg %lx\n", sd, u.i); + u.d = pd; + printf ("pd %.18lg %lx\n", pd, u.i); + u.d = spd; + printf ("spd %.18lg %lx\n", spd, u.i); + u.d = psd; + printf ("psd %.18lg %lx\n", psd, u.i); fflush (stdout); @@ -97,9 +110,14 @@ testd (double d, bool changeExpected = true) } else { + uint64_t bc_d = bit_cast (d); + uint64_t bc_pd = bit_cast (pd); + uint64_t bc_sd = bit_cast (sd); + printf ("no change expected: d=%lx pd=%lx sd=%lx\n", bc_d, bc_pd, bc_sd); + // No bit change expected if input was inf or NaN - assert (bit_cast (pd) == bit_cast (d)); - assert (bit_cast (sd) == bit_cast (d)); + assert (bit_cast (pd) == bit_cast (d)); + assert (bit_cast (sd) == bit_cast (d)); } } From a811db96bea18bc7daead22686b8f1eb0c9b9652 Mon Sep 17 00:00:00 2001 From: Cary Phillips Date: Wed, 8 Sep 2021 10:55:21 -0400 Subject: [PATCH 3/6] testf()/testd() checks isnan() Signed-off-by: Cary Phillips --- src/ImathTest/testFun.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/ImathTest/testFun.cpp b/src/ImathTest/testFun.cpp index 64dc06b2..64937374 100644 --- a/src/ImathTest/testFun.cpp +++ b/src/ImathTest/testFun.cpp @@ -24,7 +24,6 @@ using namespace std; static inline To bit_cast (From from) { -#warning "using custom bit_cast" static_assert (sizeof (From) == sizeof (To), "Type sizes do not match"); union { @@ -71,10 +70,19 @@ testf (float f, bool changeExpected = true) uint32_t bc_f = bit_cast (f); uint32_t bc_pf = bit_cast (pf); uint32_t bc_sf = bit_cast (sf); - printf ("no change expected: f=%x pf=%x sf=%x\n", bc_f, bc_pf, bc_sf); - assert (bit_cast (pf) == bit_cast (f)); - assert (bit_cast (sf) == bit_cast (f)); + if (isnan(f)) + { + printf ("no change expected [isnan(f)]: f=%x pf=%x sf=%x\n", bc_f, bc_pf, bc_sf); + assert (isnan(pf)); + assert (isnan(sf)); + } + else + { + printf ("no change expected: [!isnan(f)]: f=%x pf=%x sf=%x\n", bc_f, bc_pf, bc_sf); + assert (bit_cast (pf) == bit_cast (f)); + assert (bit_cast (sf) == bit_cast (f)); + } } } @@ -118,6 +126,19 @@ testd (double d, bool changeExpected = true) // No bit change expected if input was inf or NaN assert (bit_cast (pd) == bit_cast (d)); assert (bit_cast (sd) == bit_cast (d)); + + if (isnan(d)) + { + printf ("no change expected [isnan(d)]: d=%lx pd=%lx sd=%lx\n", bc_d, bc_pd, bc_sd); + assert (isnan(pd)); + assert (isnan(sd)); + } + else + { + printf ("no change expected: [!isnan(d)]: d=%lx pd=%lx sd=%lx\n", bc_d, bc_pd, bc_sd); + assert (bit_cast (pd) == bit_cast (d)); + assert (bit_cast (sd) == bit_cast (d)); + } } } From b2025649b4b242aeef3abee52f687c081e3ad651 Mon Sep 17 00:00:00 2001 From: Cary Phillips Date: Wed, 8 Sep 2021 13:53:57 -0400 Subject: [PATCH 4/6] Fix typo in testd() Signed-off-by: Cary Phillips --- src/ImathTest/testFun.cpp | 41 ++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/ImathTest/testFun.cpp b/src/ImathTest/testFun.cpp index 64937374..dac195f4 100644 --- a/src/ImathTest/testFun.cpp +++ b/src/ImathTest/testFun.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "testFun.h" @@ -35,6 +36,25 @@ using namespace std; } #endif +std::string +formatBits (uint64_t x) +{ + std::stringstream s; + uint64_t mask = 0x1ULL << 63; + for (int i=0; i<64; i++) + { + if (i > 0 && i%4 == 0) + s << " "; + if (x & mask) + s << "1"; + else + s << "0"; + mask >>= 1; + } + + return s.str(); +} + void testf (float f, bool changeExpected = true) { @@ -99,15 +119,15 @@ testd (double d, bool changeExpected = true) union {double d; uint64_t i;} u; u.d = d; - printf ("d %.18lg %lx\n", d, u.i); + printf ("d %0.18lg %s\n", d, formatBits (u.i).c_str()); u.d = sd; - printf ("sd %.18lg %lx\n", sd, u.i); + printf ("sd %0.18lg %s\n", sd, formatBits (u.i).c_str()); u.d = pd; - printf ("pd %.18lg %lx\n", pd, u.i); + printf ("pd %0.18lg %s\n", pd, formatBits (u.i).c_str()); u.d = spd; - printf ("spd %.18lg %lx\n", spd, u.i); + printf ("spd %0.18lg %s\n", spd, formatBits (u.i).c_str()); u.d = psd; - printf ("psd %.18lg %lx\n", psd, u.i); + printf ("psd %0.18lg %s\n", psd, formatBits (u.i).c_str()); fflush (stdout); @@ -118,24 +138,17 @@ testd (double d, bool changeExpected = true) } else { - uint64_t bc_d = bit_cast (d); - uint64_t bc_pd = bit_cast (pd); - uint64_t bc_sd = bit_cast (sd); - printf ("no change expected: d=%lx pd=%lx sd=%lx\n", bc_d, bc_pd, bc_sd); - // No bit change expected if input was inf or NaN - assert (bit_cast (pd) == bit_cast (d)); - assert (bit_cast (sd) == bit_cast (d)); if (isnan(d)) { - printf ("no change expected [isnan(d)]: d=%lx pd=%lx sd=%lx\n", bc_d, bc_pd, bc_sd); + printf ("no change expected [isnan(d)]\n"); assert (isnan(pd)); assert (isnan(sd)); } else { - printf ("no change expected: [!isnan(d)]: d=%lx pd=%lx sd=%lx\n", bc_d, bc_pd, bc_sd); + printf ("no change expected: [!isnan(d)]\n"); assert (bit_cast (pd) == bit_cast (d)); assert (bit_cast (sd) == bit_cast (d)); } From 1e1b4cd0110c97e39d4e54b0364c28bc676e9dcb Mon Sep 17 00:00:00 2001 From: Cary Phillips Date: Wed, 8 Sep 2021 15:31:21 -0400 Subject: [PATCH 5/6] Cleanup & remove debugging info Signed-off-by: Cary Phillips --- src/ImathTest/testFun.cpp | 70 +++++++++------------------------------ 1 file changed, 16 insertions(+), 54 deletions(-) diff --git a/src/ImathTest/testFun.cpp b/src/ImathTest/testFun.cpp index dac195f4..0fa3ad16 100644 --- a/src/ImathTest/testFun.cpp +++ b/src/ImathTest/testFun.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include "testFun.h" @@ -36,25 +35,6 @@ using namespace std; } #endif -std::string -formatBits (uint64_t x) -{ - std::stringstream s; - uint64_t mask = 0x1ULL << 63; - for (int i=0; i<64; i++) - { - if (i > 0 && i%4 == 0) - s << " "; - if (x & mask) - s << "1"; - else - s << "0"; - mask >>= 1; - } - - return s.str(); -} - void testf (float f, bool changeExpected = true) { @@ -65,17 +45,11 @@ testf (float f, bool changeExpected = true) float spf = IMATH_INTERNAL_NAMESPACE::succf (IMATH_INTERNAL_NAMESPACE::predf (f)); float psf = IMATH_INTERNAL_NAMESPACE::predf (IMATH_INTERNAL_NAMESPACE::succf (f)); - union {float f; uint32_t i;} u; - u.f = f; - printf ("f %.9g %x\n", f, u.i); - u.f = sf; - printf ("sf %.9g %x\n", sf, u.i); - u.f = pf; - printf ("pf %.9g %x\n", pf, u.i); - u.f = spf; - printf ("spf %.9g %x\n", spf, u.i); - u.f = psf; - printf ("psf %.9g %x\n", psf, u.i); + printf ("f %.9g %x\n", f, bit_cast(f)); + printf ("sf %.9g %x\n", sf, bit_cast(sf)); + printf ("pf %.9g %x\n", pf, bit_cast(pf)); + printf ("spf %.9g %x\n", spf, bit_cast(spf)); + printf ("psf %.9g %x\n", psf, bit_cast(psf)); fflush (stdout); @@ -86,20 +60,16 @@ testf (float f, bool changeExpected = true) } else { - // No bit change expected if input was inf or NaN - uint32_t bc_f = bit_cast (f); - uint32_t bc_pf = bit_cast (pf); - uint32_t bc_sf = bit_cast (sf); - if (isnan(f)) { - printf ("no change expected [isnan(f)]: f=%x pf=%x sf=%x\n", bc_f, bc_pf, bc_sf); + // If f is nan, pf and sf may be converted from signaling + // to quiet nan, but they'll still be nan's. assert (isnan(pf)); assert (isnan(sf)); } else { - printf ("no change expected: [!isnan(f)]: f=%x pf=%x sf=%x\n", bc_f, bc_pf, bc_sf); + // No bit change expected if input was inf. assert (bit_cast (pf) == bit_cast (f)); assert (bit_cast (sf) == bit_cast (f)); } @@ -116,18 +86,11 @@ testd (double d, bool changeExpected = true) double spd = IMATH_INTERNAL_NAMESPACE::succd (IMATH_INTERNAL_NAMESPACE::predd (d)); double psd = IMATH_INTERNAL_NAMESPACE::predd (IMATH_INTERNAL_NAMESPACE::succd (d)); - union {double d; uint64_t i;} u; - - u.d = d; - printf ("d %0.18lg %s\n", d, formatBits (u.i).c_str()); - u.d = sd; - printf ("sd %0.18lg %s\n", sd, formatBits (u.i).c_str()); - u.d = pd; - printf ("pd %0.18lg %s\n", pd, formatBits (u.i).c_str()); - u.d = spd; - printf ("spd %0.18lg %s\n", spd, formatBits (u.i).c_str()); - u.d = psd; - printf ("psd %0.18lg %s\n", psd, formatBits (u.i).c_str()); + printf ("d %0.18lg %lx\n", d, bit_cast(d)); + printf ("sd %0.18lg %lx\n", sd, bit_cast(sd)); + printf ("pd %0.18lg %lx\n", pd, bit_cast(pd)); + printf ("spd %0.18lg %lx\n", spd, bit_cast(spd)); + printf ("psd %0.18lg %lx\n", psd, bit_cast(psd)); fflush (stdout); @@ -138,17 +101,16 @@ testd (double d, bool changeExpected = true) } else { - // No bit change expected if input was inf or NaN - if (isnan(d)) { - printf ("no change expected [isnan(d)]\n"); + // If f is nan, pf and sf may be converted from signaling + // to quiet nan, but they'll still be nan's. assert (isnan(pd)); assert (isnan(sd)); } else { - printf ("no change expected: [!isnan(d)]\n"); + // No bit change expected if input was inf. assert (bit_cast (pd) == bit_cast (d)); assert (bit_cast (sd) == bit_cast (d)); } From d3ed6c46d5f3677fb97f7a8b2bbeb3d4e5674fca Mon Sep 17 00:00:00 2001 From: Cary Phillips Date: Wed, 8 Sep 2021 16:01:48 -0400 Subject: [PATCH 6/6] typo Signed-off-by: Cary Phillips --- src/ImathTest/testFun.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ImathTest/testFun.cpp b/src/ImathTest/testFun.cpp index 0fa3ad16..91f25ae8 100644 --- a/src/ImathTest/testFun.cpp +++ b/src/ImathTest/testFun.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "testFun.h" @@ -45,11 +46,11 @@ testf (float f, bool changeExpected = true) float spf = IMATH_INTERNAL_NAMESPACE::succf (IMATH_INTERNAL_NAMESPACE::predf (f)); float psf = IMATH_INTERNAL_NAMESPACE::predf (IMATH_INTERNAL_NAMESPACE::succf (f)); - printf ("f %.9g %x\n", f, bit_cast(f)); - printf ("sf %.9g %x\n", sf, bit_cast(sf)); - printf ("pf %.9g %x\n", pf, bit_cast(pf)); - printf ("spf %.9g %x\n", spf, bit_cast(spf)); - printf ("psf %.9g %x\n", psf, bit_cast(psf)); + printf ("f %.9g %x\n", f, bit_cast(f)); + printf ("sf %.9g %x\n", sf, bit_cast(sf)); + printf ("pf %.9g %x\n", pf, bit_cast(pf)); + printf ("spf %.9g %x\n", spf, bit_cast(spf)); + printf ("psf %.9g %x\n", psf, bit_cast(psf)); fflush (stdout);