Re: Tied hash numeric values are rounded off under Perl v5.8.6

2005-09-06 Thread Rafael Garcia-Suarez
Yitzchak Scott-Thoennes wrote:
 
 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:

Thanks, applied as change #25358, your testcase added to t/op/tie.t.

 --- perl/mg.c.orig  2005-08-01 07:28:07.0 -0700
 +++ perl/mg.c   2005-09-01 22:24:40.072814400 -0700


Tied hash numeric values are rounded off under Perl v5.8.6

2005-09-02 Thread Mandalemula, Rajesh
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)

 test_586.txt 

Under Perl v5.6.1 the above code works fine.

 test_561.txt 

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

 test_case.txt 

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
$

Re: Fw: Tied hash numeric values are rounded off under Perl v5.8.6

2005-09-02 Thread Yitzchak Scott-Thoennes
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.


Fw: Tied hash numeric values are rounded off under Perl v5.8.6

2005-09-01 Thread Marcus Holland-Moritz
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)

 test_586.txt 

Under Perl v5.6.1 the above code works fine.

 test_561.txt 

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

 test_case.txt 

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
$

Re: Fw: Tied hash numeric values are rounded off under Perl v5.8.6

2005-09-01 Thread Dave Mitchell
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 Cif (SvGMAGICAL(sv)) 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


Re: Fw: Tied hash numeric values are rounded off under Perl v5.8.6

2005-09-01 Thread Yitzchak Scott-Thoennes
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 Cif (SvGMAGICAL(sv)) 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

2005-09-01 Thread Yitzchak Scott-Thoennes
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).