Author: Carl Friedrich Bolz-Tereick <[email protected]>
Branch: intbound-improvements
Changeset: r93251:2ecf080bbdb4
Date: 2017-12-02 22:32 +0100
http://bitbucket.org/pypy/pypy/changeset/2ecf080bbdb4/
Log: improve the bounds computation of modulo
diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py
b/rpython/jit/metainterp/optimizeopt/intutils.py
--- a/rpython/jit/metainterp/optimizeopt/intutils.py
+++ b/rpython/jit/metainterp/optimizeopt/intutils.py
@@ -210,14 +210,26 @@
def mod_bound(self, other):
r = IntUnbounded()
- if other.is_constant():
- val = other.getint()
- if val >= 0: # with Python's modulo: 0 <= (x % pos) < pos
- r.make_ge(IntBound(0, 0))
- r.make_lt(IntBound(val, val))
- else: # with Python's modulo: neg < (x % neg) <= 0
- r.make_gt(IntBound(val, val))
- r.make_le(IntBound(0, 0))
+ if not other.has_upper and not other.has_lower:
+ return r # nothing known about other
+ if other.known_nonnegative():
+ # with Python's modulo: 0 <= (x % pos) < pos
+ r.make_ge(IntBound(0, 0))
+ if other.has_upper:
+ r.make_lt(IntBound(other.upper, other.upper))
+ elif other.has_upper and other.upper <= 0:
+ # with Python's modulo: neg < (x % neg) <= 0
+ r.make_le(IntBound(0, 0))
+ if other.has_lower:
+ r.make_gt(IntBound(other.lower, other.lower))
+ else:
+ # the interval straddles 0, so we know this:
+ # other.lower < x % other < other.upper
+ if other.has_upper:
+ r.make_lt(IntBound(other.upper, other.upper))
+ if other.has_lower:
+ r.make_gt(IntBound(other.lower, other.lower))
+ pass
return r
def lshift_bound(self, other):
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py
@@ -5,7 +5,7 @@
import sys
from rpython.rlib.rarithmetic import LONG_BIT, ovfcheck
-from hypothesis import given, strategies
+from hypothesis import given, strategies, settings
special_values = (
range(-100, 100) +
@@ -23,7 +23,7 @@
ints = strategies.builds(
int, # strategies.integers sometimes returns a long?
special_values | strategies.integers(
- min_value=int(-sys.maxint-1), max_value=sys.maxint))
+ min_value=int(-sys.maxint-1), max_value=sys.maxint))
ints_or_none = strategies.none() | ints
@@ -39,7 +39,7 @@
return IntBound(a, b)
def const(a):
- return bound(a,a)
+ return bound(a, a)
def build_bound_with_contained_number(a, b, c):
@@ -335,6 +335,67 @@
if n2 != 0:
assert b3.contains(n1 % n2) # Python-style div
+def test_mod_bound_explicit():
+ # % positive
+ a = bound(1, 5).mod_bound(bound(1, 5))
+ assert a.contains(0)
+ assert a.contains(4)
+ assert not a.contains(-1)
+ assert not a.contains(5)
+
+ a = bound(1, 5).mod_bound(bound(1, None))
+ assert a.contains(0)
+ assert a.contains(4)
+ assert not a.contains(-1)
+ assert a.contains(100000)
+
+ # % negative
+ a = bound(1, 5).mod_bound(bound(-6, -1))
+ assert a.contains(0)
+ assert a.contains(-5)
+ assert not a.contains(-6)
+ assert not a.contains(1)
+
+ a = bound(1, 5).mod_bound(bound(None, -1))
+ assert a.contains(0)
+ assert a.contains(-5)
+ assert a.contains(-60000)
+ assert not a.contains(1)
+
+ # % neither
+ a = bound(1, 5).mod_bound(bound(-6, 10))
+ assert a.contains(0)
+ assert a.contains(-5)
+ assert a.contains(9)
+ assert not a.contains(-6)
+ assert not a.contains(10)
+
+ a = bound(1, 5).mod_bound(bound(None, 5))
+ assert a.contains(0)
+ assert a.contains(4)
+ assert a.contains(-5)
+ assert a.contains(-60000)
+ assert not a.contains(5)
+
+ a = bound(1, 5).mod_bound(bound(None, 0))
+ assert a.contains(0)
+ assert a.contains(-5)
+ assert a.contains(-60000)
+ assert not a.contains(1)
+
+ a = bound(1, 5).mod_bound(bound(-4, None))
+ assert a.contains(0)
+ assert a.contains(-3)
+ assert a.contains(60000)
+ assert not a.contains(-4)
+
+ a = bound(1, 5).mod_bound(bound(0, None))
+ assert a.contains(0)
+ assert a.contains(5)
+ assert a.contains(60000)
+ assert not a.contains(-1)
+
+
def test_sub_bound():
for _, _, b1 in some_bounds():
for _, _, b2 in some_bounds():
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit