On 2017-07-05 18:29, Eric Blake wrote: > 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)
It's not. See the standard:
When a finite value of real floating type is converted to an integer
type other than _Bool, the fractional part is discarded (i.e., the value
is truncated toward zero). If the value of the integral part cannot be
represented by the integer type, the behavior is undefined. [61]
[61] The remaindering operation performed when a value of integer type
is converted to unsigned type need not be performed when a value of real
floating type is converted to unsigned type. Thus, the range of portable
real floating values is (−1, Utype_MAX+1).
See for yourself:
printf("%i\n", (uint64_t)(double)UINT64_MAX == UINT64_MAX);
This yields 1 with gcc and -O3.
>>
>> 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.
It's not safe.
Max
signature.asc
Description: OpenPGP digital signature
