qemu-block
[Top][All Lists]

## Re: [Qemu-block] [Qemu-devel] [PATCH v3 2/5] qapi: Add qobject_is_equal(

 From: Max Reitz Subject: Re: [Qemu-block] [Qemu-devel] [PATCH v3 2/5] qapi: Add qobject_is_equal() Date: Wed, 5 Jul 2017 19:00:45 +0200 User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.0

```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