[pypy-commit] pypy stdlib-2.7.9: merge default into branch
mattip
noreply at buildbot.pypy.org
Sat Feb 14 20:26:49 CET 2015
Author: mattip <matti.picus at gmail.com>
Branch: stdlib-2.7.9
Changeset: r75874:efdb6e5046b6
Date: 2015-02-14 21:23 +0200
http://bitbucket.org/pypy/pypy/changeset/efdb6e5046b6/
Log: merge default into branch
diff too long, truncating to 2000 out of 3194 lines
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
@@ -2,7 +2,7 @@
import sys
import unittest
import struct
-from test.test_support import run_unittest, impl_detail
+from test.test_support import run_unittest
formats = {
@@ -183,7 +183,6 @@
self.assertEqual(audioop.lin2lin(datas[4], 4, 2),
packs[2](0, 0x1234, 0x4567, -0x4568, 0x7fff, -0x8000, -1))
- @impl_detail(pypy=False)
def test_adpcm2lin(self):
self.assertEqual(audioop.adpcm2lin(b'\x07\x7f\x7f', 1, None),
(b'\x00\x00\x00\xff\x00\xff', (-179, 40)))
@@ -198,7 +197,6 @@
self.assertEqual(audioop.adpcm2lin(b'\0' * 5, w, None),
(b'\0' * w * 10, (0, 0)))
- @impl_detail(pypy=False)
def test_lin2adpcm(self):
self.assertEqual(audioop.lin2adpcm(datas[1], 1, None),
(b'\x07\x7f\x7f', (-221, 39)))
@@ -212,7 +210,6 @@
self.assertEqual(audioop.lin2adpcm(b'\0' * w * 10, w, None),
(b'\0' * 5, (0, 0)))
- @impl_detail(pypy=False)
def test_lin2alaw(self):
self.assertEqual(audioop.lin2alaw(datas[1], 1),
b'\xd5\x87\xa4\x24\xaa\x2a\x5a')
@@ -221,7 +218,6 @@
self.assertEqual(audioop.lin2alaw(datas[4], 4),
b'\xd5\x87\xa4\x24\xaa\x2a\x55')
- @impl_detail(pypy=False)
def test_alaw2lin(self):
encoded = b'\x00\x03\x24\x2a\x51\x54\x55\x58\x6b\x71\x7f'\
b'\x80\x83\xa4\xaa\xd1\xd4\xd5\xd8\xeb\xf1\xff'
@@ -236,7 +232,6 @@
decoded = audioop.alaw2lin(encoded, w)
self.assertEqual(audioop.lin2alaw(decoded, w), encoded)
- @impl_detail(pypy=False)
def test_lin2ulaw(self):
self.assertEqual(audioop.lin2ulaw(datas[1], 1),
b'\xff\xad\x8e\x0e\x80\x00\x67')
@@ -245,7 +240,6 @@
self.assertEqual(audioop.lin2ulaw(datas[4], 4),
b'\xff\xad\x8e\x0e\x80\x00\x7e')
- @impl_detail(pypy=False)
def test_ulaw2lin(self):
encoded = b'\x00\x0e\x28\x3f\x57\x6a\x76\x7c\x7e\x7f'\
b'\x80\x8e\xa8\xbf\xd7\xea\xf6\xfc\xfe\xff'
@@ -360,7 +354,6 @@
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:
@@ -385,7 +378,6 @@
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'abcdefgh'
state = None
diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py
--- a/lib_pypy/_ctypes/array.py
+++ b/lib_pypy/_ctypes/array.py
@@ -9,7 +9,7 @@
def __new__(self, name, cls, typedict):
res = type.__new__(self, name, cls, typedict)
if '_type_' in typedict:
- ffiarray = _rawffi.Array(typedict['_type_']._ffishape)
+ ffiarray = _rawffi.Array(typedict['_type_']._ffishape_)
res._ffiarray = ffiarray
subletter = getattr(typedict['_type_'], '_type_', None)
if subletter == 'c':
@@ -58,8 +58,8 @@
res.value = property(getvalue, setvalue)
if '_length_' in typedict:
- res._ffishape = (ffiarray, typedict['_length_'])
- res._fficompositesize = res._sizeofinstances()
+ res._ffishape_ = (ffiarray, typedict['_length_'])
+ res._fficompositesize_ = res._sizeofinstances()
else:
res._ffiarray = None
return res
@@ -156,7 +156,7 @@
class Array(_CData):
__metaclass__ = ArrayMeta
- _ffiargshape = 'P'
+ _ffiargshape_ = 'P'
def __init__(self, *args):
if not hasattr(self, '_buffer'):
@@ -191,13 +191,13 @@
if ensure_objects(cobj) is not None:
store_reference(self, index, cobj._objects)
arg = cobj._get_buffer_value()
- if self._type_._fficompositesize is None:
+ if self._type_._fficompositesize_ is None:
self._buffer[index] = arg
# something more sophisticated, cannot set field directly
else:
from ctypes import memmove
dest = self._buffer.itemaddress(index)
- memmove(dest, arg, self._type_._fficompositesize)
+ memmove(dest, arg, self._type_._fficompositesize_)
def __getitem__(self, index):
if isinstance(index, slice):
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -52,7 +52,7 @@
def get_ffi_argtype(self):
if self._ffiargtype:
return self._ffiargtype
- self._ffiargtype = _shape_to_ffi_type(self._ffiargshape)
+ self._ffiargtype = _shape_to_ffi_type(self._ffiargshape_)
return self._ffiargtype
def _CData_output(self, resbuffer, base=None, index=-1):
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -65,9 +65,9 @@
_restype_ = None
_errcheck_ = None
_flags_ = 0
- _ffiargshape = 'P'
- _ffishape = 'P'
- _fficompositesize = None
+ _ffiargshape_ = 'P'
+ _ffishape_ = 'P'
+ _fficompositesize_ = None
_ffiarray = _rawffi.Array('P')
_needs_free = False
callable = None
@@ -98,7 +98,7 @@
argtypes = property(_getargtypes, _setargtypes)
def _check_argtypes_for_fastpath(self):
- if all([hasattr(argtype, '_ffiargshape') for argtype in self._argtypes_]):
+ if all([hasattr(argtype, '_ffiargshape_') for argtype in self._argtypes_]):
fastpath_cls = make_fastpath_subclass(self.__class__)
fastpath_cls.enable_fastpath_maybe(self)
@@ -135,7 +135,7 @@
_flag = flag & PARAMFLAG_COMBINED
if _flag == PARAMFLAG_FOUT:
typ = self._argtypes_[idx]
- if getattr(typ, '_ffiargshape', None) not in ('P', 'z', 'Z'):
+ if getattr(typ, '_ffiargshape_', None) not in ('P', 'z', 'Z'):
raise TypeError(
"'out' parameter %d must be a pointer type, not %s"
% (idx+1, type(typ).__name__)
@@ -182,11 +182,11 @@
def _ffishapes(self, args, restype):
if args is None:
args = []
- argtypes = [arg._ffiargshape for arg in args]
+ argtypes = [arg._ffiargshape_ for arg in args]
if restype is not None:
if not isinstance(restype, SimpleType):
raise TypeError("invalid result type for callback function")
- restype = restype._ffiargshape
+ restype = restype._ffiargshape_
else:
restype = 'O' # void
return argtypes, restype
@@ -599,7 +599,7 @@
if self._is_primitive(restype) and not restype._is_pointer_like():
return result
#
- shape = restype._ffishape
+ shape = restype._ffishape_
if is_struct_shape(shape):
buf = result
else:
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -21,9 +21,9 @@
size = _rawffi.sizeof('P'),
align = _rawffi.alignment('P'),
length = 1,
- _ffiargshape = 'P',
- _ffishape = 'P',
- _fficompositesize = None,
+ _ffiargshape_ = 'P',
+ _ffishape_ = 'P',
+ _fficompositesize_ = None,
)
# XXX check if typedict['_type_'] is any sane
# XXX remember about paramfunc
diff --git a/lib_pypy/_ctypes/primitive.py b/lib_pypy/_ctypes/primitive.py
--- a/lib_pypy/_ctypes/primitive.py
+++ b/lib_pypy/_ctypes/primitive.py
@@ -117,9 +117,9 @@
default = TP_TO_DEFAULT[tp]
ffiarray = _rawffi.Array(tp)
result = type.__new__(self, name, bases, dct)
- result._ffiargshape = tp
- result._ffishape = tp
- result._fficompositesize = None
+ result._ffiargshape_ = tp
+ result._ffishape_ = tp
+ result._fficompositesize_ = None
result._ffiarray = ffiarray
if tp == 'z':
# c_char_p
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -36,9 +36,9 @@
rawfields = []
for f in all_fields:
if len(f) > 2:
- rawfields.append((f[0], f[1]._ffishape, f[2]))
+ rawfields.append((f[0], f[1]._ffishape_, f[2]))
else:
- rawfields.append((f[0], f[1]._ffishape))
+ rawfields.append((f[0], f[1]._ffishape_))
_set_shape(self, rawfields, self._is_union)
@@ -48,8 +48,8 @@
value = field[1]
is_bitfield = (len(field) == 3)
fields[name] = Field(name,
- self._ffistruct.fieldoffset(name),
- self._ffistruct.fieldsize(name),
+ self._ffistruct_.fieldoffset(name),
+ self._ffistruct_.fieldsize(name),
value, i, is_bitfield)
if anonymous_fields:
@@ -58,9 +58,9 @@
name = field[0]
value = field[1]
is_bitfield = (len(field) == 3)
- startpos = self._ffistruct.fieldoffset(name)
+ startpos = self._ffistruct_.fieldoffset(name)
if name in anonymous_fields:
- for subname in value._names:
+ for subname in value._names_:
resnames.append(subname)
subfield = getattr(value, subname)
relpos = startpos + subfield.offset
@@ -71,7 +71,7 @@
else:
resnames.append(name)
names = resnames
- self._names = names
+ self._names_ = names
for name, field in fields.items():
setattr(self, name, field)
@@ -114,19 +114,19 @@
elif ensure_objects(cobj) is not None:
store_reference(obj, key, cobj._objects)
arg = cobj._get_buffer_value()
- if fieldtype._fficompositesize is not None:
+ if fieldtype._fficompositesize_ is not None:
from ctypes import memmove
dest = obj._buffer.fieldaddress(self.name)
- memmove(dest, arg, fieldtype._fficompositesize)
+ memmove(dest, arg, fieldtype._fficompositesize_)
else:
obj._buffer.__setattr__(self.name, arg)
def _set_shape(tp, rawfields, is_union=False):
- tp._ffistruct = _rawffi.Structure(rawfields, is_union,
+ tp._ffistruct_ = _rawffi.Structure(rawfields, is_union,
getattr(tp, '_pack_', 0))
- tp._ffiargshape = tp._ffishape = (tp._ffistruct, 1)
- tp._fficompositesize = tp._ffistruct.size
+ tp._ffiargshape_ = tp._ffishape_ = (tp._ffistruct_, 1)
+ tp._fficompositesize_ = tp._ffistruct_.size
def struct_setattr(self, name, value):
@@ -181,16 +181,16 @@
address = address.buffer
# fix the address: turn it into as unsigned, in case it is negative
address = address & (sys.maxint * 2 + 1)
- instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address)
+ instance.__dict__['_buffer'] = self._ffistruct_.fromaddress(address)
return instance
def _sizeofinstances(self):
- if not hasattr(self, '_ffistruct'):
+ if not hasattr(self, '_ffistruct_'):
return 0
- return self._ffistruct.size
+ return self._ffistruct_.size
def _alignmentofinstances(self):
- return self._ffistruct.alignment
+ return self._ffistruct_.alignment
def from_param(self, value):
if isinstance(value, tuple):
@@ -203,7 +203,7 @@
def _CData_output(self, resarray, base=None, index=-1):
res = StructOrUnion.__new__(self)
- ffistruct = self._ffistruct.fromaddress(resarray.buffer)
+ ffistruct = self._ffistruct_.fromaddress(resarray.buffer)
res.__dict__['_buffer'] = ffistruct
res.__dict__['_base'] = base
res.__dict__['_index'] = index
@@ -224,15 +224,15 @@
self = super(_CData, cls).__new__(cls, *args, **kwds)
if '_abstract_' in cls.__dict__:
raise TypeError("abstract class")
- if hasattr(cls, '_ffistruct'):
- self.__dict__['_buffer'] = self._ffistruct(autofree=True)
+ if hasattr(cls, '_ffistruct_'):
+ self.__dict__['_buffer'] = self._ffistruct_(autofree=True)
return self
def __init__(self, *args, **kwds):
type(self)._make_final()
- if len(args) > len(self._names):
+ if len(args) > len(self._names_):
raise TypeError("too many initializers")
- for name, arg in zip(self._names, args):
+ for name, arg in zip(self._names_, args):
if name in kwds:
raise TypeError("duplicate value for argument %r" % (
name,))
@@ -244,7 +244,7 @@
"""Return a _rawffi array of length 1 whose address is the same as
the address of the field 'name' of self."""
address = self._buffer.fieldaddress(name)
- A = _rawffi.Array(fieldtype._ffishape)
+ A = _rawffi.Array(fieldtype._ffishape_)
return A.fromaddress(address, 1)
def _get_buffer_for_param(self):
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -270,11 +270,14 @@
_ffi.cdef("int sqlite3_enable_load_extension(sqlite3 *db, int onoff);")
if sys.platform.startswith('freebsd'):
+ import os
+ import os.path
+ _localbase = os.environ.get('LOCALBASE', '/usr/local')
_lib = _ffi.verify("""
#include <sqlite3.h>
""", libraries=['sqlite3'],
- include_dirs=['/usr/local/include'],
- library_dirs=['/usr/local/lib']
+ include_dirs=[os.path.join(_localbase, 'include')],
+ library_dirs=[os.path.join(_localbase, 'lib')]
)
else:
_lib = _ffi.verify("""
diff --git a/lib_pypy/audioop.py b/lib_pypy/audioop.py
--- a/lib_pypy/audioop.py
+++ b/lib_pypy/audioop.py
@@ -1,12 +1,11 @@
-from __future__ import division
import __builtin__ as builtins
import math
import struct
from fractions import gcd
-from ctypes import create_string_buffer
+from cffi import FFI
-_buffer = buffer
+_buffer = memoryview
class error(Exception):
@@ -149,7 +148,7 @@
def _sum2(cp1, cp2, length):
size = 2
return sum(getsample(cp1, size, i) * getsample(cp2, size, i)
- for i in range(length))
+ for i in range(length)) + 0.0
def findfit(cp1, cp2):
@@ -328,13 +327,14 @@
_check_params(len(cp), size)
clip = _get_clipfn(size)
- result = create_string_buffer(len(cp))
+ rv = ffi.new("unsigned char[]", len(cp))
+ result = ffi.buffer(rv)
for i, sample in enumerate(_get_samples(cp, size)):
sample = clip(int(sample * factor))
_put_sample(result, size, i, sample)
- return result.raw
+ return result[:]
def tomono(cp, size, fac1, fac2):
@@ -343,7 +343,8 @@
sample_count = _sample_count(cp, size)
- result = create_string_buffer(len(cp) // 2)
+ rv = ffi.new("unsigned char[]", len(cp) // 2)
+ result = ffi.buffer(rv)
for i in range(0, sample_count, 2):
l_sample = getsample(cp, size, i)
@@ -354,7 +355,7 @@
_put_sample(result, size, i // 2, sample)
- return result.raw
+ return result[:]
def tostereo(cp, size, fac1, fac2):
@@ -362,19 +363,9 @@
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
+ rv = ffi.new("unsigned char[]", len(cp) * 2)
+ lib.tostereo(rv, cp, len(cp), size, fac1, fac2)
+ return ffi.buffer(rv)[:]
def add(cp1, cp2, size):
@@ -383,42 +374,34 @@
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
+ rv = ffi.new("unsigned char[]", len(cp1))
+ lib.add(rv, cp1, cp2, len(cp1), size)
+ return ffi.buffer(rv)[:]
def bias(cp, size, bias):
_check_params(len(cp), size)
- result = create_string_buffer(len(cp))
+ rv = ffi.new("unsigned char[]", len(cp))
+ result = ffi.buffer(rv)
for i, sample in enumerate(_get_samples(cp, size)):
sample = _overflow(sample + bias, size)
_put_sample(result, size, i, sample)
- return result.raw
+ return result[:]
def reverse(cp, size):
_check_params(len(cp), size)
sample_count = _sample_count(cp, size)
- result = create_string_buffer(len(cp))
+ rv = ffi.new("unsigned char[]", len(cp))
+ result = ffi.buffer(rv)
for i, sample in enumerate(_get_samples(cp, size)):
_put_sample(result, size, sample_count - i - 1, sample)
- return result.raw
+ return result[:]
def lin2lin(cp, size, size2):
@@ -429,7 +412,8 @@
return cp
new_len = (len(cp) // size) * size2
- result = create_string_buffer(new_len)
+ rv = ffi.new("unsigned char[]", new_len)
+ result = ffi.buffer(rv)
for i in range(_sample_count(cp, size)):
sample = _get_sample(cp, size, i)
@@ -444,7 +428,7 @@
sample = _overflow(sample, size2)
_put_sample(result, size2, i, sample)
- return result.raw
+ return result[:]
def ratecv(cp, size, nchannels, inrate, outrate, state, weightA=1, weightB=0):
@@ -471,11 +455,10 @@
inrate //= d
outrate //= d
- prev_i = [0] * nchannels
- cur_i = [0] * nchannels
-
if state is None:
d = -outrate
+ prev_i = ffi.new('int[]', nchannels)
+ cur_i = ffi.new('int[]', nchannels)
else:
d, samps = state
@@ -483,70 +466,709 @@
raise error("illegal state argument")
prev_i, cur_i = zip(*samps)
- prev_i, cur_i = list(prev_i), list(cur_i)
+ prev_i = ffi.new('int[]', prev_i)
+ cur_i = ffi.new('int[]', cur_i)
+ state_d = ffi.new('int[]', (d,))
q = frame_count // inrate
ceiling = (q + 1) * outrate
nbytes = ceiling * bytes_per_frame
- result = create_string_buffer(nbytes)
+ rv = ffi.new("unsigned char[]", nbytes)
+ trim_index = lib.ratecv(rv, cp, frame_count, size,
+ nchannels, inrate, outrate,
+ state_d, prev_i, cur_i,
+ weightA, weightB)
+ result = ffi.buffer(rv)[:trim_index]
+ samps = zip(prev_i, cur_i)
+ return (result, (d, tuple(samps)))
- 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 = retval[:trim_index]
+ffi = FFI()
+ffi.cdef("""
+typedef short PyInt16;
- return (retval, (d, tuple(samps)))
+int ratecv(char* rv, char* cp, size_t len, int size,
+ int nchannels, int inrate, int outrate,
+ int* state_d, int* prev_i, int* cur_i,
+ int weightA, int weightB);
- for chan in range(nchannels):
- prev_i[chan] = cur_i[chan]
- cur_i[chan] = next(samples)
+void tostereo(char* rv, char* cp, size_t len, int size,
+ double fac1, double fac2);
+void add(char* rv, char* cp1, char* cp2, size_t len1, int size);
- cur_i[chan] = (
- (weightA * cur_i[chan] + weightB * prev_i[chan])
- // (weightA + weightB)
- )
+/* 2's complement (14-bit range) */
+unsigned char
+st_14linear2ulaw(PyInt16 pcm_val);
+PyInt16 st_ulaw2linear16(unsigned char);
- frame_count -= 1
- d += outrate
+/* 2's complement (13-bit range) */
+unsigned char
+st_linear2alaw(PyInt16 pcm_val);
+PyInt16 st_alaw2linear16(unsigned char);
- 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
+void lin2adcpm(unsigned char* rv, unsigned char* cp, size_t len,
+ size_t size, int* state);
+void adcpm2lin(unsigned char* rv, unsigned char* cp, size_t len,
+ size_t size, int* state);
+""")
+
+# This code is directly copied from CPython file: Modules/audioop.c
+_AUDIOOP_C_MODULE = """
+typedef short PyInt16;
+typedef int Py_Int32;
+
+/* Code shamelessly stolen from sox, 12.17.7, g711.c
+** (c) Craig Reese, Joe Campbell and Jeff Poskanzer 1989 */
+
+/* From g711.c:
+ *
+ * December 30, 1994:
+ * Functions linear2alaw, linear2ulaw have been updated to correctly
+ * convert unquantized 16 bit values.
+ * Tables for direct u- to A-law and A- to u-law conversions have been
+ * corrected.
+ * Borge Lindberg, Center for PersonKommunikation, Aalborg University.
+ * bli at cpk.auc.dk
+ *
+ */
+#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
+#define CLIP 32635
+#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
+#define QUANT_MASK (0xf) /* Quantization field mask. */
+#define SEG_SHIFT (4) /* Left shift for segment number. */
+#define SEG_MASK (0x70) /* Segment field mask. */
+
+static PyInt16 seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
+ 0x1FF, 0x3FF, 0x7FF, 0xFFF};
+static PyInt16 seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
+ 0x3FF, 0x7FF, 0xFFF, 0x1FFF};
+
+static PyInt16
+search(PyInt16 val, PyInt16 *table, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (val <= *table++)
+ return (i);
+ }
+ return (size);
+}
+#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
+#define st_alaw2linear16(uc) (_st_alaw2linear16[uc])
+
+static PyInt16 _st_ulaw2linear16[256] = {
+ -32124, -31100, -30076, -29052, -28028, -27004, -25980,
+ -24956, -23932, -22908, -21884, -20860, -19836, -18812,
+ -17788, -16764, -15996, -15484, -14972, -14460, -13948,
+ -13436, -12924, -12412, -11900, -11388, -10876, -10364,
+ -9852, -9340, -8828, -8316, -7932, -7676, -7420,
+ -7164, -6908, -6652, -6396, -6140, -5884, -5628,
+ -5372, -5116, -4860, -4604, -4348, -4092, -3900,
+ -3772, -3644, -3516, -3388, -3260, -3132, -3004,
+ -2876, -2748, -2620, -2492, -2364, -2236, -2108,
+ -1980, -1884, -1820, -1756, -1692, -1628, -1564,
+ -1500, -1436, -1372, -1308, -1244, -1180, -1116,
+ -1052, -988, -924, -876, -844, -812, -780,
+ -748, -716, -684, -652, -620, -588, -556,
+ -524, -492, -460, -428, -396, -372, -356,
+ -340, -324, -308, -292, -276, -260, -244,
+ -228, -212, -196, -180, -164, -148, -132,
+ -120, -112, -104, -96, -88, -80, -72,
+ -64, -56, -48, -40, -32, -24, -16,
+ -8, 0, 32124, 31100, 30076, 29052, 28028,
+ 27004, 25980, 24956, 23932, 22908, 21884, 20860,
+ 19836, 18812, 17788, 16764, 15996, 15484, 14972,
+ 14460, 13948, 13436, 12924, 12412, 11900, 11388,
+ 10876, 10364, 9852, 9340, 8828, 8316, 7932,
+ 7676, 7420, 7164, 6908, 6652, 6396, 6140,
+ 5884, 5628, 5372, 5116, 4860, 4604, 4348,
+ 4092, 3900, 3772, 3644, 3516, 3388, 3260,
+ 3132, 3004, 2876, 2748, 2620, 2492, 2364,
+ 2236, 2108, 1980, 1884, 1820, 1756, 1692,
+ 1628, 1564, 1500, 1436, 1372, 1308, 1244,
+ 1180, 1116, 1052, 988, 924, 876, 844,
+ 812, 780, 748, 716, 684, 652, 620,
+ 588, 556, 524, 492, 460, 428, 396,
+ 372, 356, 340, 324, 308, 292, 276,
+ 260, 244, 228, 212, 196, 180, 164,
+ 148, 132, 120, 112, 104, 96, 88,
+ 80, 72, 64, 56, 48, 40, 32,
+ 24, 16, 8, 0
+};
+
+/*
+ * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
+ * stored in a unsigned char. This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 14-bits.
+ *
+ * In order to simplify the encoding process, the original linear magnitude
+ * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
+ * (33 - 8191). The result can be seen in the following encoding table:
+ *
+ * Biased Linear Input Code Compressed Code
+ * ------------------------ ---------------
+ * 00000001wxyza 000wxyz
+ * 0000001wxyzab 001wxyz
+ * 000001wxyzabc 010wxyz
+ * 00001wxyzabcd 011wxyz
+ * 0001wxyzabcde 100wxyz
+ * 001wxyzabcdef 101wxyz
+ * 01wxyzabcdefg 110wxyz
+ * 1wxyzabcdefgh 111wxyz
+ *
+ * Each biased linear code has a leading 1 which identifies the segment
+ * number. The value of the segment number is equal to 7 minus the number
+ * of leading 0's. The quantization interval is directly available as the
+ * four bits wxyz. * The trailing bits (a - h) are ignored.
+ *
+ * Ordinarily the complement of the resulting code word is used for
+ * transmission, and so the code word is complemented before it is returned.
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+static unsigned char
+st_14linear2ulaw(PyInt16 pcm_val) /* 2's complement (14-bit range) */
+{
+ PyInt16 mask;
+ PyInt16 seg;
+ unsigned char uval;
+
+ /* The original sox code does this in the calling function, not here */
+ pcm_val = pcm_val >> 2;
+
+ /* u-law inverts all bits */
+ /* Get the sign and the magnitude of the value. */
+ if (pcm_val < 0) {
+ pcm_val = -pcm_val;
+ mask = 0x7F;
+ } else {
+ mask = 0xFF;
+ }
+ if ( pcm_val > CLIP ) pcm_val = CLIP; /* clip the magnitude */
+ pcm_val += (BIAS >> 2);
+
+ /* Convert the scaled magnitude to segment number. */
+ seg = search(pcm_val, seg_uend, 8);
+
+ /*
+ * Combine the sign, segment, quantization bits;
+ * and complement the code word.
+ */
+ if (seg >= 8) /* out of range, return maximum value. */
+ return (unsigned char) (0x7F ^ mask);
+ else {
+ uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
+ return (uval ^ mask);
+ }
+
+}
+
+static PyInt16 _st_alaw2linear16[256] = {
+ -5504, -5248, -6016, -5760, -4480, -4224, -4992,
+ -4736, -7552, -7296, -8064, -7808, -6528, -6272,
+ -7040, -6784, -2752, -2624, -3008, -2880, -2240,
+ -2112, -2496, -2368, -3776, -3648, -4032, -3904,
+ -3264, -3136, -3520, -3392, -22016, -20992, -24064,
+ -23040, -17920, -16896, -19968, -18944, -30208, -29184,
+ -32256, -31232, -26112, -25088, -28160, -27136, -11008,
+ -10496, -12032, -11520, -8960, -8448, -9984, -9472,
+ -15104, -14592, -16128, -15616, -13056, -12544, -14080,
+ -13568, -344, -328, -376, -360, -280, -264,
+ -312, -296, -472, -456, -504, -488, -408,
+ -392, -440, -424, -88, -72, -120, -104,
+ -24, -8, -56, -40, -216, -200, -248,
+ -232, -152, -136, -184, -168, -1376, -1312,
+ -1504, -1440, -1120, -1056, -1248, -1184, -1888,
+ -1824, -2016, -1952, -1632, -1568, -1760, -1696,
+ -688, -656, -752, -720, -560, -528, -624,
+ -592, -944, -912, -1008, -976, -816, -784,
+ -880, -848, 5504, 5248, 6016, 5760, 4480,
+ 4224, 4992, 4736, 7552, 7296, 8064, 7808,
+ 6528, 6272, 7040, 6784, 2752, 2624, 3008,
+ 2880, 2240, 2112, 2496, 2368, 3776, 3648,
+ 4032, 3904, 3264, 3136, 3520, 3392, 22016,
+ 20992, 24064, 23040, 17920, 16896, 19968, 18944,
+ 30208, 29184, 32256, 31232, 26112, 25088, 28160,
+ 27136, 11008, 10496, 12032, 11520, 8960, 8448,
+ 9984, 9472, 15104, 14592, 16128, 15616, 13056,
+ 12544, 14080, 13568, 344, 328, 376, 360,
+ 280, 264, 312, 296, 472, 456, 504,
+ 488, 408, 392, 440, 424, 88, 72,
+ 120, 104, 24, 8, 56, 40, 216,
+ 200, 248, 232, 152, 136, 184, 168,
+ 1376, 1312, 1504, 1440, 1120, 1056, 1248,
+ 1184, 1888, 1824, 2016, 1952, 1632, 1568,
+ 1760, 1696, 688, 656, 752, 720, 560,
+ 528, 624, 592, 944, 912, 1008, 976,
+ 816, 784, 880, 848
+};
+
+/*
+ * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data
+ * stored in a unsigned char. This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 13-bits.
+ *
+ * Linear Input Code Compressed Code
+ * ------------------------ ---------------
+ * 0000000wxyza 000wxyz
+ * 0000001wxyza 001wxyz
+ * 000001wxyzab 010wxyz
+ * 00001wxyzabc 011wxyz
+ * 0001wxyzabcd 100wxyz
+ * 001wxyzabcde 101wxyz
+ * 01wxyzabcdef 110wxyz
+ * 1wxyzabcdefg 111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+static unsigned char
+st_linear2alaw(PyInt16 pcm_val) /* 2's complement (13-bit range) */
+{
+ PyInt16 mask;
+ short seg;
+ unsigned char aval;
+
+ /* The original sox code does this in the calling function, not here */
+ pcm_val = pcm_val >> 3;
+
+ /* A-law using even bit inversion */
+ if (pcm_val >= 0) {
+ mask = 0xD5; /* sign (7th) bit = 1 */
+ } else {
+ mask = 0x55; /* sign bit = 0 */
+ pcm_val = -pcm_val - 1;
+ }
+
+ /* Convert the scaled magnitude to segment number. */
+ seg = search(pcm_val, seg_aend, 8);
+
+ /* Combine the sign, segment, and quantization bits. */
+
+ if (seg >= 8) /* out of range, return maximum value. */
+ return (unsigned char) (0x7F ^ mask);
+ else {
+ aval = (unsigned char) seg << SEG_SHIFT;
+ if (seg < 2)
+ aval |= (pcm_val >> 1) & QUANT_MASK;
+ else
+ aval |= (pcm_val >> seg) & QUANT_MASK;
+ return (aval ^ mask);
+ }
+}
+/* End of code taken from sox */
+
+/* Intel ADPCM step variation table */
+static int indexTable[16] = {
+ -1, -1, -1, -1, 2, 4, 6, 8,
+ -1, -1, -1, -1, 2, 4, 6, 8,
+};
+
+static int stepsizeTable[89] = {
+ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+ 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+ 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+#define CHARP(cp, i) ((signed char *)(cp+i))
+#define SHORTP(cp, i) ((short *)(cp+i))
+#define LONGP(cp, i) ((Py_Int32 *)(cp+i))
+"""
+
+lib = ffi.verify(_AUDIOOP_C_MODULE + r"""
+#include <math.h>
+
+static const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF};
+/* -1 trick is needed on Windows to support -0x80000000 without a warning */
+static const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x7FFFFFFF-1};
+
+static int
+fbound(double val, double minval, double maxval)
+{
+ if (val > maxval)
+ val = maxval;
+ else if (val < minval + 1)
+ val = minval;
+ return val;
+}
+
+static int
+gcd(int a, int b)
+{
+ while (b > 0) {
+ int tmp = a % b;
+ a = b;
+ b = tmp;
+ }
+ return a;
+}
+
+int ratecv(char* rv, char* cp, size_t len, int size,
+ int nchannels, int inrate, int outrate,
+ int* state_d, int* prev_i, int* cur_i,
+ int weightA, int weightB)
+{
+ char *ncp = rv;
+ int d, chan;
+
+ /* divide inrate and outrate by their greatest common divisor */
+ d = gcd(inrate, outrate);
+ inrate /= d;
+ outrate /= d;
+ /* divide weightA and weightB by their greatest common divisor */
+ d = gcd(weightA, weightB);
+ weightA /= d;
+ weightA /= d;
+
+ d = *state_d;
+
+ for (;;) {
+ while (d < 0) {
+ if (len == 0) {
+ *state_d = d;
+ return ncp - rv;
+ }
+ for (chan = 0; chan < nchannels; chan++) {
+ prev_i[chan] = cur_i[chan];
+ if (size == 1)
+ cur_i[chan] = ((int)*CHARP(cp, 0)) << 24;
+ else if (size == 2)
+ cur_i[chan] = ((int)*SHORTP(cp, 0)) << 16;
+ else if (size == 4)
+ cur_i[chan] = (int)*LONGP(cp, 0);
+ cp += size;
+ /* implements a simple digital filter */
+ cur_i[chan] = (int)(
+ ((double)weightA * (double)cur_i[chan] +
+ (double)weightB * (double)prev_i[chan]) /
+ ((double)weightA + (double)weightB));
+ }
+ len--;
+ d += outrate;
+ }
+ while (d >= 0) {
+ for (chan = 0; chan < nchannels; chan++) {
+ int cur_o;
+ cur_o = (int)(((double)prev_i[chan] * (double)d +
+ (double)cur_i[chan] * (double)(outrate - d)) /
+ (double)outrate);
+ if (size == 1)
+ *CHARP(ncp, 0) = (signed char)(cur_o >> 24);
+ else if (size == 2)
+ *SHORTP(ncp, 0) = (short)(cur_o >> 16);
+ else if (size == 4)
+ *LONGP(ncp, 0) = (Py_Int32)(cur_o);
+ ncp += size;
+ }
+ d -= inrate;
+ }
+ }
+}
+
+void tostereo(char* rv, char* cp, size_t len, int size,
+ double fac1, double fac2)
+{
+ int val1, val2, val = 0;
+ double fval, maxval, minval;
+ char *ncp = rv;
+ int i;
+
+ maxval = (double) maxvals[size];
+ minval = (double) minvals[size];
+
+ for ( i=0; i < len; i += size ) {
+ if ( size == 1 ) val = (int)*CHARP(cp, i);
+ else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+ else if ( size == 4 ) val = (int)*LONGP(cp, i);
+
+ fval = (double)val*fac1;
+ val1 = (int)floor(fbound(fval, minval, maxval));
+
+ fval = (double)val*fac2;
+ val2 = (int)floor(fbound(fval, minval, maxval));
+
+ if ( size == 1 ) *CHARP(ncp, i*2) = (signed char)val1;
+ else if ( size == 2 ) *SHORTP(ncp, i*2) = (short)val1;
+ else if ( size == 4 ) *LONGP(ncp, i*2) = (Py_Int32)val1;
+
+ if ( size == 1 ) *CHARP(ncp, i*2+1) = (signed char)val2;
+ else if ( size == 2 ) *SHORTP(ncp, i*2+2) = (short)val2;
+ else if ( size == 4 ) *LONGP(ncp, i*2+4) = (Py_Int32)val2;
+ }
+}
+
+void add(char* rv, char* cp1, char* cp2, size_t len1, int size)
+{
+ int i;
+ int val1 = 0, val2 = 0, minval, maxval, newval;
+ char* ncp = rv;
+
+ maxval = maxvals[size];
+ minval = minvals[size];
+
+ for ( i=0; i < len1; i += size ) {
+ if ( size == 1 ) val1 = (int)*CHARP(cp1, i);
+ else if ( size == 2 ) val1 = (int)*SHORTP(cp1, i);
+ else if ( size == 4 ) val1 = (int)*LONGP(cp1, i);
+
+ if ( size == 1 ) val2 = (int)*CHARP(cp2, i);
+ else if ( size == 2 ) val2 = (int)*SHORTP(cp2, i);
+ else if ( size == 4 ) val2 = (int)*LONGP(cp2, i);
+
+ if (size < 4) {
+ newval = val1 + val2;
+ /* truncate in case of overflow */
+ if (newval > maxval)
+ newval = maxval;
+ else if (newval < minval)
+ newval = minval;
+ }
+ else {
+ double fval = (double)val1 + (double)val2;
+ /* truncate in case of overflow */
+ newval = (int)floor(fbound(fval, minval, maxval));
+ }
+
+ if ( size == 1 ) *CHARP(ncp, i) = (signed char)newval;
+ else if ( size == 2 ) *SHORTP(ncp, i) = (short)newval;
+ else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)newval;
+ }
+}
+
+void lin2adcpm(unsigned char* ncp, unsigned char* cp, size_t len,
+ size_t size, int* state)
+{
+ int step, outputbuffer = 0, bufferstep;
+ int val = 0;
+ int diff, vpdiff, sign, delta;
+ size_t i;
+ int valpred = state[0];
+ int index = state[1];
+
+ step = stepsizeTable[index];
+ bufferstep = 1;
+
+ for ( i=0; i < len; i += size ) {
+ if ( size == 1 ) val = ((int)*CHARP(cp, i)) << 8;
+ else if ( size == 2 ) val = (int)*SHORTP(cp, i);
+ else if ( size == 4 ) val = ((int)*LONGP(cp, i)) >> 16;
+
+ /* Step 1 - compute difference with previous value */
+ diff = val - valpred;
+ sign = (diff < 0) ? 8 : 0;
+ if ( sign ) diff = (-diff);
+
+ /* Step 2 - Divide and clamp */
+ /* Note:
+ ** This code *approximately* computes:
+ ** delta = diff*4/step;
+ ** vpdiff = (delta+0.5)*step/4;
+ ** but in shift step bits are dropped. The net result of this
+ ** is that even if you have fast mul/div hardware you cannot
+ ** put it to good use since the fixup would be too expensive.
+ */
+ delta = 0;
+ vpdiff = (step >> 3);
+
+ if ( diff >= step ) {
+ delta = 4;
+ diff -= step;
+ vpdiff += step;
+ }
+ step >>= 1;
+ if ( diff >= step ) {
+ delta |= 2;
+ diff -= step;
+ vpdiff += step;
+ }
+ step >>= 1;
+ if ( diff >= step ) {
+ delta |= 1;
+ vpdiff += step;
+ }
+
+ /* Step 3 - Update previous value */
+ if ( sign )
+ valpred -= vpdiff;
+ else
+ valpred += vpdiff;
+
+ /* Step 4 - Clamp previous value to 16 bits */
+ if ( valpred > 32767 )
+ valpred = 32767;
+ else if ( valpred < -32768 )
+ valpred = -32768;
+
+ /* Step 5 - Assemble value, update index and step values */
+ delta |= sign;
+
+ index += indexTable[delta];
+ if ( index < 0 ) index = 0;
+ if ( index > 88 ) index = 88;
+ step = stepsizeTable[index];
+
+ /* Step 6 - Output value */
+ if ( bufferstep ) {
+ outputbuffer = (delta << 4) & 0xf0;
+ } else {
+ *ncp++ = (delta & 0x0f) | outputbuffer;
+ }
+ bufferstep = !bufferstep;
+ }
+ state[0] = valpred;
+ state[1] = index;
+}
+
+
+void adcpm2lin(unsigned char* ncp, unsigned char* cp, size_t len,
+ size_t size, int* state)
+{
+ int step, inputbuffer = 0, bufferstep;
+ int val = 0;
+ int diff, vpdiff, sign, delta;
+ size_t i;
+ int valpred = state[0];
+ int index = state[1];
+
+ step = stepsizeTable[index];
+ bufferstep = 0;
+
+ for ( i=0; i < len*size*2; i += size ) {
+ /* Step 1 - get the delta value and compute next index */
+ if ( bufferstep ) {
+ delta = inputbuffer & 0xf;
+ } else {
+ inputbuffer = *cp++;
+ delta = (inputbuffer >> 4) & 0xf;
+ }
+
+ bufferstep = !bufferstep;
+
+ /* Step 2 - Find new index value (for later) */
+ index += indexTable[delta];
+ if ( index < 0 ) index = 0;
+ if ( index > 88 ) index = 88;
+
+ /* Step 3 - Separate sign and magnitude */
+ sign = delta & 8;
+ delta = delta & 7;
+
+ /* Step 4 - Compute difference and new predicted value */
+ /*
+ ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
+ ** in adpcm_coder.
+ */
+ vpdiff = step >> 3;
+ if ( delta & 4 ) vpdiff += step;
+ if ( delta & 2 ) vpdiff += step>>1;
+ if ( delta & 1 ) vpdiff += step>>2;
+
+ if ( sign )
+ valpred -= vpdiff;
+ else
+ valpred += vpdiff;
+
+ /* Step 5 - clamp output value */
+ if ( valpred > 32767 )
+ valpred = 32767;
+ else if ( valpred < -32768 )
+ valpred = -32768;
+
+ /* Step 6 - Update step value */
+ step = stepsizeTable[index];
+
+ /* Step 6 - Output value */
+ if ( size == 1 ) *CHARP(ncp, i) = (signed char)(valpred >> 8);
+ else if ( size == 2 ) *SHORTP(ncp, i) = (short)(valpred);
+ else if ( size == 4 ) *LONGP(ncp, i) = (Py_Int32)(valpred<<16);
+ }
+ state[0] = valpred;
+ state[1] = index;
+}
+""")
+
+def _get_lin_samples(cp, size):
+ for sample in _get_samples(cp, size):
+ if size == 1:
+ yield sample << 8
+ elif size == 2:
+ yield sample
+ elif size == 4:
+ yield sample >> 16
+
+def _put_lin_sample(result, size, i, sample):
+ if size == 1:
+ sample >>= 8
+ elif size == 2:
+ pass
+ elif size == 4:
+ sample <<= 16
+ _put_sample(result, size, i, sample)
def lin2ulaw(cp, size):
- raise NotImplementedError()
+ _check_params(len(cp), size)
+ rv = ffi.new("unsigned char[]", _sample_count(cp, size))
+ for i, sample in enumerate(_get_lin_samples(cp, size)):
+ rv[i] = lib.st_14linear2ulaw(sample)
+ return ffi.buffer(rv)[:]
def ulaw2lin(cp, size):
- raise NotImplementedError()
+ _check_size(size)
+ rv = ffi.new("unsigned char[]", len(cp) * size)
+ result = ffi.buffer(rv)
+ for i, value in enumerate(cp):
+ sample = lib.st_ulaw2linear16(ord(value))
+ _put_lin_sample(result, size, i, sample)
+ return result[:]
def lin2alaw(cp, size):
- raise NotImplementedError()
+ _check_params(len(cp), size)
+ rv = ffi.new("unsigned char[]", _sample_count(cp, size))
+ for i, sample in enumerate(_get_lin_samples(cp, size)):
+ rv[i] = lib.st_linear2alaw(sample)
+ return ffi.buffer(rv)[:]
def alaw2lin(cp, size):
- raise NotImplementedError()
+ _check_size(size)
+ rv = ffi.new("unsigned char[]", len(cp) * size)
+ result = ffi.buffer(rv)
+ for i, value in enumerate(cp):
+ sample = lib.st_alaw2linear16(ord(value))
+ _put_lin_sample(result, size, i, sample)
+ return result[:]
def lin2adpcm(cp, size, state):
- raise NotImplementedError()
+ _check_params(len(cp), size)
+ if state is None:
+ state = (0, 0)
+ rv = ffi.new("unsigned char[]", len(cp) // size // 2)
+ state_ptr = ffi.new("int[]", state)
+ lib.lin2adcpm(rv, cp, len(cp), size, state_ptr)
+ return ffi.buffer(rv)[:], tuple(state_ptr)
def adpcm2lin(cp, size, state):
- raise NotImplementedError()
+ _check_size(size)
+ if state is None:
+ state = (0, 0)
+ rv = ffi.new("unsigned char[]", len(cp) * size * 2)
+ state_ptr = ffi.new("int[]", state)
+ lib.adcpm2lin(rv, cp, len(cp), size, state_ptr)
+ return ffi.buffer(rv)[:], tuple(state_ptr)
+
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "0.8.6"
-__version_info__ = (0, 8, 6)
+__version__ = "0.8.6+"
+__version_info__ = (0, 8, 6, "plus")
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -55,7 +55,8 @@
# _cffi_backend.so compiled.
import _cffi_backend as backend
from . import __version__
- assert backend.__version__ == __version__
+ assert backend.__version__ == __version__, \
+ "version mismatch, %s != %s" % (backend.__version__, __version__)
# (If you insist you can also try to pass the option
# 'backend=backend_ctypes.CTypesBackend()', but don't
# rely on it! It's probably not going to work well.)
diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py
--- a/lib_pypy/cffi/backend_ctypes.py
+++ b/lib_pypy/cffi/backend_ctypes.py
@@ -2,11 +2,10 @@
from . import model
if sys.version_info < (3,):
- integer_types = (int, long)
bytechr = chr
else:
unicode = str
- integer_types = int
+ long = int
xrange = range
bytechr = lambda num: bytes([num])
@@ -181,7 +180,7 @@
address = 0
elif isinstance(source, CTypesData):
address = source._cast_to_integer()
- elif isinstance(source, integer_types):
+ elif isinstance(source, (int, long)):
address = source
else:
raise TypeError("bad type for cast to %r: %r" %
@@ -358,7 +357,7 @@
is_signed = (ctype(-1).value == -1)
#
def _cast_source_to_int(source):
- if isinstance(source, (integer_types, float)):
+ if isinstance(source, (int, long, float)):
source = int(source)
elif isinstance(source, CTypesData):
source = source._cast_to_integer()
@@ -399,7 +398,7 @@
if kind == 'bool':
@classmethod
def _cast_from(cls, source):
- if not isinstance(source, (integer_types, float)):
+ if not isinstance(source, (int, long, float)):
source = _cast_source_to_int(source)
return cls(bool(source))
def __int__(self):
@@ -438,7 +437,7 @@
if kind == 'int' or kind == 'byte' or kind == 'bool':
@staticmethod
def _to_ctypes(x):
- if not isinstance(x, integer_types):
+ if not isinstance(x, (int, long)):
if isinstance(x, CTypesData):
x = int(x)
else:
@@ -465,7 +464,7 @@
if kind == 'float':
@staticmethod
def _to_ctypes(x):
- if not isinstance(x, (integer_types, float, CTypesData)):
+ if not isinstance(x, (int, long, float, CTypesData)):
raise TypeError("float expected, got %s" %
type(x).__name__)
return ctype(x).value
@@ -529,14 +528,14 @@
self._own = True
def __add__(self, other):
- if isinstance(other, integer_types):
+ if isinstance(other, (int, long)):
return self._new_pointer_at(self._address +
other * self._bitem_size)
else:
return NotImplemented
def __sub__(self, other):
- if isinstance(other, integer_types):
+ if isinstance(other, (int, long)):
return self._new_pointer_at(self._address -
other * self._bitem_size)
elif type(self) is type(other):
@@ -611,7 +610,7 @@
def __init__(self, init):
if length is None:
- if isinstance(init, integer_types):
+ if isinstance(init, (int, long)):
len1 = init
init = None
elif kind == 'char' and isinstance(init, bytes):
@@ -686,7 +685,7 @@
return CTypesPtr._arg_to_ctypes(value)
def __add__(self, other):
- if isinstance(other, integer_types):
+ if isinstance(other, (int, long)):
return CTypesPtr._new_pointer_at(
ctypes.addressof(self._blob) +
other * ctypes.sizeof(BItem._ctype))
diff --git a/lib_pypy/cffi/verifier.py b/lib_pypy/cffi/verifier.py
--- a/lib_pypy/cffi/verifier.py
+++ b/lib_pypy/cffi/verifier.py
@@ -1,4 +1,4 @@
-import sys, os, binascii, shutil
+import sys, os, binascii, shutil, io
from . import __version_verifier_modules__
from . import ffiplatform
@@ -13,6 +13,16 @@
if type == imp.C_EXTENSION]
+if sys.version_info >= (3,):
+ NativeIO = io.StringIO
+else:
+ class NativeIO(io.BytesIO):
+ def write(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('ascii')
+ super(NativeIO, self).write(s)
+
+
class Verifier(object):
def __init__(self, ffi, preamble, tmpdir=None, modulename=None,
@@ -144,19 +154,36 @@
self._vengine.collect_types()
self._has_module = True
- def _write_source(self, file=None):
- must_close = (file is None)
- if must_close:
- _ensure_dir(self.sourcefilename)
- file = open(self.sourcefilename, 'w')
+ def _write_source_to(self, file):
self._vengine._f = file
try:
self._vengine.write_source_to_f()
finally:
del self._vengine._f
- if must_close:
- file.close()
- if must_close:
+
+ def _write_source(self, file=None):
+ if file is not None:
+ self._write_source_to(file)
+ else:
+ # Write our source file to an in memory file.
+ f = NativeIO()
+ self._write_source_to(f)
+ source_data = f.getvalue()
+
+ # Determine if this matches the current file
+ if os.path.exists(self.sourcefilename):
+ with open(self.sourcefilename, "r") as fp:
+ needs_written = not (fp.read() == source_data)
+ else:
+ needs_written = True
+
+ # Actually write the file out if it doesn't match
+ if needs_written:
+ _ensure_dir(self.sourcefilename)
+ with open(self.sourcefilename, "w") as fp:
+ fp.write(source_data)
+
+ # Set this flag
self._has_source = True
def _compile_module(self):
diff --git a/lib_pypy/gdbm.py b/lib_pypy/gdbm.py
--- a/lib_pypy/gdbm.py
+++ b/lib_pypy/gdbm.py
@@ -1,4 +1,4 @@
-import cffi, os
+import cffi, os, sys
ffi = cffi.FFI()
ffi.cdef('''
@@ -37,9 +37,19 @@
''')
try:
- lib = ffi.verify('''
- #include "gdbm.h"
- ''', libraries=['gdbm'])
+ if sys.platform.startswith('freebsd'):
+ import os.path
+ _localbase = os.environ.get('LOCALBASE', '/usr/local')
+ lib = ffi.verify('''
+ #include "gdbm.h"
+ ''', libraries=['gdbm'],
+ include_dirs=[os.path.join(_localbase, 'include')],
+ library_dirs=[os.path.join(_localbase, 'lib')]
+ )
+ else:
+ lib = ffi.verify('''
+ #include "gdbm.h"
+ ''', libraries=['gdbm'])
except cffi.VerificationError as e:
# distutils does not preserve the actual message,
# but the verification is simple enough that the
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -73,6 +73,7 @@
assume_immutable_completions = False
use_brackets = False
sort_in_column = True
+ tab_insert_spaces_if_stem_is_empty = False
def error(self, msg="none"):
pass # don't show error messages by default
@@ -86,6 +87,13 @@
return ''.join(b[p+1:self.pos])
def get_completions(self, stem):
+ if len(stem) == 0 and self.tab_insert_spaces_if_stem_is_empty:
+ b = self.buffer
+ p = self.pos
+ while p > 0 and b[p - 1] != '\n':
+ p -= 1
+ num_spaces = 4 - ((self.pos - p) % 4)
+ return [' ' * num_spaces]
result = []
function = self.config.readline_completer
if function is not None:
@@ -204,14 +212,15 @@
boolean value is true.
"""
reader = self.get_reader()
- saved = reader.more_lines
+ saved = reader.more_lines, reader.tab_insert_spaces_if_stem_is_empty
try:
reader.more_lines = more_lines
reader.ps1 = reader.ps2 = ps1
reader.ps3 = reader.ps4 = ps2
+ reader.tab_insert_spaces_if_stem_is_empty = True
return reader.readline(returns_unicode=returns_unicode)
finally:
- reader.more_lines = saved
+ reader.more_lines, reader.tab_insert_spaces_if_stem_is_empty = saved
def parse_and_bind(self, string):
pass # XXX we don't support parsing GNU-readline-style init files
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -48,9 +48,13 @@
Install build-time dependencies
-------------------------------
(**Note**: for some hints on how to translate the Python interpreter under
-Windows, see the `windows document`_)
+Windows, see the `windows document`_ . For hints on how to cross-compile in
+a chroot using scratchbox2, see the `arm document`_ in the
+`RPython documentation`_)
.. _`windows document`: windows.html
+.. _`arm document`: http://rpython.readthedocs.org/en/latest/arm.html
+.. _`RPython documentation`: http://rpython.readthedocs.org
To build PyPy on Unix using the C translation backend, you need at least a C
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -300,6 +300,18 @@
Notably missing from the list above are ``str`` and ``unicode``. If your
code relies on comparing strings with ``is``, then it might break in PyPy.
+Note that for floats there "``is``" only one object per "bit pattern"
+of the float. So ``float('nan') is float('nan')`` is true on PyPy,
+but not on CPython because they are two objects; but ``0.0 is -0.0``
+is always False, as the bit patterns are different. As usual,
+``float('nan') == float('nan')`` is always False. When used in
+containers (as list items or in sets for example), the exact rule of
+equality used is "``if x is y or x == y``" (on both CPython and PyPy);
+as a consequence, because all ``nans`` are identical in PyPy, you
+cannot have several of them in a set, unlike in CPython. (Issue `#1974`__)
+
+.. __: https://bitbucket.org/pypy/pypy/issue/1974/different-behaviour-for-collections-of
+
Miscellaneous
-------------
diff --git a/pypy/doc/interpreter-optimizations.rst b/pypy/doc/interpreter-optimizations.rst
--- a/pypy/doc/interpreter-optimizations.rst
+++ b/pypy/doc/interpreter-optimizations.rst
@@ -165,7 +165,7 @@
We improved this by keeping method lookup separated from method call, unlike
some other approaches, but using the value stack as a cache instead of building
a temporary object. We extended the bytecode compiler to (optionally) generate
-the following code for ``obj.meth(x)``::
+the following code for ``obj.meth(x, y)``::
LOAD_GLOBAL obj
LOOKUP_METHOD meth
@@ -181,7 +181,7 @@
the attribute actually refers to a function object from the class; when this is
not the case, ``LOOKUP_METHOD`` still pushes two values, but one *(im_func)* is
simply the regular result that ``LOAD_ATTR`` would have returned, and the other
-*(im_self)* is a None placeholder.
+*(im_self)* is an interpreter-level None placeholder.
After pushing the arguments, the layout of the stack in the above
example is as follows (the stack grows upwards):
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -712,7 +712,7 @@
return self.wrap(not self.is_true(w_obj))
def eq_w(self, w_obj1, w_obj2):
- """shortcut for space.is_true(space.eq(w_obj1, w_obj2))"""
+ """Implements equality with the double check 'x is y or x == y'."""
return self.is_w(w_obj1, w_obj2) or self.is_true(self.eq(w_obj1, w_obj2))
def is_(self, w_one, w_two):
diff --git a/pypy/interpreter/unicodehelper.py b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -16,17 +16,20 @@
space.wrap(msg)]))
return raise_unicode_exception_decode
+class RUnicodeEncodeError(Exception):
+ def __init__(self, encoding, object, start, end, reason):
+ self.encoding = encoding
+ self.object = object
+ self.start = start
+ self.end = end
+ self.reason = reason
+
@specialize.memo()
def encode_error_handler(space):
# Fast version of the "strict" errors handler.
def raise_unicode_exception_encode(errors, encoding, msg, u,
startingpos, endingpos):
- raise OperationError(space.w_UnicodeEncodeError,
- space.newtuple([space.wrap(encoding),
- space.wrap(u),
- space.wrap(startingpos),
- space.wrap(endingpos),
- space.wrap(msg)]))
+ raise RUnicodeEncodeError(encoding, u, startingpos, endingpos, msg)
return raise_unicode_exception_encode
# ____________________________________________________________
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -8,7 +8,7 @@
appleveldefs = {
}
interpleveldefs = {
- '__version__': 'space.wrap("0.8.6")',
+ '__version__': 'space.wrap("0.8.6+")',
'load_library': 'libraryobj.load_library',
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -3241,4 +3241,4 @@
def test_version():
# this test is here mostly for PyPy
- assert __version__ == "0.8.6"
+ assert __version__ == "0.8.6+"
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -1153,6 +1153,11 @@
assert buffer(s)._pypy_raw_address() == addr
assert buffer(s, 10)._pypy_raw_address() == addr + 10
+ addr = memoryview(s)._pypy_raw_address()
+ assert type(addr) is int
+ assert memoryview(s)._pypy_raw_address() == addr
+ assert memoryview(s)[10:]._pypy_raw_address() == addr + 10
+
def test_union(self):
import _rawffi
longsize = _rawffi.sizeof('l')
diff --git a/pypy/module/micronumpy/ctors.py b/pypy/module/micronumpy/ctors.py
--- a/pypy/module/micronumpy/ctors.py
+++ b/pypy/module/micronumpy/ctors.py
@@ -81,7 +81,10 @@
return w_object.descr_copy(space, w_order)
elif not copy and (subok or type(w_object) is W_NDimArray):
return w_object
- # we have a ndarray, but need to copy or change dtype or create W_NDimArray
+ if subok and not type(w_object) is W_NDimArray:
+ raise oefmt(space.w_NotImplementedError,
+ "array(..., subok=True) only partially implemented")
+ # we have a ndarray, but need to copy or change dtype
if dtype is None:
dtype = w_object.get_dtype()
if dtype != w_object.get_dtype():
@@ -89,13 +92,12 @@
copy = True
if copy:
shape = w_object.get_shape()
- _elems_w = w_object.reshape(space, space.wrap(-1))
elems_w = [None] * w_object.get_size()
- for i in range(len(elems_w)):
- elems_w[i] = _elems_w.descr_getitem(space, space.wrap(i))
- elif subok:
- raise oefmt(space.w_NotImplementedError,
- "array(...copy=False, subok=True) not implemented yet")
+ elsize = w_object.get_dtype().elsize
+ # TODO - use w_object.implementation without copying to a list
+ # unfortunately that causes a union error in translation
+ for i in range(w_object.get_size()):
+ elems_w[i] = w_object.implementation.getitem(i * elsize)
else:
sz = support.product(w_object.get_shape()) * dtype.elsize
return W_NDimArray.from_shape_and_storage(space,
@@ -113,7 +115,7 @@
dtype = descriptor.variable_dtype(space, dtype.char + '1')
w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
- if len(elems_w) == 1:
+ if support.product(shape) == 1:
w_arr.set_scalar_value(dtype.coerce(space, elems_w[0]))
else:
loop.assign(space, w_arr, elems_w)
diff --git a/pypy/module/micronumpy/flatiter.py b/pypy/module/micronumpy/flatiter.py
--- a/pypy/module/micronumpy/flatiter.py
+++ b/pypy/module/micronumpy/flatiter.py
@@ -15,6 +15,7 @@
self._base = base
self.dtype = base.get_dtype()
self.shape = [base.get_size()]
+ self.storage = self._base.implementation.storage
def base(self):
return self._base
diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py
--- a/pypy/module/micronumpy/test/test_ndarray.py
+++ b/pypy/module/micronumpy/test/test_ndarray.py
@@ -2852,6 +2852,13 @@
c.flat = ['defgh', 'ijklmnop']
assert (c.flatten() == ['def', 'ijk']*5).all()
+ def test_flatiter_subtype(self):
+ from numpy import array
+ x = array([[1, 2], [3, 4]]).T
+ y = array(x.flat)
+ assert (x == [[1, 3], [2, 4]]).all()
+
+
def test_slice_copy(self):
from numpy import zeros
a = zeros((10, 10))
diff --git a/pypy/module/micronumpy/test/test_subtype.py b/pypy/module/micronumpy/test/test_subtype.py
--- a/pypy/module/micronumpy/test/test_subtype.py
+++ b/pypy/module/micronumpy/test/test_subtype.py
@@ -26,6 +26,12 @@
self.called_finalize = True
return SubType ''')
+ def test_subtype_ndarray(self):
+ from numpy import arange, array
+ a = arange(24, dtype='int32').reshape((6,4))
+ b = array(a, dtype='float64', subok=True)
+ assert (a == b).all()
+
def test_subtype_base(self):
from numpy import ndarray, dtype
class C(ndarray):
@@ -272,40 +278,103 @@
import numpy as N
# numpy's matrix class caused an infinite loop
class matrix(N.ndarray):
- getcnt = 0
def __new__(subtype, data, dtype=None, copy=True):
+ print('matrix __new__')
+ if isinstance(data, matrix):
+ dtype2 = data.dtype
+ if (dtype is None):
+ dtype = dtype2
+ if (dtype2 == dtype) and (not copy):
+ return data
+ return data.astype(dtype)
+
+ if isinstance(data, N.ndarray):
+ if dtype is None:
+ intype = data.dtype
+ else:
+ intype = N.dtype(dtype)
+ new = data.view(subtype)
+ if intype != data.dtype:
+ return new.astype(intype)
+ if copy: return new.copy()
+ else: return new
+
+ if isinstance(data, str):
+ data = _convert_from_string(data)
+
+ # now convert data to an array
arr = N.array(data, dtype=dtype, copy=copy)
+ ndim = arr.ndim
shape = arr.shape
+ if (ndim > 2):
+ raise ValueError("matrix must be 2-dimensional")
+ elif ndim == 0:
+ shape = (1, 1)
+ elif ndim == 1:
+ shape = (1, shape[0])
+
+ order = False
+ if (ndim == 2) and arr.flags.fortran:
+ order = True
+
+ if not (order or arr.flags.contiguous):
+ arr = arr.copy()
ret = N.ndarray.__new__(subtype, shape, arr.dtype,
buffer=arr,
- order=True)
+ order=order)
return ret
+ def __array_finalize__(self, obj):
+ print('matrix __array_finalize__')
+ self._getitem = False
+ if (isinstance(obj, matrix) and obj._getitem): return
+ ndim = self.ndim
+ if (ndim == 2):
+ return
+ if (ndim > 2):
+ newshape = tuple([x for x in self.shape if x > 1])
+ ndim = len(newshape)
+ if ndim == 2:
+ self.shape = newshape
+ return
+ elif (ndim > 2):
+ raise ValueError("shape too large to be a matrix.")
+ else:
+ newshape = self.shape
+ if ndim == 0:
+ self.shape = (1, 1)
+ elif ndim == 1:
+ self.shape = (1, newshape[0])
+ return
+
def __getitem__(self, index):
- matrix.getcnt += 1
- if matrix.getcnt > 10:
- # XXX strides.find_shape_and_elems is sensitive
- # to shape modification
- xxx
- out = N.ndarray.__getitem__(self, index)
+ print('matrix __getitem__')
+ self._getitem = True
+
+ try:
+ out = N.ndarray.__getitem__(self, index)
+ finally:
+ self._getitem = False
if not isinstance(out, N.ndarray):
return out
+
+ if out.ndim == 0:
+ return out[()]
+ if out.ndim == 1:
+ sh = out.shape[0]
# Determine when we should have a column array
- old_shape = out.shape
- if out.ndim < 2:
- sh = out.shape[0]
try:
n = len(index)
except:
n = 0
- if n > 1:
+ if n > 1 and isscalar(index[1]):
out.shape = (sh, 1)
else:
out.shape = (1, sh)
- #print 'out, shape was',old_shape,'now',out.shape,'out',out
return out
+
a = matrix([[1., 2.], [3., 4.]])
b = N.array([a])
assert (b == a).all()
@@ -318,6 +387,17 @@
assert len(b.shape) == 2
assert (b == a).all()
+ b = N.array(a, copy=True, dtype=int)
+ assert len(b.shape) == 2
+ assert (b == a).all()
+
+ c = matrix(a, copy=False)
+ assert c.base is not None
+ c[0, 0] = 100
+ assert a[0, 0] == 100
+ b = N.array(c, copy=True)
+ assert (b == a).all()
+
def test_setstate_no_version(self):
# Some subclasses of ndarray, like MaskedArray, do not use
# version in __setstare__
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -27,7 +27,7 @@
log = self.run(main, [libm_name])
pow_addr, res = log.result
assert res == 8.0 * 300
- py.test.xfail() # XXX re-optimize _ffi for the JIT?
+ py.test.skip("XXX re-optimize _ffi for the JIT?")
loop, = log.loops_by_filename(self.filepath)
if 'ConstClass(pow)' in repr(loop): # e.g. OS/X
pow_addr = 'ConstClass(pow)'
@@ -134,7 +134,7 @@
ops = loop.allops()
opnames = log.opnames(ops)
assert opnames.count('new_with_vtable') == 1 # only the virtualref
- py.test.xfail() # XXX re-optimize _ffi for the JIT?
+ py.test.skip("XXX re-optimize _ffi for the JIT?")
assert opnames.count('call_release_gil') == 1
idx = opnames.index('call_release_gil')
call = ops[idx]
@@ -159,7 +159,7 @@
return struct.getfield('x')
#
log = self.run(main, [])
- py.test.xfail() # XXX re-optimize _ffi for the JIT?
+ py.test.skip("XXX re-optimize _ffi for the JIT?")
loop, = log.loops_by_filename(self.filepath)
assert loop.match_by_id('getfield', """
guard_not_invalidated(descr=...)
diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py b/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py
--- a/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/test_ownlib.py
@@ -8,34 +8,137 @@
SOURCE = """\
#include <errno.h>
-int test_getting_errno(void) {
+#ifdef _WIN32
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT
+#endif
+
+EXPORT int test_getting_errno(void) {
errno = 123;
return -1;
}
-int test_setting_errno(void) {
+EXPORT int test_setting_errno(void) {
return errno;
+};
+
+typedef struct {
+ long x;
+ long y;
+} POINT;
+
+typedef struct {
+ long left;
+ long top;
+ long right;
+ long bottom;
+} RECT;
+
+
+EXPORT int PointInRect(RECT *prc, POINT pt)
+{
+ if (pt.x < prc->left)
+ return 0;
+ if (pt.x > prc->right)
+ return 0;
+ if (pt.y < prc->top)
+ return 0;
+ if (pt.y > prc->bottom)
More information about the pypy-commit
mailing list