-
Notifications
You must be signed in to change notification settings - Fork 577
%g formatting broken on Ubuntu-18.04, NVSIZE == 8 #18170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
On 9/27/20 8:13 PM, sisyphus wrote:
This issue is found with perl-5.32.0, all the way back to perl-5.8.9
(AFAICT), there being no such issue on perl-5.6.2
Same problem exists on my Debian Wheezy system, but Windows (Windows 7)
and FreeBSD (freebsd-12.0) are fine.
I'm interested in fixing this - I would appreciate any hints on
whereabouts in the perl source I should start looking.
The code that does this is Perl_sv_vcatpvfn_flags in sv.c I looked at
the code a little, and it looks like it pays no attention to the
precision under %g, but does unde %f and %e. Since %g is either %f or
%e depending the the value, I'm surprised it doesn't just figure out
which and then jump to the appropriate code, instead of reimplementing
something.
… For this report, I'll stick to version 5.32.0 and Ubuntu-18.04.
*Description*
"%.${digits}g" formatting is broken for $digits > 17, $Config{nvsize} == 8.
A quick check indicates that this type of issue does NOT occur with
-Duselongdouble and -Dusequadmath builds of perl.
*Steps to Reproduce*
For example:
$ perl -le 'printf "%.54g\n", 0.3
0.29999999999999999
$ perl -le 'printf "%.53e\n", 0.3;'
2.99999999999999988897769753748434595763683319091796875e-01
*Expected behavior*
As you can see, the "%.53e" formatting is fine and produces the correct
result.
I expected the "%.54g" formatting to produce:
0.299999999999999988897769753748434595763683319091796875
but, either my expectation is way out of line, or the %g formatting is
severely crippled.
The significance of the correct output is that it exactly represents (as
a base 10 number) the actual value held by the double 0.3.
The "%.54g" formatting works fine in C, using the compiler that built
this perl-5.32.0.
Given that the capability for such extended formatting already exists,
I'm hopeful that it can be provided to "%g" without too much difficulty.
Cheers,
Rob
|
Thanks Karl - that sent me to the right place. which, AFAICT, equates to: The size of ebuf is 127, precis is set to 54 and fv is a long double representation of the value (0.3 in my example). In a C script I ran: char ebuf[127]; and it produced the expected value of It's getting late ... I'll see what tomorrow brings. Cheers, |
I misread the definition of SNPRINTF_G. SNPRINTF_G(fv, ebuf, sizeof(ebuf), precis) and it's the gcvt function that's crippled. I doubt that there will be any interest (apart from mine) in getting this fixed. Cheers, |
In the belief that this might not be the best forum on which to ask the questions I've just asked, I've also raised them at: |
On 9/30/20 12:09 AM, sisyphus wrote:
I misread the definition of SNPRINTF_G.
(I looked at the definition of Gconvert in uconfig.h - I should have
looked at the definition in the generated config.h.)
SNPRINTF_G(fv, ebuf, sizeof(ebuf), precis)
actually equates to:
gcvt((double)fv, precis, ebuf)
and it's the gcvt function that's crippled.
If sprintf() was used instead, then all would be as I like it.
I doubt that there will be any interest (apart from mine) in getting
this fixed.
Is there a configure option I can use when building perl on Ubuntu-18.04
which will lead to gcvt() being replaced by sprintf() ?
Or do I need to hack the source ?
Cheers,
Rob
—
I would be interested in getting this fixed. I don't believe there is a
Configure option, but why are we using it to begin with?
The linux man page for it says:
Marked as LEGACY in POSIX.1-2001. POSIX.1-2008 removes the
specification of gcvt(), recommending the use of sprintf(3) instead
(though snprintf(3) may be preferable).
|
Over on perlmonks (https://www.perlmonks.org/?node_id=11122363) Max and Merijn have suggested that fixing compline/d_gconvert.U is the way to go. Max also came up with a -Dd_Gconvert='sprintf((b),"%.*g",(n),(x))' configure option that seems to do the job, and doesn't break the test suite. And I'm still a little puzzled as to how freebsd-12.0 manages to do things correctly. Cheers, |
The Gconvert macro is used only in 2 places in the perl source - once in sv,c (inside the SNPRINTF_G macro), and once (explicitly) in cpan/Win32API-File/const2perl.h. Before I go any further, I'll spend a bit of time doing some testing of this with perl-5.33.2 builds on both Windows and Linux, for the variety of nvtypes. Ultimately, it would be nice to then do away completely with the Gconvert macro ... but probably best not to get too far ahead of myself. Cheers, |
On Thu, Oct 1, 2020 at 1:39 AM Karl Williamson ***@***.***> wrote:
I would be interested in getting this fixed. I don't believe there is a
Configure option, but why are we using it to begin with?
The linux man page for it says:
Marked as LEGACY in POSIX.1-2001. POSIX.1-2008 removes the
specification of gcvt(), recommending the use of sprintf(3) instead
(though snprintf(3) may be preferable).
To detect the bug I've added a test to t/op/sprintf2.t
See the attached sprintf2.t.patch.
The bug only affects perls whose nvtype is double, but my patch also adds
tests to check that %.*g formatting works as expected when a largish
decimal precision is requested on -Duselongdouble and -Dusequadmath builds.
When it comes to fixing this particular issue, I can see 3 options.
The first and simplest is, in Perl_sv_vcatpvfn_flags(), to entirely remove
the "else if (c == 'g' ...){}" block (which begins at line 13105 of sv.c).
That block is only ever entered if nvtype is double, and all tests still
pass if that block is removed - including the additional tests that I've
proposed in the patch to t/op/sprintf2.t.
Option 2 is the patch to sv.c that's in the attached sv.c.patch. It avoids
use of gcvt() by hard coding sprintf() in.
This is my preferred option, under the assumption that a correctly
functioning "else if (c == 'g' ...){}" block provides more optimal
performance, and should therefore be retained.
(I have not verified the validity of that assumption.)
When I first switched to using sprintf(), I got -Wformat-overflow warnings,
which I've managed to avoid by changing the conditions that are evaluated.
See the "NOTE" below.
With both of those options there is still an SNPRINTF_G() call
in Perl_sv_2pv_flags().
That means there is still an instance of Gconvert() being called whenever
Perl_sv_2pv_flags() is called - which could perhaps bight at some time.
A third option is to fix the way that Gconvert is set by the Configure
process, such that gcvt() is not used, even if available.
SNPRINTF_G() will then do the right thing.
In addition to fixing that Configure process, we would still need to apply
a patch to sv.c - see sv.c_with_gconvert_fixed.patch.
That patch is needed largely to avoid -Wformat-overflow warnings that would
be generated from inside the "else if (c == 'g' ...){}" block,during
compilation when sprintf() is used.
In fixing that, it also fixes the questionable conditions that previously
existed inside that "else if (c == 'g' ...){}" block.
NOTE: The -Wformat-overflow warning I allude to is:
warning: ‘%.*g’ directive writing between 1 and 133 bytes into a region of
size 127 [-Wformat-overflow=]
It's accompanied by a number of noisy and confusing "Note" messages.
It occurs only when sprintf() is used and it only occurs at -O2
optimization or higher with -Wall.
It may not occur on all systems, but it certainly occurs on Ubuntu-18.04.
I gather (from Hugo) that it has been seen before.
AFAICT, the compiler somehow detects that the buffer size is 127 (which is
correct) and that the maximum number of digits that can (and/or will) be
requested is 126.
Of course, "%.126g" can be as small as 1 byte or as large as 133 bytes -
and the top end of that range will certainly overflow a 127-byte buffer.
I suspect that the determination of the value of "126" might have resulted
from some of the strange conditions being evaluated inside the "else if (c
== 'g' ...){}" block. Or maybe an overly ambitious optimizer.
With the changes I've made to the conditions being evaluated, an overflow
cannot occur, and no -Wformat-overflow warning is emitted.
All patches seem ok to me on Ubuntu-18.04, Debian wheezy and Windows.
What do you think, Karl ? (And anyone else, of course.)
Can we get by with patching ? ... or do I need to knuckle down and fix the
way that Gconvert is being Configured ?
Cheers,
Rob
|
I can't see the 3 patches. . |
I'm not convinced the changes to the conditions are safe: we have calculated the width of the radix point and rolled that into I tried to create a locale with an extra-wide radix point for testing, but on this Ubuntu system while |
If it's possible that the radix point can consume more than one byte, then
my changes to the conditions are NOT safe.
I had not considered the possibility that such a radix point could exist -
and didn't realize the significance of the information you provided in your
latest post to the perlmonks thread.
Would this shortcoming in my changes be satisfactorily addressed by
changing the condition:
&& sizeof(ebuf) - precis > 10
to
&& sizeof(ebuf) - precis > 9 + SvCUR(PL_numeric_radix_sv)
or to simply:
&& sizeof(ebuf) - precis > 17 /* allow for worst case radix point of 8 */
.
I'm a little distrusting of the optimizer's ability to correctly evaluate
float_need, and haven't really tested its role in the appearance of the
overflow warnings.
I'm again wondering why the original condition (&& sizeof(ebuf) -
float_need > precis) could not prevent those warnings.
&& sizeof(ebuf) - float_need > precis
is equivalent to:
&& sizeof(ebuf) > precis + float_need
ise equivalent to:
&& sizeof(ebuf) - precis > float_need /* get overflow warnings */
We know that the warnings are prevented by:
&& sizeof(ebuf) - precis > 10 /* no overflow warnings */
I think the optimizer considers that the value of float_need is 0 ... but
I'm not sure.
And I know that we can avoid those warnings with the (wasteful):
&& sizeof(ebuf) - precis > 1 + float_need /* no overflow warnings */
Employing that last condition would mean that we'll fall through this block
when precis gets to a value of 91 - even though, allowing for an 8-byte
radix point, there's no need to fall through until precis reaches a value
of 110.
I've no problem with such premature fallthrough - everything would still
work fine. I assume the routine through to which we fall is less optimal,
but that doesn't bother me either.
My main concern is simply in getting correct results.
However, assuming that it provides more optimal performance, I do feel we
ought to respect the effort that has been put into this block of code and
mould it into something a little more dignified than it currently is.
…On Wed, Oct 7, 2020 at 3:56 AM Hugo van der Sanden ***@***.***> wrote:
I'm not convinced the changes to the conditions are safe: we have
calculated the width of the radix point and rolled that into float_need,
but you no longer include that in the checks.
I tried to create a locale with an extra-wide radix point for testing, but
on this Ubuntu system while locale(5) documents decimal_point only as
"string", locale-gen(1) actually restricts it to a single character. I
imagine not every OS is so restrictive, but that means I cannot readily
test it with anything wider than a single Unicode codepoint.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#18170 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAR3PAYUJU6B3XAWG5F56TSJND5JANCNFSM4R354WRA>
.
|
No, we need to go through hoops to get to it: act only #ifdef USE_LOCALE_NUMERIC; then safely swap in the actual locale (under mutex if needed), get it, then safely swap back (either immediately or later - but one of the two without fail). This is what the #ifdef USE_LOCALE_NUMERIC block just after the initialization of float_need is doing.
This is what I was referring to in my previous comment: I do not think it is safe to assume that every platform will guarantee that the radix point string is restricted to a single codepoint, though it appears to be doing its best to guarantee it on my Ubuntu system. I think we need to assume we may need to cope with a radix point like "<-----------------decimal point here------------------>", or at the very least a combining form that requires multiple codepoints.
Yes, it must treat the It's possible wrapping full range checks around that addition would also be sufficient to make the warning go away, I might give that a try tomorrow. |
On 10/6/20 10:56 AM, Hugo van der Sanden wrote:
I'm not convinced the changes to the conditions are safe: we have
calculated the width of the radix point and rolled that into
|float_need|, but you no longer include that in the checks.
I tried to create a locale with an extra-wide radix point for testing,
but on this Ubuntu system while |locale(5)| documents decimal_point only
as "string", |locale-gen(1)| actually restricts it to a single
character. I imagine not every OS is so restrictive, but that means I
cannot readily test it with anything wider than a single Unicode codepoint.
I know of no radix longer than 1 character wide; I kind of doubt there
is one, but possibly.
But I do know of a radix character more than a single byte wide. That
is U+066B ARABIC DECIMAL SEPARATOR.
My guess is that in printing you care about bytes rather than
characters. And this one's existence says you have to worry about its
width.
|
On Wed, Oct 7, 2020 at 1:30 PM Karl Williamson ***@***.***> wrote:
My guess is that in printing you care about bytes rather than
characters. And this one's existence says you have to worry about its
width.
Considerations regarding locale always do my head in.
The way I'm seeing it, if we know the width (in bytes) of the radix point
we can just alter the condition that I introduced to:
&& sizeof(ebuf) - precis > 9 + the_width
If USE_LOCALE_NUMERIC is defined, then we know that
the_width = SvCUR(PL_numeric_radix_sv)
So I take it that there must be some difficulty in determining the value of
"the_width" when USE_LOCALE_NUMERIC is not defined.
Am I, thus far, looking at it correctly ?
Cheers,
Rob
|
On 10/7/20 1:18 AM, sisyphus wrote:
On Wed, Oct 7, 2020 at 1:30 PM Karl Williamson ***@***.***>
wrote:
> My guess is that in printing you care about bytes rather than
> characters. And this one's existence says you have to worry about its
> width.
>
Considerations regarding locale always do my head in.
The way I'm seeing it, if we know the width (in bytes) of the radix point
we can just alter the condition that I introduced to:
&& sizeof(ebuf) - precis > 9 + the_width
If USE_LOCALE_NUMERIC is defined, then we know that
the_width = SvCUR(PL_numeric_radix_sv)
So I take it that there must be some difficulty in determining the value of
"the_width" when USE_LOCALE_NUMERIC is not defined.
Am I, thus far, looking at it correctly ?
If it isn't defined, what gets used is a dot radix, with a 1 byte width
|
On Thu, Oct 8, 2020 at 1:51 AM Karl Williamson ***@***.***> wrote:
If it isn't defined, what gets used is a dot radix, with a 1 byte width
So .... is the portable thing to do as simple as replacing:
&& sizeof(ebuf) - precis > 10
with:
#if defined(USE_LOCAL_NUMERIC)
&& sizeof(ebuf) - precis > 9 + SvCUR(PL_numeric_radix_sv)
#else
&& sizeof(ebuf) - precis > 10
#endif
Anyway ... if that's still not right, I'm happy to wait and see what Hugo
comes up with.
Maybe then, the penny will drop ;-)
Cheers,
Rob
|
This is becoming insane. With just that one condition removed, I can then replace the SNPRINTF_G() call with: and no overflow warning is emitted. I don't really know why that condition is in there to begin with. effectively guarantee that float_need < sizeof(ebuf), don't they ? Anyway, although this apparently fixes my original issue, it doesn't stop the premature fallthrough - if we think that's worth fixing. Cheers, |
Currently testing with the attached (sv.c2.txt) patch to sv.c. All it does is:
Any obvious problems with that ? |
Well, mainly the justification.
Following If removing that check is what makes the gcc warning go away, that's clearly a bug in gcc: making it less restrictive cannot possibly make it suddenly safe enough not to need a warning. If that really is the case, we'd be better off disabling the warning for affected versions of gcc.
No, not if
We've calculated float_need to be worst case what we need. If worst case is actually Fixing it would mean understanding what part of it is wrong, and correcting that part.
This is the part I know least about. I believe that historically there were lots of buggy sprintf() implementations out there, and I'm reasonably sure that's why we have this SNPRINTF_G macro in the first place. If those buggy implementations are still out there, this will break for them without any easy workaround. On the other hand, fixing it by updating configure or the hints files to make a different choice would give users of such hypothetical platforms a relatively easy workaround - the same one you found was available to you, by supplying a configure option. |
The way I'm seeing it, in the original sv.c we have But then ... it all turns out to be very flaky. Unless there really is a need (that I'm still too dim to notice) for the condition As to the removal of that SNPRINTF_G() call, we know it's not doing the right thing on Ubuntu and (probably) Debian because of the buggy gcvt() that Gconvert invokes. Perhaps the latter can be achieved simply by adding an appropriate test to the probing that the Configure script is already doing. So much work, for so little gain - the story of my life ;-) BTW, I think that when I first tried removing |
If It seems my earlier attempts to communicate this were unsuccessful, so if what I'm saying still isn't clear please try to point out what part of what I'm saying is not clear. |
Yes - I just needed to remind myself that x - y is always >= 0 in unsigned land irrespective of the relative magnitudes of x and y. (Pathetic, I know.) Not sure whether that meets with approval. Apart from that, the only other change I made was to replace the SNPRINTF_G call with: As I said, that was sufficient to avoid compilation warnings, Cheers, |
That last suggestion doesn't even sit well with my own cavalier standards. I tried a few other sneaky ways to test whether the '<' (or the '<=') condition held, like: For my own builds of perl, I think I'll just suppress that warning by changing the order of the existing conditions, and by providing the -Dd_Gconvert=sprintf(....) argument to the Configure command - at least until such time as I can get the Configure script to do the right thing. I did manually add a test to the Configure script which resulted in sprintf() being assigned to Gconvert. |
That looks fine to me, if accompanied with a comment explaining why.
Ditto. Note that there's also some value in trying to cut this down to a minimal reproducer that could be reported to the gcc team - fixing the warning there would be a better solution all round. Similarly, I hope that you will report your buggy gcvt() if you haven't already done so. |
Bug report about the gcvt/qgcvt behaviour has (now) been submitted: I also have a demo for a bug report regarding the -Wformat-overflow warnings: void foo(double, unsigned int); int main(void) { foo(d, precis); void foo(double dub, unsigned int prec) { The warning, and all of its associated noise, disappears as soon as the line Before I file the report, are there any thoughts about the script's fitness for submission in a bug report ? Cheers, |
I filed the gcvt and qgcvt bug reports with gcc, but they are disavowing any responsibility, stating: Anyone here know exactly where "there" is located ? Cheers, |
As I mentioned, when Gconvert uses spritnf() on Ubuntu, I get similar warnings in XS-APItest as experienced with sv.c: There was also another warning in XS-APItest: And I've included a revised patch to sv.c (sv.c.patch.txt) in accordance with latest suggestions. |
=> https://packages.ubuntu.com/search?keywords=libc6 You'll need a launchpad account; when I posted a recent issue for the locale package, they asked me to post it upstream (but pointed me where to go for that). |
That probably also merits a comment, something like:
This was already fixed a couple of weeks ago by 4e3e027.
I agree it's not robust, but that's not uncommon when trying to work around toolchain bugs. This LGTM. |
Getting closer, I think: As regards my changes to Configure, I suspect the same alteration would need to be made to https://perl5.git.perl.org/metaconfig.git/blob/HEAD:/U/compline/d_gconvert.U As regards my changes to sv.c, I still get the feeling that we should remove all references to
That allows just enough for a possible leading '-', a radix point, a (max) 5-byte exponent and the terminating NULL. I'm currently comfortable with the amendments to APItest.xs and sprintf2.t that I've proposed in this latest attached diff. Cheers, |
@Tux could you take a look at the Configure change proposed here? |
The "safety net" is there on non-DEBUGGING builds, because we'll get coredumps or security issues if we get it wrong. The safety net is removed on DEBUGGING builds. While the size of it may be arguable, I think the principle here is a good idea. This is described in the block comment above the derivation of float_need. The leading 0x1 is there for This is described in detail in the block comment above the derivation of float_need.
When you say "8-byte exponent", do you mean the sum of:
? The comments do explain the derivation of that, and it is described in more detail in the block comment above the derivation of float_need. I have no idea where your 5 maximum comes from. There are more formatting specifiers than just I am finding this discussion increasingly frustrating: I exhort you to read those comments. If you find something wrong there, please point that out specifically so we can correct it. If you find something unclear, please point out the specific part you find unclear so we can attempt to improve it. |
On Fri, Oct 16, 2020 at 2:43 AM Hugo van der Sanden < ***@***.***> wrote:
The leading 0x1 is there for %a formats.
We're in a block of code that's performing only %g formatting of doubles.
This is described in detail in the block comment above the derivation of
float_need.
2. `float_need` allows for an 8-byte exponent even though 5 bytes will be the maximum - more wastefulness and confusion.
When you say "8-byte exponent", do you mean the sum of:
+ 2 /* "e-", "p+" etc */
+ 6 /* exponent: up to 16383 (quad fp) */
Yes.
6 + 2 == 8 and that is clearly the number of bytes that are being allowed
for the exponent.
"16383" is a 5-digit number, and I don't know why they allow 6 bytes for
it. (Admittedly it's only 1 byte - nothing to get excited over.)
I have no idea where your 5 maximum comes from.
Since this block of code that I'm altering is guaranteed to be processing
only doubles, there will be no more than 3 digits in the exponent. Taking
into account the 'e-' means that we need to allow for 5 bytes.
There are more formatting specifiers than just %g being handled here.
These are all described in detail in the block comment above the derivation
of float_need.
Apart from the size of the safety net,I've no question with the way that
<code>float_need</code> is being set.
It just seems odd to me that we reference that value inside a block where
we are guaranteed to be performing %g formatting of a double.
To me, <code>float_need</code> is 27 bytes bigger than it needs to be for
the purposes of this particular block of code.
However, if 20 of those bytes are, in fact, there for a good reason (as
you've indicated), then it's only bigger than it needs to be by 7 bytes -
and it's not worth quibbling about 7 bytes.
Therefore, I'll just stay with that last patch.
I am finding this discussion increasingly frustrating: I exhort you to
read those comments. If you find something wrong there, please point that
out specifically so we can correct it. If you find something unclear,
please point out the specific part you find unclear so we can attempt to
improve it.
My preference is that I report a bug, and some competent person fixes it.
The second part of that doesn't seem to happen any more, so I end up trying
to contribute to the fixing of it myself.
If anyone with a commit bit wants to just jump in and fix this issue,
please do so.
Hugo, I understand your frustration, of course - and I apologise for
causing it.
I am always mindful of the need for me to do things better .... but that
mindfulness is (obviously and sadly) not sufficient.
Cheers,
Rob
|
Well the base bug here seemed to be in your C library's gcvt, and a secondary one was in gcc's printf warning logic.
The desire is for consistency: we know we need some logic to determine the minimum number of extra bytes, far better to have that in one place and then used in all relevant pathways. I would not necessarily be against setting float_need separately for different format letters, but I'd want to do it by expanding the existing setting of it with some conditionals, so that the logic being implemented continues to relate clearly to the existing comments. The question becomes whether there's enough benefit to justify the added complexity. But it would scare me to make tight assumptions about the maximum width of a radix point; I'd want some locale expert like @khwilliamson to offer assurance that those assumptions will be safe across the myriad platforms perl supports, and will continue to be when we add more platforms in the future. Independently of that, if you feel you could get some noticeable benefit from dropping the 20 byte safety margin, it would not be unreasonable to make it depend on a new #define that you could override at configure time - the current tight coupling to debugging perls does not really seem ideal to me.
.. or we could even #define the size of the safety net itself, which would let you set it to -7 if you were really feeling racy. |
Ok ... it's probably a good idea to just concentrate on the bugs.
(Yes, the -Wformat-overflow warning issued when compiling APItest.c is justified AFAICT.) So - let's just fix those 2 bugs, and do whatever we need to do to silence the bogus warnings. So ... I think I'm just waiting on the verdict from @Tux regarding proposed changes to Configure. The link to the glibc bug report (re gcvt and qgcvt) is: And the pre-existing report regarding the bogus -Wformat-overflow warnings (to which I added) is at: |
Sorry to be late, busy :( |
On Fri, Oct 16, 2020 at 6:00 PM H.Merijn Brand ***@***.***> wrote:
Sorry to be late, busy :(
I looked at the Configure part of
https://github.com/Perl/perl5/files/5384834/diff.txt , and it looks
harmless. I'd like to see either an explanation of what the Ubuntu/Debian
bug is or a reference url in some comment.
The Ubuntu/Debian bug is demonstrated (and reported) at:
https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1899553
Cheers,
Rob
|
Heh ... sorry, @Tux probably meant that he'd like to see the reference/explanation presented in the Configure file ;-) Do I now create a pull request ? Cheers, |
Just noticed that the Configure patch is incorrect. (I had fiddled about with that test to check that Gconvert would still use gcvt/qgcvt if the test passed ... and then had not properly reversed the fiddling.) Attached is the corrected Configure patch. |
That's usually the easiest way to get stuff reviewed and merged, yes. |
FWIW @khwilliamson created a branch. The patch to Configure has already been merged to meta, so if the complete pictura is accepted, a regen of Configure is ready for use. Accept pending :) |
This looks like it has been merged. Is there a reason to keep this ticket open @sisyphus |
@khwilliamson , AFAIK there's no reason to keep this open. |
This issue is found with perl-5.32.0, all the way back to perl-5.8.9 (AFAICT), there being no such issue on perl-5.6.2
Same problem exists on my Debian Wheezy system, but Windows (Windows 7) and FreeBSD (freebsd-12.0) are fine.
I'm interested in fixing this - I would appreciate any hints on whereabouts in the perl source I should start looking.
For this report, I'll stick to version 5.32.0 and Ubuntu-18.04.
Description
"%.${digits}g" formatting is broken for $digits > 17, $Config{nvsize} == 8.
A quick check indicates that this type of issue does NOT occur with -Duselongdouble and -Dusequadmath builds of perl.
Steps to Reproduce
For example:
$ perl -le 'printf "%.54g\n", 0.3
0.29999999999999999
$ perl -le 'printf "%.53e\n", 0.3;'
2.99999999999999988897769753748434595763683319091796875e-01
Expected behavior
As you can see, the "%.53e" formatting is fine and produces the correct result.
I expected the "%.54g" formatting to produce:
0.299999999999999988897769753748434595763683319091796875
but, either my expectation is way out of line, or the %g formatting is severely crippled.
The significance of the correct output is that it exactly represents (as a base 10 number) the actual value held by the double 0.3.
The "%.54g" formatting works fine in C, using the compiler that built this perl-5.32.0.
Given that the capability for such extended formatting already exists, I'm hopeful that it can be provided to "%g" without too much difficulty.
Cheers,
Rob
Perl configuration
Summary of my perl5 (revision 5 version 32 subversion 0) configuration:
Platform:
osname=linux
osvers=4.15.0-106-generic
archname=x86_64-linux
uname='linux sisyphus5-desktop 4.15.0-106-generic #107-ubuntu smp thu jun 4 11:27:52 utc 2020 x86_64 x86_64 x86_64 gnulinux '
config_args='-des -Duse64bitall -Dprefix=/home/sisyphus/perl-5.32.0-d'
hint=recommended
useposix=true
d_sigaction=define
useithreads=undef
usemultiplicity=undef
use64bitint=define
use64bitall=define
uselongdouble=undef
usemymalloc=n
default_inc_excludes_dot=define
bincompat5005=undef
Compiler:
cc='cc'
ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
optimize='-O2'
cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
ccversion=''
gccversion='7.5.0'
gccosandvers=''
intsize=4
longsize=8
ptrsize=8
doublesize=8
byteorder=12345678
doublekind=3
d_longlong=define
longlongsize=8
d_longdbl=define
longdblsize=16
longdblkind=3
ivtype='long'
ivsize=8
nvtype='double'
nvsize=8
Off_t='off_t'
lseeksize=8
alignbytes=8
prototype=define
Linker and Libraries:
ld='cc'
ldflags =' -fstack-protector-strong -L/usr/local/lib'
libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
libs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
libc=libc-2.27.so
so=so
useshrplib=false
libperl=libperl.a
gnulibc_version='2.27'
Dynamic Linking:
dlsrc=dl_dlopen.xs
dlext=so
d_dlsymun=undef
ccdlflags='-Wl,-E'
cccdlflags='-fPIC'
lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'
Characteristics of this binary (from libperl):
Compile-time options:
HAS_TIMES
PERLIO_LAYERS
PERL_COPY_ON_WRITE
PERL_DONT_CREATE_GVSV
PERL_MALLOC_WRAP
PERL_OP_PARENT
PERL_PRESERVE_IVUV
USE_64_BIT_ALL
USE_64_BIT_INT
USE_LARGE_FILES
USE_LOCALE
USE_LOCALE_COLLATE
USE_LOCALE_CTYPE
USE_LOCALE_NUMERIC
USE_LOCALE_TIME
USE_PERLIO
USE_PERL_ATOF
Built under linux
Compiled at Jun 25 2020 19:42:19
@inc:
/home/sisyphus/perl-5.32.0-d/lib/site_perl/5.32.0/x86_64-linux
/home/sisyphus/perl-5.32.0-d/lib/site_perl/5.32.0
/home/sisyphus/perl-5.32.0-d/lib/5.32.0/x86_64-linux
/home/sisyphus/perl-5.32.0-d/lib/5.32.0
The text was updated successfully, but these errors were encountered: