On 07/05/2017 11:22 AM, Max Reitz wrote: >>>> return (double)x == x && x == y; >>> >>> Yes, that would do, too; and spares me of having to think about how well >>> comparing an arbitrary double to UINT64_MAX actually works. :-) >> >> On second thought, this won't do, because (double)x == x is always true >> if x is an integer (because this will implicitly cast the second x to a >> double, too). However, (uint64_t)(double)x == x should work. > > Hm, well, the nice thing with this is that (double)UINT64_MAX is > actually UINT64_MAX + 1, and now (uint64_t)(UINT64_MAX + 1) is > undefined... Urgs.
(uint64_t)(UINT64_MAX + 1) is well-defined - it is 0. (Adding in unsigned integers is always well-defined - it wraps around on mathematical overflow modulo the integer size. You're thinking of overflow addition on signed integers, which is indeed undefined) > > So I guess one thing that isn't very obvious but that should *always* > work (and is always well-defined) is this: > > For uint64_t: y < 0x1p64 && (uint64_t)y == x > > For int64_t: y >= -0x1p63 && y < 0x1p63 && (int64_t)y == x That's harder to read, compared to the double-cast method which is well-defined after all. > > I hope. :-/ > > (But finally a chance to use binary exponents! Yay!) Justifying the use of binary exponents is going to be harder than that, and would need a really good comment in the code, compared to just using a safe double-cast. -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
signature.asc
Description: OpenPGP digital signature
