Re: Fw: Tied hash numeric values are rounded off under Perl v5.8.6
Trimmed the cc list a little. On Thu, Sep 01, 2005 at 10:10:36PM -0700, Yitzchak Scott-Thoennes wrote: > On Thu, Sep 01, 2005 at 09:58:49PM -0700, Yitzchak Scott-Thoennes wrote: > > > I wouldn't really like to venture what the correct fix is, epecially as > > > I'm still consfused about the meanings of the public verses private N/I/P > > > flags. > > > > I *think* I understand it, and magic values shouldn't get public flags > > full stop. sv_2pv_flags is correct in assuming this. There's code > > somewhere that downgrades them to private that should discard any > > private flags if any public flags were found (but doesn't). > > I think the code I'm thinking of is in restore_magic (called by mg_get). I'm incorrect. The above applies only to magic on scalars, so sv_2pv_flags is making an unwarranted assumption and should look for public flags first. The $h{a} and @h{qw/a/} cases differ because pp_helem happens to do an sv_mortalcopy while pp_hslice doesn't. However, the bug I thought was there indeed was for scalar magic: sub TIESCALAR { bless {} } sub FETCH { my $x=3.3; 1 if 0+$x; $x } tie $h, "main"; print $h; prints 3 and should IMO print 3.3. The following fixes it, though I haven't run full tests yet: --- perl/mg.c.orig 2005-08-01 07:28:07.0 -0700 +++ perl/mg.c 2005-09-01 22:24:40.072814400 -0700 @@ -2793,8 +2793,16 @@ S_restore_magic(pTHX_ const void *p) SvFLAGS(sv) |= mgs->mgs_flags; else mg_magical(sv); - if (SvGMAGICAL(sv)) - SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK); + if (SvGMAGICAL(sv)) { +/* downgrade public flags to private, + and discard any other private flags */ + +U32 public = SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK); +if (public) { + SvFLAGS(sv) &= ~( public | SVp_IOK|SVp_NOK|SVp_POK ); +SvFLAGS(sv) |= ( public << PRIVSHIFT ); +} +} } mgs->mgs_sv = NULL; /* mark the MGS structure as restored */ End of Patch.
Re: Fw: Tied hash numeric values are rounded off under Perl v5.8.6
On Thu, Sep 01, 2005 at 09:58:49PM -0700, Yitzchak Scott-Thoennes wrote: > > I wouldn't really like to venture what the correct fix is, epecially as > > I'm still consfused about the meanings of the public verses private N/I/P > > flags. > > I *think* I understand it, and magic values shouldn't get public flags > full stop. sv_2pv_flags is correct in assuming this. There's code > somewhere that downgrades them to private that should discard any > private flags if any public flags were found (but doesn't). I think the code I'm thinking of is in restore_magic (called by mg_get).
Re: Fw: Tied hash numeric values are rounded off under Perl v5.8.6
On Thu, Sep 01, 2005 at 10:19:11PM +0100, Dave Mitchell wrote: > On Thu, Sep 01, 2005 at 10:25:24PM +0200, Marcus Holland-Moritz wrote: > > I think this is a bug in Perl itself that was introduced with > > 5.8.0 and is still present. It can be cut down to this code: > > > > #!perl -wl > > use Tie::Hash; > > tie %h, "Tie::StdHash"; > > $a = 3.55; > > $_ = $a + 0; > > $h{a} = $a; > > print $h{a}, ", ", @h{qw(a)}; > > > > __END__ > > > > [EMAIL PROTECTED] ~ $ perl5.6.2 test.pl > > 3.55, 3.55 > > > > [EMAIL PROTECTED] ~ $ perl5.8.0 test.pl > > 3.55, 3 > > > > [EMAIL PROTECTED] ~ $ bleadperl test.pl > > 3.55, 3 > > It's down to the different ways Perl_sv_2pv_flags handles magic and > non-magic values. In the former case, it does mg_get(), which happens to set > the SV with NOK,pIOK,pNOK flags and IV = 3, NV = 3.55. > Then, the C branch prefers I over N: > > if (SvIOKp(sv)) { > > goto tokensave; > } > if (SvNOKp(sv)) { > > > so stringifies to "3". > The non-magical branch only does the I thing if there isn't an N thing: > > if (SvIOK(sv) || ((SvIOKp(sv) && !SvNOKp(sv { > > so it stringifies to "3.55". > > I wouldn't really like to venture what the correct fix is, epecially as > I'm still consfused about the meanings of the public verses private N/I/P > flags. I *think* I understand it, and magic values shouldn't get public flags full stop. sv_2pv_flags is correct in assuming this. There's code somewhere that downgrades them to private that should discard any private flags if any public flags were found (but doesn't).
Re: Fw: Tied hash numeric values are rounded off under Perl v5.8.6
On Thu, Sep 01, 2005 at 10:25:24PM +0200, Marcus Holland-Moritz wrote: > I think this is a bug in Perl itself that was introduced with > 5.8.0 and is still present. It can be cut down to this code: > > #!perl -wl > use Tie::Hash; > tie %h, "Tie::StdHash"; > $a = 3.55; > $_ = $a + 0; > $h{a} = $a; > print $h{a}, ", ", @h{qw(a)}; > > __END__ > > [EMAIL PROTECTED] ~ $ perl5.6.2 test.pl > 3.55, 3.55 > > [EMAIL PROTECTED] ~ $ perl5.8.0 test.pl > 3.55, 3 > > [EMAIL PROTECTED] ~ $ bleadperl test.pl > 3.55, 3 It's down to the different ways Perl_sv_2pv_flags handles magic and non-magic values. In the former case, it does mg_get(), which happens to set the SV with NOK,pIOK,pNOK flags and IV = 3, NV = 3.55. Then, the C branch prefers I over N: if (SvIOKp(sv)) { goto tokensave; } if (SvNOKp(sv)) { so stringifies to "3". The non-magical branch only does the I thing if there isn't an N thing: if (SvIOK(sv) || ((SvIOKp(sv) && !SvNOKp(sv { so it stringifies to "3.55". I wouldn't really like to venture what the correct fix is, epecially as I'm still consfused about the meanings of the public verses private N/I/P flags. -- Wesley Crusher gets beaten up by his classmates for being a smarmy git, and consequently has a go at making some friends of his own age for a change. -- Things That Never Happen in "Star Trek" #18
Fw: Tied hash numeric values are rounded off under Perl v5.8.6
I think this is a bug in Perl itself that was introduced with 5.8.0 and is still present. It can be cut down to this code: #!perl -wl use Tie::Hash; tie %h, "Tie::StdHash"; $a = 3.55; $_ = $a + 0; $h{a} = $a; print $h{a}, ", ", @h{qw(a)}; __END__ [EMAIL PROTECTED] ~ $ perl5.6.2 test.pl 3.55, 3.55 [EMAIL PROTECTED] ~ $ perl5.8.0 test.pl 3.55, 3 [EMAIL PROTECTED] ~ $ bleadperl test.pl 3.55, 3 Unfortunately I don't have the time right now to investigate myself. I'm forwarding your message to the perl5-porters list. Marcus Begin forwarded message: Date: Thu, 1 Sep 2005 13:52:59 +0530 From: "Mandalemula, Rajesh" <[EMAIL PROTECTED]> To: <[EMAIL PROTECTED]> Cc: <[EMAIL PROTECTED]>, "Mandalemula, Rajesh" <[EMAIL PROTECTED]> Subject: Tied hash numeric values are rounded off under Perl v5.8.6 Hello, We recently upgraded Perl to v5.8.6 and noticed a behavioral change w.r.t tied hashes using Tie::IxHash (Tie::Hash::Indexed also) & numeric hash values. The same version of the module works fine under Perl v5.6.1 Problem: The attached program below rounds off the numeric hash value under 5.8.6. (Check "Scalar" & "Splice" values) <> Under Perl v5.6.1 the above code works fine. <> Further debugging revealed: From perldelta v5.8.0 - http://www.perldoc.com/perl5.8.0/pod/perldelta.html#Understanding-of-Num bers . . . . Perl now tries internally to use integer values in numeric conversions and basic arithmetics (+ - * /) if the arguments are integers, and tries also to keep the results stored internally as integers. This change leads to often slightly faster and always less lossy arithmetics. (Previously Perl always preferred floating point numbers in its math.) . . . . A quick test with the below example <> From http://www.faqs.org/docs/perl5int/perlvar.html . . . . What about pIOK? pIOK means that the IV slot represents the underlying ("p" for "private") data. If, for instance, the SV is tied, then we may not use the "10" that is in the IV slot - we must call the appropriate FETCH routine to get the value - so IOK is not set. The "10", however, is private data, only available to the tying mechanism, so pIOK is set. . . . . We understand that this is a behavioral change in Perl v5.8, and one could revert to the old v5.6.1 behavior by re-compiling Perl with -DNO_PERL_PRESERVE_IVUV, which we would like to avoid for the reasons mentioned in the perldelta page above. Hopefully the Perl module Tie::IxHash could be made aware of this behavior and avoid errors like above in data interpretation. Please note that this behavior exists for all tied variables, not just tied hashes. Any quick response would be appreciated. Thanks. Rajesh$ perl -V:'version' version='5.8.6'; $ perl use Tie::IxHash; use Devel::Peek; my %h; tie %h, "Tie::IxHash"; $a = 3.55; $b = $a * 2; $h{numeric} = $a; print "Splice = "; print @h{numeric}, "\n"; print "Scalar = "; print $h{numeric}, "\n"; ^D Splice = 3 Scalar = 3.55 $$ /usr/local/bin/perl -V:'version' version='5.6.1'; $ /usr/local/bin/perl use Tie::IxHash; use Devel::Peek; my %h; tie %h, "Tie::IxHash"; $a = 3.55; $b = $a * 2; $h{numeric} = $a; print "Splice = "; print @h{numeric}, "\n"; print "Scalar = "; print $h{numeric}, "\n"; ^D Splice = 3.55 Scalar = 3.55 $$ perl -V:'version' version='5.8.6'; $ perl use Devel::Peek; $a = 3.55; Devel::Peek::Dump($a); $b = 2.5 * $a * 4.5; Devel::Peek::Dump($a); ^D SV = NV(0x180d38) at 0x17af28 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 3.55 SV = PVNV(0x19acc8) at 0x17af28 REFCNT = 1 FLAGS = (NOK,pIOK,pNOK) IV = 3 NV = 3.55 PV = 0 $ Note: The pIOK is set for $a, even when $a is just used in the expr "$b = 2.5 * $a * 4.5" The same code when run under v5.6.1 does *not* set pIOK for $a $ /usr/local/bin/perl -V:'version' version='5.6.1'; $ /usr/local/bin/perl use Devel::Peek; $a = 3.55; Devel::Peek::Dump($a); $b = 2.5 * $a * 4.5; Devel::Peek::Dump($a); ^D SV = NV(0x11bc78) at 0x110934 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 3.55 SV = NV(0x11bc78) at 0x110934 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 3.55 $