From: "Ludovic Courtès" <ludo@gnu.org>
To: Maxime Devos <maximedevos@telenet.be>
Cc: 49659@debbugs.gnu.org
Subject: [bug#49659] [PATCH core-updates] gnu: guile: Fix failing tests on i686-linux.
Date: Tue, 20 Jul 2021 22:51:59 +0200 [thread overview]
Message-ID: <87fsw8k8sw.fsf_-_@gnu.org> (raw)
In-Reply-To: <ca331c5fb87a4d0697c5282e5452e0e0eaae6424.camel@telenet.be> (Maxime Devos's message of "Tue, 20 Jul 2021 18:55:52 +0200")
Maxime Devos <maximedevos@telenet.be> skribis:
> Ludovic Courtès schreef op di 20-07-2021 om 15:55 [+0200]:
[...]
>> 1. Should we make it conditional on
>> (or (string-prefix? "i686-" %host-type)
>> (string-prefix? "i586-" %host-type))
>
> Rather, (target-x86-32?). target-x86-32? also recognises "i486-linux-gnu"
> even though that's not a ‘supported’ cross-target.
Yes, makes sense.
>> ? (I wonder why armhf-linux doesn’t have the same problem.)
>
> AFAIK floats & doubles on arm don't have excess precision.
>
> Floating-point numbers are either 32-bit or 64-bit,
> unlike in x86, where the floating-point registers are 80-bit
> but (sizeof) double==8 (64 bits).
>
> (I'm ignoring MMX, SSE and the like.)
>
> I don't know any architectures beside x86 which have excess precision.
> "-fexcess-precision=standard" should be harmless on architectures
> that don't have excess precision.
>
> I'd make it unconditional, but conditional on x86-target? should work
> for all ‘supported’ targets in Guix.
Alright.
I’d still err on the side of making the change only for target-x86-32?,
because that’s the only case where we know it’s needed.
>> 2. Is there any downside to compiling all of libguile with this flag?
>
> I searched with "git grep -F double" and "git grep -F float".
> Floating-point arithmetic doen't seem to be used much outside numbers.c.
>
> There's vm-engine.c, but the results of the calculations are written
> to some (stack?) memory (not a register), so the excess precision
> would be thrown away anyway, so I don't expect a slow-down.
>
> No code appears to be relying on excess precision.
OK.
>> 3. Do we have a clear explanation of why ‘-fexcess-precision=fast’
>> (the default) would lead to failures in ‘numbers.test’?
>
> The problem I think is that the rounding choices made in
> scm_i_inexact_floor_divide
> must be consistent with those made in
> scm_i_inexact_floor_quotient
> and
> scm_i_inexact_floor_remainder
> (There are tests testing whether the results agree.)
>
> "-fexcess-precision=standard" reduces the degrees of freedom GCC has
> in choosing when to round, so it is more likely the rounding choices
> coincide? It's only an untested hypothesis though.
>
> FWIW, I think this line:
>
> /* in scm_i_inexact_floor_remainder */
> return scm_i_from_double (x - y * floor (x / y));
>
> should be (for less fragility in case GCC changes its optimisations and
> register allocation / spilling)
>
> /* in scm_i_inexact_floor_remainder */
> return scm_i_from_double (x - y * (double) floor (x / y));
>
> even then, there's no guarantee the rounding choices for x/y
> are the same in scm_i_inexact_floor_divide, scm_i_inexact_floor_remainder
> and scm_i_inexact_floor_quotient.
Makes sense. Seems to me that this should simply be implemented
differently to avoid the inconsistency in the first place (or one could
ignore IA32 altogether…).
> I dunno if 'floor' is broken. Let me explain why this output is possible for a
> well-implemented 'floor':
>
> I want to note that printf("%f", floor(x/y))
> can display 16 different strings:
>
> GCC can choose to round 'x' and/or 'y' by moving it from a register to stack memory.
> (doesn't apply here I think because SCM values discard the excess precision)
>
> GCC can choose to round the result of x/y (same reasons)
>
> GCC can choose to round the result of floor(x/y) (same reasons)
>
> Likewise, printf("%f", x/y) can display 8 different strings, and the rounding
> choices may be different from those made for printf("%f", floor(x/y)).
>
> So this inconsistency (x/y=91.00... > 90.00 = floor(x/y)) doesn't really
> surprise me. A more concrete scenario: suppose the CPU is configured to round
> upwards, and 'floor' is a mapping between extended-precision floating-point numbers.
>
> Let 'x' and 'y' be two floating-point numbers, such that:
>
> (1) the mathematical value of 'x/y' is slightly less than 91
> (2) 'x/y' when calculated in extended precision is slightly less than 91.
> Denote this approximation as F1.
> (3) 'x/y' when calculated in double precision is 91 (or slightly larger)
> (due to the ‘rounding upwards’ mode, in ‘rounding downwards’ it might
> have been slightly less than 91 as in (2))
> Denote this approximation as F2.
>
> Then [floor(x/y)=] floor(F1)=floor(90.999...)=90.0,
> and [x/y=] F2=91.0, thus we seemingly have x/y >= 1 + floor(x/y),
> even though that's mathematically nonsense.
>
> Thus, by choosing when to round (in-)appropriately, it is possible (on x86)
> that printf("x/y=%f, floor(x/y)=%f",x/y,floor(x/y)) will output "x/y=91.0 floor(x/y)=90.0".
I’m no expert but that makes sense to me.
Could you send an updated patch?
If you think of a way to fix the issue in Guile itself, we can also do
that. :-)
Thanks for the investigation & explanation!
Ludo’.
next prev parent reply other threads:[~2021-07-20 20:53 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-20 11:27 [bug#49659] [PATCH core-updates] gnu: guile: Fix failing tests on i686-linux Maxime Devos
2021-07-20 13:55 ` Ludovic Courtès
2021-07-20 16:55 ` Maxime Devos
2021-07-20 20:51 ` Ludovic Courtès [this message]
2021-07-20 18:22 ` Efraim Flashner
2021-07-20 21:34 ` [bug#49659] [PATCH v2\ core-updates v2] " Maxime Devos
2021-07-21 13:49 ` bug#49659: [PATCH core-updates] " Ludovic Courtès
2021-07-21 14:50 ` [bug#49659] " Mathieu Othacehe
2021-07-23 9:07 ` Ludovic Courtès
2021-07-23 9:27 ` Maxime Devos
2021-07-25 23:52 ` Thiago Jung Bauermann via Guix-patches via
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
List information: https://guix.gnu.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87fsw8k8sw.fsf_-_@gnu.org \
--to=ludo@gnu.org \
--cc=49659@debbugs.gnu.org \
--cc=maximedevos@telenet.be \
/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.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).