From: Max Reitz <mreitz@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: qemu-block@nongnu.org, Kevin Wolf <kwolf@redhat.com>,
qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v3 2/5] qapi: Add qobject_is_equal()
Date: Wed, 5 Jul 2017 18:22:55 +0200 [thread overview]
Message-ID: <e21524cb-a199-fa6e-11f6-8b445a1633db@redhat.com> (raw)
In-Reply-To: <5067e305-39fe-3590-4a7c-0f0136d8e5b1@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 4785 bytes --]
On 2017-07-05 18:05, Max Reitz wrote:
> On 2017-07-05 15:48, Max Reitz wrote:
>> On 2017-07-05 09:07, Markus Armbruster wrote:
>>> Max Reitz <mreitz@redhat.com> writes:
>>>
>>>> This generic function (along with its implementations for different
>>>> types) determines whether two QObjects are equal.
>>>>
>>>> Signed-off-by: Max Reitz <mreitz@redhat.com>
>>> [...]
>>>> diff --git a/qobject/qnum.c b/qobject/qnum.c
>>>> index 476e81c..784d061 100644
>>>> --- a/qobject/qnum.c
>>>> +++ b/qobject/qnum.c
>>>> @@ -213,6 +213,59 @@ QNum *qobject_to_qnum(const QObject *obj)
>>>> }
>>>>
>>>> /**
>>>> + * qnum_is_equal(): Test whether the two QNums are equal
>>>> + */
>>>> +bool qnum_is_equal(const QObject *x, const QObject *y)
>>>> +{
>>>> + QNum *num_x = qobject_to_qnum(x);
>>>> + QNum *num_y = qobject_to_qnum(y);
>>>> +
>>>> + switch (num_x->kind) {
>>>> + case QNUM_I64:
>>>> + switch (num_y->kind) {
>>>> + case QNUM_I64:
>>>> + /* Comparison in native int64_t type */
>>>> + return num_x->u.i64 == num_y->u.i64;
>>>> + case QNUM_U64:
>>>> + /* Implicit conversion of x to uin64_t, so we have to
>>>> + * check its sign before */
>>>> + return num_x->u.i64 >= 0 && num_x->u.i64 == num_y->u.u64;
>>>> + case QNUM_DOUBLE:
>>>> + /* Implicit conversion of x to double; no overflow
>>>> + * possible */
>>>> + return num_x->u.i64 == num_y->u.dbl;
>>>
>>> Overflow is impossible, but loss of precision is possible:
>>>
>>> (double)9007199254740993ull == 9007199254740992.0
>>>
>>> yields true. Is this what we want?
>>
>> I'd argue that yes, because the floating point value represents
>> basically all of the values which are "equal" to it.
>>
>> But I don't have a string opinion. I guess the alternative would be to
>> convert the double to an integer instead and check for overflows before?
>>
>>>> + }
>>>> + abort();
>>>> + case QNUM_U64:
>>>> + switch (num_y->kind) {
>>>> + case QNUM_I64:
>>>> + return qnum_is_equal(y, x);
>>>> + case QNUM_U64:
>>>> + /* Comparison in native uint64_t type */
>>>> + return num_x->u.u64 == num_y->u.u64;
>>>> + case QNUM_DOUBLE:
>>>> + /* Implicit conversion of x to double; no overflow
>>>> + * possible */
>>>> + return num_x->u.u64 == num_y->u.dbl;
>>>
>>> Similar loss of precision.
>>>
>>>> + }
>>>> + abort();
>>>> + case QNUM_DOUBLE:
>>>> + switch (num_y->kind) {
>>>> + case QNUM_I64:
>>>> + return qnum_is_equal(y, x);
>>>> + case QNUM_U64:
>>>> + return qnum_is_equal(y, x);
>>>> + case QNUM_DOUBLE:
>>>> + /* Comparison in native double type */
>>>> + return num_x->u.dbl == num_y->u.dbl;
>>>> + }
>>>> + abort();
>>>> + }
>>>> +
>>>> + abort();
>>>> +}
>>>
>>> I think there's more than one sane interpretations of "is equal",
>>> including:
>>>
>>> * The mathematical numbers represented by @x and @y are equal.
>>>
>>> * @x and @y have the same contents, i.e. same kind and u.
>>>
>>> * @x and @y are the same object (listed for completeness; we don't need
>>> a function to compare pointers).
>>>
>>> Your patch implements yet another one. Which one do we want, and why?
>>
>> Mine is the first one, except that I think that a floating point value
>> does not represent a single number but just some number in a range.
>>
>>> The second is easier to implement than the first.
>>
>> It seems much less useful, though.
>>
>>> If we really want the first, you need to fix the loss of precision bugs.
>>
>> I'm not sure, but I don't mind either, so...
>>
>>> I guess the obvious fix is
>>>
>>> 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.
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
I hope. :-/
(But finally a chance to use binary exponents! Yay!)
Max
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 498 bytes --]
next prev parent reply other threads:[~2017-07-05 16:23 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-07-03 12:25 [Qemu-devel] [PATCH v3 0/5] block: Don't compare strings in bdrv_reopen_prepare() Max Reitz
2017-07-03 12:25 ` [Qemu-devel] [PATCH v3 1/5] qapi/qnull: Add own header Max Reitz
2017-07-03 12:35 ` Eric Blake
2017-07-03 12:25 ` [Qemu-devel] [PATCH v3 2/5] qapi: Add qobject_is_equal() Max Reitz
2017-07-03 12:44 ` Eric Blake
2017-07-05 7:07 ` Markus Armbruster
2017-07-05 13:48 ` Max Reitz
2017-07-05 14:15 ` Eric Blake
2017-07-05 16:11 ` Markus Armbruster
2017-07-05 16:05 ` Max Reitz
2017-07-05 16:22 ` Max Reitz [this message]
2017-07-05 16:29 ` Eric Blake
2017-07-05 17:00 ` Max Reitz
2017-07-05 17:04 ` Max Reitz
2017-07-05 17:22 ` Eric Blake
2017-07-05 17:18 ` Eric Blake
2017-07-05 16:30 ` Max Reitz
2017-07-03 12:25 ` [Qemu-devel] [PATCH v3 3/5] block: qobject_is_equal() in bdrv_reopen_prepare() Max Reitz
2017-07-03 12:51 ` Eric Blake
2017-07-03 13:01 ` Max Reitz
2017-07-03 14:29 ` Eric Blake
2017-07-05 7:14 ` Markus Armbruster
2017-07-05 17:50 ` Max Reitz
2017-07-03 12:25 ` [Qemu-devel] [PATCH v3 4/5] iotests: Add test for non-string option reopening Max Reitz
2017-07-03 12:25 ` [Qemu-devel] [PATCH v3 5/5] tests: Add check-qobject for equality tests Max Reitz
2017-07-03 14:15 ` Eric Blake
2017-07-03 16:13 ` Max Reitz
2017-07-05 7:22 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e21524cb-a199-fa6e-11f6-8b445a1633db@redhat.com \
--to=mreitz@redhat.com \
--cc=armbru@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.