Skip to content
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

Wacky modulus behaviour #775

Closed
p5pRT opened this issue Oct 22, 1999 · 7 comments
Closed

Wacky modulus behaviour #775

p5pRT opened this issue Oct 22, 1999 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Oct 22, 1999

Migrated from rt.perl.org#1700 (status was 'resolved')

Searchable as RT1700$

@p5pRT
Copy link
Author

p5pRT commented Oct 22, 1999

From gnat@frii.com

Until you do it in separate steps, 'time % -60' is never negative.
This smells like a spurious NV conversion. Somewhere.

Nat

@p5pRT
Copy link
Author

p5pRT commented Oct 22, 1999

From [Unknown Contact. See original ticket]

Nathan Torkington writes​:

perl -le 'print time % -60'
perl -le '$x = time; print $x % -60'
perl -le '$x = time; $y = $x % -60; print $y'

Until you do it in separate steps, 'time % -60' is never negative.
This smells like a spurious NV conversion. Somewhere.

Is not it that time may take an argument, and % may preceed an identifier?

Ilya

@p5pRT
Copy link
Author

p5pRT commented Oct 22, 1999

From [Unknown Contact. See original ticket]

Ilya Zakharevich writes​:

perl -le 'print time % -60'
perl -le '$x = time; print $x % -60'
perl -le '$x = time; $y = $x % -60; print $y'

Is not it that time may take an argument, and % may preceed an identifier?

I don't think so. The second case, which doesn't give an argument to
time(), prints the same thing as the first case.

Nat

@p5pRT
Copy link
Author

p5pRT commented Oct 23, 1999

From [Unknown Contact. See original ticket]

Nathan Torkington <gnat@​frii.com> wrote

perl -le 'print time % -60'
perl -le '$x = time; print $x % -60'
perl -le '$x = time; $y = $x % -60; print $y'

Until you do it in separate steps, 'time % -60' is never negative.
This smells like a spurious NV conversion. Somewhere.

Nope. It's a false optimisation. The last time it showed up, the
example was something like

perl -le 'print time; print time*1000'

I don't recall the details, but basically Perl is saying something like
"I know time() returns an IV, so I know the operation (* or %) is
on integers, so I'll force `use integer'". So you're getting the
altered semantics that you get from `use integer'.

I also don't recall why this didn't get fixed - whether it was just
lack of tuits, lack of understanding of the relevant code (that's my
excuse), or a desire to put performance above correct semantics.

Mike Guy

@p5pRT
Copy link
Author

p5pRT commented Oct 23, 1999

From @gsar

On Sat, 23 Oct 1999 16​:24​:17 BST, "M.J.T. Guy" wrote​:

Nathan Torkington <gnat@​frii.com> wrote

perl -le 'print time % -60'
perl -le '$x = time; print $x % -60'
perl -le '$x = time; $y = $x % -60; print $y'

Until you do it in separate steps, 'time % -60' is never negative.
This smells like a spurious NV conversion. Somewhere.

Nope. It's a false optimisation. The last time it showed up, the
example was something like

perl -le 'print time; print time*1000'

I don't recall the details, but basically Perl is saying something like
"I know time() returns an IV, so I know the operation (* or %) is
on integers, so I'll force `use integer'". So you're getting the
altered semantics that you get from `use integer'.

I also don't recall why this didn't get fixed - whether it was just
lack of tuits, lack of understanding of the relevant code (that's my
excuse), or a desire to put performance above correct semantics.

AFAIK this particular bug in modulus has never come up before, or I
would have fixed it. :-) Note that the "consistent C modulus"
behavior based on C<use integer> was something that got added in
5.004. Pity the testsuite isn't good enough to have caught this. :-(

Sarathy
gsar@​ActiveState.com

Inline Patch
-----------------------------------8<-----------------------------------
Change 4428 by gsar@auger on 1999/10/23 20:28:56

	fix accidental C modulo semantics on integer-valued operations
	(e.g. caused C<length("abc") % -10> to return 3 rather than -7)

Affected files ...

... //depot/perl/op.c#205 edit
... //depot/perl/t/op/int.t#6 edit

Differences ...

==== //depot/perl/op.c#205 (text) ====
Index: perl/op.c
--- perl/op.c.~1~	Sat Oct 23 13:29:02 1999
+++ perl/op.c	Sat Oct 23 13:29:02 1999
@@ -2112,8 +2112,12 @@
 	return o;
 
     if (!(PL_hints & HINT_INTEGER)) {
-	if (type == OP_DIVIDE || !(o->op_flags & OPf_KIDS))
+	if (type == OP_MODULO
+	    || type == OP_DIVIDE
+	    || !(o->op_flags & OPf_KIDS))
+	{
 	    return o;
+	}
 
 	for (curop = ((UNOP*)o)->op_first; curop; curop = curop->op_sibling) {
 	    if (curop->op_type == OP_CONST) {

==== //depot/perl/t/op/int.t#6 (xtext) ====
Index: perl/t/op/int.t
--- perl/t/op/int.t.~1~	Sat Oct 23 13:29:02 1999
+++ perl/t/op/int.t	Sat Oct 23 13:29:02 1999
@@ -1,9 +1,7 @@
 #!./perl
 
-# $RCSfile: int.t,v $$Revision: 4.1 $$Date: 92/08/07 18:28:00 $
-
-print "1..4\n";
+print "1..6\n";
 
 # compile time evaluation
 
 if (int(1.234) == 1) {print "ok 1\n";} else {print "not ok 1\n";}
@@ -15,3 +13,12 @@
 $x = 1.234;
 if (int($x) == 1) {print "ok 3\n";} else {print "not ok 3\n";}
 if (int(-$x) == -1) {print "ok 4\n";} else {print "not ok 4\n";}
+
+$x = length("abc") % -10;
+print $x == -7 ? "ok 5\n" : "# expected -7, got $x\nnot ok 5\n";
+
+{
+    use integer;
+    $x = length("abc") % -10;
+    print $x == 3 ? "ok 6\n" : "# expected 3, got $x\nnot ok 6\n";
+}
End of Patch.

@p5pRT
Copy link
Author

p5pRT commented Oct 24, 1999

From @gisle

Gurusamy Sarathy <gsar@​ActiveState.com> writes​:

+{
+ use integer;
+ $x = length("abc") % -10;
+ print $x == 3 ? "ok 6\n" : "# expected 3, got $x\nnot ok 6\n";
+}
End of Patch.

Is this safe?

Under 'use integer' you get the %-operator as implemented by C and C
allow more than one result to be correct for negative operands.
Perhaps something like is safer​:

use integer;
$x = length("abc") % -10;
$y = 3 % -10;
print $x == $y ? "ok 6\n" : "# expected $y, got $x\nnot ok 6\n";

Regards,
Gisle

@p5pRT
Copy link
Author

p5pRT commented Oct 24, 1999

From @gsar

On 24 Oct 1999 12​:25​:01 +0200, Gisle Aas wrote​:

Under 'use integer' you get the %-operator as implemented by C and C
allow more than one result to be correct for negative operands.
Perhaps something like is safer​:

use integer;
$x = length("abc") % -10;
$y = 3 % -10;
print $x == $y ? "ok 6\n" : "# expected $y, got $x\nnot ok 6\n";

Good point, but I think we could do somewhat better.

Sarathy
gsar@​ActiveState.com

Inline Patch
-----------------------------------8<-----------------------------------
Change 4441 by gsar@auger on 1999/10/24 14:33:11

	test in change#4428 needs strict interpretation of C modulus

Affected files ...

... //depot/perl/t/op/int.t#8 edit

Differences ...

==== //depot/perl/t/op/int.t#8 (xtext) ====
Index: perl/t/op/int.t
--- perl/t/op/int.t.~1~	Sun Oct 24 07:33:15 1999
+++ perl/t/op/int.t	Sun Oct 24 07:33:15 1999
@@ -25,5 +25,6 @@
 {
     use integer;
     $x = length("abc") % -10;
-    print $x == 3 ? "ok 6\n" : "# expected 3, got $x\nnot ok 6\n";
+    $y = (3/-10)*-10;
+    print $x+$y == 3 && abs($x) < 10 ? "ok 6\n" : "not ok 6\n";
 }
End of Patch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant