[pypy-commit] pypy default: merge heads
arigo
noreply at buildbot.pypy.org
Wed Feb 19 19:38:56 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r69211:6a81e7b47559
Date: 2014-02-19 19:38 +0100
http://bitbucket.org/pypy/pypy/changeset/6a81e7b47559/
Log: merge heads
diff --git a/lib-python/2.7/test/test_audioop.py b/lib-python/2.7/test/test_audioop.py
--- a/lib-python/2.7/test/test_audioop.py
+++ b/lib-python/2.7/test/test_audioop.py
@@ -1,6 +1,6 @@
import audioop
import unittest
-from test.test_support import run_unittest
+from test.test_support import run_unittest, impl_detail
endian = 'big' if audioop.getsample('\0\1', 2, 0) == 1 else 'little'
@@ -93,21 +93,25 @@
wtd = len(d2)//3
self.assertEqual(len(audioop.lin2lin(d1, got, wtd)), len(d2))
+ @impl_detail(pypy=False)
def test_adpcm2lin(self):
# Very cursory test
self.assertEqual(audioop.adpcm2lin(b'\0\0', 1, None), (b'\0' * 4, (0,0)))
self.assertEqual(audioop.adpcm2lin(b'\0\0', 2, None), (b'\0' * 8, (0,0)))
self.assertEqual(audioop.adpcm2lin(b'\0\0', 4, None), (b'\0' * 16, (0,0)))
+ @impl_detail(pypy=False)
def test_lin2adpcm(self):
# Very cursory test
self.assertEqual(audioop.lin2adpcm('\0\0\0\0', 1, None), ('\0\0', (0,0)))
+ @impl_detail(pypy=False)
def test_lin2alaw(self):
self.assertEqual(audioop.lin2alaw(data[0], 1), '\xd5\xc5\xf5')
self.assertEqual(audioop.lin2alaw(data[1], 2), '\xd5\xd5\xd5')
self.assertEqual(audioop.lin2alaw(data[2], 4), '\xd5\xd5\xd5')
+ @impl_detail(pypy=False)
def test_alaw2lin(self):
# Cursory
d = audioop.lin2alaw(data[0], 1)
@@ -123,11 +127,13 @@
self.assertEqual(audioop.alaw2lin(d, 4),
b'\x00\x00\x08\x00\x00\x00\x08\x01\x00\x00\x10\x02')
+ @impl_detail(pypy=False)
def test_lin2ulaw(self):
self.assertEqual(audioop.lin2ulaw(data[0], 1), '\xff\xe7\xdb')
self.assertEqual(audioop.lin2ulaw(data[1], 2), '\xff\xff\xff')
self.assertEqual(audioop.lin2ulaw(data[2], 4), '\xff\xff\xff')
+ @impl_detail(pypy=False)
def test_ulaw2lin(self):
# Cursory
d = audioop.lin2ulaw(data[0], 1)
@@ -195,6 +201,7 @@
self.assertRaises(audioop.error,
audioop.findmax, ''.join( chr(x) for x in xrange(256)), -2392392)
+ @impl_detail(pypy=False)
def test_issue7673(self):
state = None
for data, size in INVALID_DATA:
@@ -219,6 +226,7 @@
self.assertRaises(audioop.error, audioop.lin2alaw, data, size)
self.assertRaises(audioop.error, audioop.lin2adpcm, data, size, state)
+ @impl_detail(pypy=False)
def test_wrongsize(self):
data = b'abc'
state = None
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -109,7 +109,7 @@
RegrTest('test_asynchat.py', usemodules='select fcntl'),
RegrTest('test_asyncore.py', usemodules='select fcntl'),
RegrTest('test_atexit.py', core=True),
- RegrTest('test_audioop.py', skip="incomplete module"),
+ RegrTest('test_audioop.py'),
RegrTest('test_augassign.py', core=True),
RegrTest('test_base64.py', usemodules='struct'),
RegrTest('test_bastion.py'),
diff --git a/lib_pypy/audioop.py b/lib_pypy/audioop.py
--- a/lib_pypy/audioop.py
+++ b/lib_pypy/audioop.py
@@ -1,5 +1,8 @@
-
+import __builtin__
+import math
import struct
+from fractions import gcd
+from ctypes import create_string_buffer
class error(Exception):
@@ -8,7 +11,7 @@
def _check_size(size):
if size != 1 and size != 2 and size != 4:
- raise error("Size should be 1, 2 or 4")
+ raise error("Size should be 1, 2 or 4")
def _check_params(length, size):
@@ -17,13 +20,526 @@
raise error("not a whole number of frames")
+def _sample_count(cp, size):
+ return len(cp) / size
+
+
+def _get_samples(cp, size, signed=True):
+ for i in range(_sample_count(cp, size)):
+ yield _get_sample(cp, size, i, signed)
+
+
+def _struct_format(size, signed):
+ if size == 1:
+ return "b" if signed else "B"
+ elif size == 2:
+ return "h" if signed else "H"
+ elif size == 4:
+ return "i" if signed else "I"
+
+
+def _get_sample(cp, size, i, signed=True):
+ fmt = _struct_format(size, signed)
+ start = i * size
+ end = start + size
+ return struct.unpack_from(fmt, buffer(cp)[start:end])[0]
+
+
+def _put_sample(cp, size, i, val, signed=True):
+ fmt = _struct_format(size, signed)
+ struct.pack_into(fmt, cp, i * size, val)
+
+
+def _get_maxval(size, signed=True):
+ if signed and size == 1:
+ return 0x7f
+ elif size == 1:
+ return 0xff
+ elif signed and size == 2:
+ return 0x7fff
+ elif size == 2:
+ return 0xffff
+ elif signed and size == 4:
+ return 0x7fffffff
+ elif size == 4:
+ return 0xffffffff
+
+
+def _get_minval(size, signed=True):
+ if not signed:
+ return 0
+ elif size == 1:
+ return -0x80
+ elif size == 2:
+ return -0x8000
+ elif size == 4:
+ return -0x80000000
+
+
+def _get_clipfn(size, signed=True):
+ maxval = _get_maxval(size, signed)
+ minval = _get_minval(size, signed)
+ return lambda val: __builtin__.max(min(val, maxval), minval)
+
+
+def _overflow(val, size, signed=True):
+ minval = _get_minval(size, signed)
+ maxval = _get_maxval(size, signed)
+ if minval <= val <= maxval:
+ return val
+
+ bits = size * 8
+ if signed:
+ offset = 2**(bits-1)
+ return ((val + offset) % (2**bits)) - offset
+ else:
+ return val % (2**bits)
+
+
def getsample(cp, size, i):
_check_params(len(cp), size)
if not (0 <= i < len(cp) / size):
raise error("Index out of range")
- if size == 1:
- return struct.unpack_from("B", buffer(cp)[i:])[0]
- elif size == 2:
- return struct.unpack_from("H", buffer(cp)[i * 2:])[0]
- elif size == 4:
- return struct.unpack_from("I", buffer(cp)[i * 4:])[0]
+ return _get_sample(cp, size, i)
+
+
+def max(cp, size):
+ _check_params(len(cp), size)
+
+ if len(cp) == 0:
+ return 0
+
+ return __builtin__.max(abs(sample) for sample in _get_samples(cp, size))
+
+
+def minmax(cp, size):
+ _check_params(len(cp), size)
+
+ max_sample, min_sample = 0, 0
+ for sample in _get_samples(cp, size):
+ max_sample = __builtin__.max(sample, max_sample)
+ min_sample = __builtin__.min(sample, min_sample)
+
+ return min_sample, max_sample
+
+
+def avg(cp, size):
+ _check_params(len(cp), size)
+ sample_count = _sample_count(cp, size)
+ if sample_count == 0:
+ return 0
+ return sum(_get_samples(cp, size)) / sample_count
+
+
+def rms(cp, size):
+ _check_params(len(cp), size)
+
+ sample_count = _sample_count(cp, size)
+ if sample_count == 0:
+ return 0
+
+ sum_squares = sum(sample**2 for sample in _get_samples(cp, size))
+ return int(math.sqrt(sum_squares / sample_count))
+
+
+def _sum2(cp1, cp2, length):
+ size = 2
+ total = 0
+ for i in range(length):
+ total += getsample(cp1, size, i) * getsample(cp2, size, i)
+ return total
+
+
+def findfit(cp1, cp2):
+ size = 2
+
+ if len(cp1) % 2 != 0 or len(cp2) % 2 != 0:
+ raise error("Strings should be even-sized")
+
+ if len(cp1) < len(cp2):
+ raise error("First sample should be longer")
+
+ len1 = _sample_count(cp1, size)
+ len2 = _sample_count(cp2, size)
+
+ sum_ri_2 = _sum2(cp2, cp2, len2)
+ sum_aij_2 = _sum2(cp1, cp1, len2)
+ sum_aij_ri = _sum2(cp1, cp2, len2)
+
+ result = (sum_ri_2 * sum_aij_2 - sum_aij_ri * sum_aij_ri) / sum_aij_2
+
+ best_result = result
+ best_i = 0
+
+ for i in range(1, len1 - len2 + 1):
+ aj_m1 = _get_sample(cp1, size, i - 1)
+ aj_lm1 = _get_sample(cp1, size, i + len2 - 1)
+
+ sum_aij_2 += aj_lm1**2 - aj_m1**2
+ sum_aij_ri = _sum2(buffer(cp1)[i*size:], cp2, len2)
+
+ result = (sum_ri_2 * sum_aij_2 - sum_aij_ri * sum_aij_ri) / sum_aij_2
+
+ if result < best_result:
+ best_result = result
+ best_i = i
+
+ factor = _sum2(buffer(cp1)[best_i*size:], cp2, len2) / sum_ri_2
+
+ return best_i, factor
+
+
+def findfactor(cp1, cp2):
+ size = 2
+
+ if len(cp1) % 2 != 0:
+ raise error("Strings should be even-sized")
+
+ if len(cp1) != len(cp2):
+ raise error("Samples should be same size")
+
+ sample_count = _sample_count(cp1, size)
+
+ sum_ri_2 = _sum2(cp2, cp2, sample_count)
+ sum_aij_ri = _sum2(cp1, cp2, sample_count)
+
+ return sum_aij_ri / sum_ri_2
+
+
+def findmax(cp, len2):
+ size = 2
+ sample_count = _sample_count(cp, size)
+
+ if len(cp) % 2 != 0:
+ raise error("Strings should be even-sized")
+
+ if len2 < 0 or sample_count < len2:
+ raise error("Input sample should be longer")
+
+ if sample_count == 0:
+ return 0
+
+ result = _sum2(cp, cp, len2)
+ best_result = result
+ best_i = 0
+
+ for i in range(1, sample_count - len2 + 1):
+ sample_leaving_window = getsample(cp, size, i - 1)
+ sample_entering_window = getsample(cp, size, i + len2 - 1)
+
+ result -= sample_leaving_window**2
+ result += sample_entering_window**2
+
+ if result > best_result:
+ best_result = result
+ best_i = i
+
+ return best_i
+
+
+def avgpp(cp, size):
+ _check_params(len(cp), size)
+ sample_count = _sample_count(cp, size)
+
+ prevextremevalid = False
+ prevextreme = None
+ avg = 0
+ nextreme = 0
+
+ prevval = getsample(cp, size, 0)
+ val = getsample(cp, size, 1)
+
+ prevdiff = val - prevval
+
+ for i in range(1, sample_count):
+ val = getsample(cp, size, i)
+ diff = val - prevval
+
+ if diff * prevdiff < 0:
+ if prevextremevalid:
+ avg += abs(prevval - prevextreme)
+ nextreme += 1
+
+ prevextremevalid = True
+ prevextreme = prevval
+
+ prevval = val
+ if diff != 0:
+ prevdiff = diff
+
+ if nextreme == 0:
+ return 0
+
+ return avg / nextreme
+
+
+def maxpp(cp, size):
+ _check_params(len(cp), size)
+ sample_count = _sample_count(cp, size)
+
+ prevextremevalid = False
+ prevextreme = None
+ max = 0
+
+ prevval = getsample(cp, size, 0)
+ val = getsample(cp, size, 1)
+
+ prevdiff = val - prevval
+
+ for i in range(1, sample_count):
+ val = getsample(cp, size, i)
+ diff = val - prevval
+
+ if diff * prevdiff < 0:
+ if prevextremevalid:
+ extremediff = abs(prevval - prevextreme)
+ if extremediff > max:
+ max = extremediff
+ prevextremevalid = True
+ prevextreme = prevval
+
+ prevval = val
+ if diff != 0:
+ prevdiff = diff
+
+ return max
+
+
+def cross(cp, size):
+ _check_params(len(cp), size)
+
+ crossings = 0
+ last_sample = 0
+ for sample in _get_samples(cp, size):
+ if sample <= 0 < last_sample or sample >= 0 > last_sample:
+ crossings += 1
+ last_sample = sample
+
+ return crossings
+
+
+def mul(cp, size, factor):
+ _check_params(len(cp), size)
+ clip = _get_clipfn(size)
+
+ result = create_string_buffer(len(cp))
+
+ for i, sample in enumerate(_get_samples(cp, size)):
+ sample = clip(int(sample * factor))
+ _put_sample(result, size, i, sample)
+
+ return result.raw
+
+
+def tomono(cp, size, fac1, fac2):
+ _check_params(len(cp), size)
+ clip = _get_clipfn(size)
+
+ sample_count = _sample_count(cp, size)
+
+ result = create_string_buffer(len(cp) / 2)
+
+ for i in range(0, sample_count, 2):
+ l_sample = getsample(cp, size, i)
+ r_sample = getsample(cp, size, i + 1)
+
+ sample = (l_sample * fac1) + (r_sample * fac2)
+ sample = clip(sample)
+
+ _put_sample(result, size, i / 2, sample)
+
+ return result.raw
+
+
+def tostereo(cp, size, fac1, fac2):
+ _check_params(len(cp), size)
+
+ sample_count = _sample_count(cp, size)
+
+ result = create_string_buffer(len(cp) * 2)
+ clip = _get_clipfn(size)
+
+ for i in range(sample_count):
+ sample = _get_sample(cp, size, i)
+
+ l_sample = clip(sample * fac1)
+ r_sample = clip(sample * fac2)
+
+ _put_sample(result, size, i * 2, l_sample)
+ _put_sample(result, size, i * 2 + 1, r_sample)
+
+ return result.raw
+
+
+def add(cp1, cp2, size):
+ _check_params(len(cp1), size)
+
+ if len(cp1) != len(cp2):
+ raise error("Lengths should be the same")
+
+ clip = _get_clipfn(size)
+ sample_count = _sample_count(cp1, size)
+ result = create_string_buffer(len(cp1))
+
+ for i in range(sample_count):
+ sample1 = getsample(cp1, size, i)
+ sample2 = getsample(cp2, size, i)
+
+ sample = clip(sample1 + sample2)
+
+ _put_sample(result, size, i, sample)
+
+ return result.raw
+
+
+def bias(cp, size, bias):
+ _check_params(len(cp), size)
+
+ result = create_string_buffer(len(cp))
+
+ for i, sample in enumerate(_get_samples(cp, size)):
+ sample = _overflow(sample + bias, size)
+ _put_sample(result, size, i, sample)
+
+ return result.raw
+
+
+def reverse(cp, size):
+ _check_params(len(cp), size)
+ sample_count = _sample_count(cp, size)
+
+ result = create_string_buffer(len(cp))
+ for i, sample in enumerate(_get_samples(cp, size)):
+ _put_sample(result, size, sample_count - i - 1, sample)
+
+ return result.raw
+
+
+def lin2lin(cp, size, size2):
+ _check_params(len(cp), size)
+ _check_size(size2)
+
+ if size == size2:
+ return cp
+
+ new_len = (len(cp) / size) * size2
+
+ result = create_string_buffer(new_len)
+
+ for i in range(_sample_count(cp, size)):
+ sample = _get_sample(cp, size, i)
+ if size < size2:
+ sample = sample << (4 * size2 / size)
+ elif size > size2:
+ sample = sample >> (4 * size / size2)
+
+ sample = _overflow(sample, size2)
+
+ _put_sample(result, size2, i, sample)
+
+ return result.raw
+
+
+def ratecv(cp, size, nchannels, inrate, outrate, state, weightA=1, weightB=0):
+ _check_params(len(cp), size)
+ if nchannels < 1:
+ raise error("# of channels should be >= 1")
+
+ bytes_per_frame = size * nchannels
+ frame_count = len(cp) / bytes_per_frame
+
+ if bytes_per_frame / nchannels != size:
+ raise OverflowError("width * nchannels too big for a C int")
+
+ if weightA < 1 or weightB < 0:
+ raise error("weightA should be >= 1, weightB should be >= 0")
+
+ if len(cp) % bytes_per_frame != 0:
+ raise error("not a whole number of frames")
+
+ if inrate <= 0 or outrate <= 0:
+ raise error("sampling rate not > 0")
+
+ d = gcd(inrate, outrate)
+ inrate /= d
+ outrate /= d
+
+ prev_i = [0] * nchannels
+ cur_i = [0] * nchannels
+
+ if state is None:
+ d = -outrate
+ else:
+ d, samps = state
+
+ if len(samps) != nchannels:
+ raise error("illegal state argument")
+
+ prev_i, cur_i = zip(*samps)
+ prev_i, cur_i = list(prev_i), list(cur_i)
+
+ q = frame_count / inrate
+ ceiling = (q + 1) * outrate
+ nbytes = ceiling * bytes_per_frame
+
+ result = create_string_buffer(nbytes)
+
+ samples = _get_samples(cp, size)
+ out_i = 0
+ while True:
+ while d < 0:
+ if frame_count == 0:
+ samps = zip(prev_i, cur_i)
+ retval = result.raw
+
+ # slice off extra bytes
+ trim_index = (out_i * bytes_per_frame) - len(retval)
+ retval = buffer(retval)[:trim_index]
+
+ return (retval, (d, tuple(samps)))
+
+ for chan in range(nchannels):
+ prev_i[chan] = cur_i[chan]
+ cur_i[chan] = samples.next()
+
+ cur_i[chan] = (
+ (weightA * cur_i[chan] + weightB * prev_i[chan])
+ / (weightA + weightB)
+ )
+
+ frame_count -= 1
+ d += outrate
+
+ while d >= 0:
+ for chan in range(nchannels):
+ cur_o = (
+ (prev_i[chan] * d + cur_i[chan] * (outrate - d))
+ / outrate
+ )
+ _put_sample(result, size, out_i, _overflow(cur_o, size))
+ out_i += 1
+ d -= inrate
+
+
+def lin2ulaw(cp, size):
+ raise NotImplementedError()
+
+
+def ulaw2lin(cp, size):
+ raise NotImplementedError()
+
+
+def lin2alaw(cp, size):
+ raise NotImplementedError()
+
+
+def alaw2lin(cp, size):
+ raise NotImplementedError()
+
+
+def lin2adpcm(cp, size, state):
+ raise NotImplementedError()
+
+
+def adpcm2lin(cp, size, state):
+ raise NotImplementedError()
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -78,3 +78,7 @@
.. branch: optimize-int-and
Optimize away INT_AND with constant mask of 1s that fully cover the bitrange
of other operand.
+
+.. branch: bounds-int-add-or
+Propagate appropriate bounds through INT_(OR|XOR|AND) operations if the
+operands are positive to kill some guards
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -964,8 +964,7 @@
# ----------------------- reduce -------------------------------
- def _reduce_ufunc_impl(ufunc_name, promote_to_largest=False,
- cumulative=False):
+ def _reduce_ufunc_impl(ufunc_name, cumulative=False):
@unwrap_spec(keepdims=bool)
def impl(self, space, w_axis=None, w_dtype=None, w_out=None, keepdims=False):
if space.is_none(w_out):
@@ -976,13 +975,11 @@
else:
out = w_out
return getattr(interp_ufuncs.get(space), ufunc_name).reduce(
- space, self, promote_to_largest, w_axis,
- keepdims, out, w_dtype, cumulative=cumulative)
- return func_with_new_name(impl, "reduce_%s_impl_%d_%d" % (ufunc_name,
- promote_to_largest, cumulative))
+ space, self, w_axis, keepdims, out, w_dtype, cumulative=cumulative)
+ return func_with_new_name(impl, "reduce_%s_impl_%d" % (ufunc_name, cumulative))
- descr_sum = _reduce_ufunc_impl("add", True)
- descr_prod = _reduce_ufunc_impl("multiply", True)
+ descr_sum = _reduce_ufunc_impl("add")
+ descr_prod = _reduce_ufunc_impl("multiply")
descr_max = _reduce_ufunc_impl("maximum")
descr_min = _reduce_ufunc_impl("minimum")
descr_all = _reduce_ufunc_impl('logical_and')
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -19,12 +19,15 @@
class W_Ufunc(W_Root):
- _immutable_fields_ = ["name", "promote_to_float", "promote_bools", "identity",
- "int_only", "allow_bool", "allow_complex", "complex_to_float"]
+ _immutable_fields_ = [
+ "name", "promote_to_largest", "promote_to_float", "promote_bools",
+ "identity", "int_only", "allow_bool", "allow_complex", "complex_to_float"
+ ]
- def __init__(self, name, promote_to_float, promote_bools, identity,
- int_only, allow_bool, allow_complex, complex_to_float):
+ def __init__(self, name, promote_to_largest, promote_to_float, promote_bools,
+ identity, int_only, allow_bool, allow_complex, complex_to_float):
self.name = name
+ self.promote_to_largest = promote_to_largest
self.promote_to_float = promote_to_float
self.promote_bools = promote_bools
self.identity = identity
@@ -88,9 +91,8 @@
'output must be an array'))
else:
out = w_out
- return self.reduce(space, w_obj, False, #do not promote_to_largest
- w_axis, True, #keepdims must be true
- out, w_dtype, cumulative=True)
+ return self.reduce(space, w_obj, w_axis, True, #keepdims must be true
+ out, w_dtype, cumulative=True)
@unwrap_spec(skipna=bool, keepdims=bool)
def descr_reduce(self, space, w_obj, w_axis=None, w_dtype=None,
@@ -154,15 +156,13 @@
out = None
elif not isinstance(w_out, W_NDimArray):
raise OperationError(space.w_TypeError, space.wrap(
- 'output must be an array'))
+ 'output must be an array'))
else:
out = w_out
- promote_to_largest = False
- return self.reduce(space, w_obj, promote_to_largest, w_axis, keepdims, out,
- w_dtype)
+ return self.reduce(space, w_obj, w_axis, keepdims, out, w_dtype)
- def reduce(self, space, w_obj, promote_to_largest, w_axis,
- keepdims=False, out=None, dtype=None, cumulative=False):
+ def reduce(self, space, w_obj, w_axis, keepdims=False, out=None, dtype=None,
+ cumulative=False):
if self.argcount != 2:
raise OperationError(space.w_ValueError, space.wrap("reduce only "
"supported for binary functions"))
@@ -185,8 +185,8 @@
dtype = find_unaryop_result_dtype(
space, obj.get_dtype(),
promote_to_float=self.promote_to_float,
- promote_to_largest=promote_to_largest,
- promote_bools=True
+ promote_to_largest=self.promote_to_largest,
+ promote_bools=self.promote_bools,
)
if self.identity is None:
for i in range(shapelen):
@@ -263,18 +263,18 @@
return self._outer(space, __args__)
def _outer(self, space, __args__):
- raise OperationError(space.w_ValueError,
- space.wrap("outer product only supported for binary functions"))
+ raise OperationError(space.w_ValueError, space.wrap(
+ "outer product only supported for binary functions"))
class W_Ufunc1(W_Ufunc):
_immutable_fields_ = ["func", "bool_result"]
argcount = 1
- def __init__(self, func, name, promote_to_float=False, promote_bools=False,
- identity=None, bool_result=False, int_only=False,
+ def __init__(self, func, name, promote_to_largest=False, promote_to_float=False,
+ promote_bools=False, identity=None, bool_result=False, int_only=False,
allow_bool=True, allow_complex=True, complex_to_float=False):
- W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity,
- int_only, allow_bool, allow_complex, complex_to_float)
+ W_Ufunc.__init__(self, name, promote_to_largest, promote_to_float, promote_bools,
+ identity, int_only, allow_bool, allow_complex, complex_to_float)
self.func = func
self.bool_result = bool_result
@@ -336,11 +336,11 @@
_immutable_fields_ = ["func", "comparison_func", "done_func"]
argcount = 2
- def __init__(self, func, name, promote_to_float=False, promote_bools=False,
- identity=None, comparison_func=False, int_only=False,
+ def __init__(self, func, name, promote_to_largest=False, promote_to_float=False,
+ promote_bools=False, identity=None, comparison_func=False, int_only=False,
allow_bool=True, allow_complex=True, complex_to_float=False):
- W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity,
- int_only, allow_bool, allow_complex, complex_to_float)
+ W_Ufunc.__init__(self, name, promote_to_largest, promote_to_float, promote_bools,
+ identity, int_only, allow_bool, allow_complex, complex_to_float)
self.func = func
self.comparison_func = comparison_func
if name == 'logical_and':
@@ -606,9 +606,9 @@
def __init__(self, space):
"NOT_RPYTHON"
for ufunc_def in [
- ("add", "add", 2, {"identity": 0}),
+ ("add", "add", 2, {"identity": 0, "promote_to_largest": True}),
("subtract", "sub", 2),
- ("multiply", "mul", 2, {"identity": 1}),
+ ("multiply", "mul", 2, {"identity": 1, "promote_to_largest": True}),
("bitwise_and", "bitwise_and", 2, {"identity": 1,
"int_only": True}),
("bitwise_or", "bitwise_or", 2, {"identity": 0,
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -756,7 +756,7 @@
raises(ValueError, maximum.reduce, zeros((2, 0)), axis=1)
def test_reduce_1d(self):
- from numpypy import add, maximum, less
+ from numpypy import array, add, maximum, less, float16, complex64
assert less.reduce([5, 4, 3, 2, 1])
assert add.reduce([1, 2, 3]) == 6
@@ -764,6 +764,12 @@
assert maximum.reduce([1, 2, 3]) == 3
raises(ValueError, maximum.reduce, [])
+ assert add.reduce(array([True, False] * 200)) == 200
+ assert add.reduce(array([True, False] * 200, dtype='int8')) == 200
+ assert add.reduce(array([True, False] * 200), dtype='int8') == -56
+ assert type(add.reduce(array([True, False] * 200, dtype='float16'))) is float16
+ assert type(add.reduce(array([True, False] * 200, dtype='complex64'))) is complex64
+
def test_reduceND(self):
from numpypy import add, arange
a = arange(12).reshape(3, 4)
@@ -1025,7 +1031,7 @@
assert logaddexp2(float('inf'), float('inf')) == float('inf')
def test_accumulate(self):
- from numpypy import add, multiply, arange
+ from numpypy import add, subtract, multiply, divide, arange, dtype
assert (add.accumulate([2, 3, 5]) == [2, 5, 10]).all()
assert (multiply.accumulate([2, 3, 5]) == [2, 6, 30]).all()
a = arange(4).reshape(2,2)
@@ -1041,6 +1047,10 @@
print b
assert (b == [[0, 0, 1], [1, 3, 5]]).all()
assert b.dtype == int
+ assert add.accumulate([True]*200)[-1] == 200
+ assert add.accumulate([True]*200).dtype == dtype('int')
+ assert subtract.accumulate([True]*200).dtype == dtype('bool')
+ assert divide.accumulate([True]*200).dtype == dtype('int8')
def test_noncommutative_reduce_accumulate(self):
import numpypy as np
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -7,6 +7,7 @@
CONST_0, MODE_ARRAY, MODE_STR, MODE_UNICODE)
from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
from rpython.jit.metainterp.resoperation import rop
+from rpython.jit.backend.llsupport import symbolic
def get_integer_min(is_unsigned, byte_size):
@@ -23,6 +24,17 @@
return (1 << ((byte_size << 3) - 1)) - 1
+def next_pow2_m1(n):
+ """Calculate next power of 2 greater than n minus one."""
+ n |= n >> 1
+ n |= n >> 2
+ n |= n >> 4
+ n |= n >> 8
+ n |= n >> 16
+ n |= n >> 32
+ return n
+
+
class OptIntBounds(Optimization):
"""Keeps track of the bounds placed on integers by guards and remove
redundant guards"""
@@ -56,17 +68,24 @@
optimize_GUARD_FALSE = optimize_GUARD_TRUE
optimize_GUARD_VALUE = optimize_GUARD_TRUE
- def optimize_INT_XOR(self, op):
+ def optimize_INT_OR_or_XOR(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
if v1 is v2:
- self.make_constant_int(op.result, 0)
+ if op.getopnum() == rop.INT_OR:
+ self.make_equal_to(op.result, v1)
+ else:
+ self.make_constant_int(op.result, 0)
return
self.emit_operation(op)
if v1.intbound.known_ge(IntBound(0, 0)) and \
v2.intbound.known_ge(IntBound(0, 0)):
r = self.getvalue(op.result)
- r.intbound.make_ge(IntLowerBound(0))
+ mostsignificant = v1.intbound.upper | v2.intbound.upper
+ r.intbound.intersect(IntBound(0, next_pow2_m1(mostsignificant)))
+
+ optimize_INT_OR = optimize_INT_OR_or_XOR
+ optimize_INT_XOR = optimize_INT_OR_or_XOR
def optimize_INT_AND(self, op):
v1 = self.getvalue(op.getarg(0))
@@ -82,6 +101,10 @@
val = v1.box.getint()
if val >= 0:
r.intbound.intersect(IntBound(0, val))
+ elif v1.intbound.known_ge(IntBound(0, 0)) and \
+ v2.intbound.known_ge(IntBound(0, 0)):
+ lesser = min(v1.intbound.upper, v2.intbound.upper)
+ r.intbound.intersect(IntBound(0, next_pow2_m1(lesser)))
def optimize_INT_SUB(self, op):
v1 = self.getvalue(op.getarg(0))
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbounds.py b/rpython/jit/metainterp/optimizeopt/test/test_intbounds.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/metainterp/optimizeopt/test/test_intbounds.py
@@ -0,0 +1,12 @@
+from rpython.jit.metainterp.optimizeopt.intbounds import next_pow2_m1
+
+
+def test_next_pow2_m1():
+ assert next_pow2_m1(0) == 0
+ assert next_pow2_m1(1) == 1
+ assert next_pow2_m1(7) == 7
+ assert next_pow2_m1(256) == 511
+ assert next_pow2_m1(255) == 255
+ assert next_pow2_m1(80) == 127
+ assert next_pow2_m1((1 << 32) - 5) == (1 << 32) - 1
+ assert next_pow2_m1((1 << 64) - 1) == (1 << 64) - 1
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -5326,6 +5326,114 @@
"""
self.optimize_loop(ops, ops)
+ def test_int_and_cmp_above_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_and(i0, i1)
+ i3 = int_le(i2, 255)
+ guard_true(i3) []
+ jump(i2)
+ """
+
+ expected = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_and(i0, i1)
+ jump(i2)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_and_cmp_below_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_and(i0, i1)
+ i3 = int_lt(i2, 255)
+ guard_true(i3) []
+ jump(i2)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_int_or_cmp_above_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_or(i0, i1)
+ i3 = int_le(i2, 65535)
+ guard_true(i3) []
+ jump(i2)
+ """
+
+ expected = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_or(i0, i1)
+ jump(i2)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_or_cmp_below_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_or(i0, i1)
+ i3 = int_lt(i2, 65535)
+ guard_true(i3) []
+ jump(i2)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_int_xor_cmp_above_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_xor(i0, i1)
+ i3 = int_le(i2, 65535)
+ guard_true(i3) []
+ jump(i2)
+ """
+
+ expected = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_xor(i0, i1)
+ jump(i2)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_int_xor_cmp_below_bounds(self):
+ ops = """
+ [p0,p1]
+ i0 = getarrayitem_gc(p0, 0, descr=chararraydescr)
+ i1 = getarrayitem_gc(p1, 0, descr=u2arraydescr)
+ i2 = int_xor(i0, i1)
+ i3 = int_lt(i2, 65535)
+ guard_true(i3) []
+ jump(i2)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_int_or_same_arg(self):
+ ops = """
+ [i0]
+ i1 = int_or(i0, i0)
+ jump(i1)
+ """
+ expected = """
+ [i0]
+ jump(i0)
+ """
+ self.optimize_loop(ops, expected)
+
class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
pass
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -1,6 +1,6 @@
import py, random
-from rpython.rtyper.lltypesystem import lltype, llmemory, rclass, rstr
+from rpython.rtyper.lltypesystem import lltype, llmemory, rclass, rstr, rffi
from rpython.rtyper.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
from rpython.rtyper.rclass import FieldListAccessor, IR_QUASIIMMUTABLE
@@ -208,6 +208,8 @@
chararray = lltype.GcArray(lltype.Char)
chararraydescr = cpu.arraydescrof(chararray)
+ u2array = lltype.GcArray(rffi.USHORT)
+ u2arraydescr = cpu.arraydescrof(u2array)
# array of structs (complex data)
complexarray = lltype.GcArray(
More information about the pypy-commit
mailing list