Author: Amaury Forgeot d'Arc <amaur...@gmail.com> Branch: py3k Changeset: r75869:2f2ec61d2d55 Date: 2015-02-14 13:31 +0100 http://bitbucket.org/pypy/pypy/changeset/2f2ec61d2d55/
Log: hg merge default diff too long, truncating to 2000 out of 3186 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 @@ -11,7 +11,7 @@ if cls == (_CData,): # this is the Array class defined below return res - ffiarray = res._ffiarray = _rawffi.Array(res._type_._ffishape) + ffiarray = res._ffiarray = _rawffi.Array(res._type_._ffishape_) subletter = getattr(res._type_, '_type_', None) if subletter == 'c': def getvalue(self): @@ -58,8 +58,8 @@ target[len(val)] = '\x00' res.value = property(getvalue, setvalue) - res._ffishape = (ffiarray, res._length_) - res._fficompositesize = res._sizeofinstances() + res._ffishape_ = (ffiarray, res._length_) + res._fficompositesize_ = res._sizeofinstances() return res from_address = cdata_from_address @@ -154,7 +154,7 @@ return l class Array(_CData, metaclass=ArrayMeta): - _ffiargshape = 'P' + _ffiargshape_ = 'P' def __init__(self, *args): if not hasattr(self, '_buffer'): @@ -189,13 +189,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 @@ -64,9 +64,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 @@ -97,7 +97,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) @@ -134,7 +134,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__) @@ -181,11 +181,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.maxsize * 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 @@ -223,15 +223,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,)) @@ -243,7 +243,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/_gdbm.py b/lib_pypy/_gdbm.py --- a/lib_pypy/_gdbm.py +++ b/lib_pypy/_gdbm.py @@ -1,5 +1,4 @@ -import cffi, os -import sys +import cffi, os, sys ffi = cffi.FFI() ffi.cdef(''' @@ -38,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/_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 @@ -2,7 +2,7 @@ import math import struct from fractions import gcd -from ctypes import create_string_buffer +from cffi import FFI _buffer = memoryview @@ -148,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): @@ -327,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): @@ -342,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) @@ -353,7 +355,7 @@ _put_sample(result, size, i // 2, sample) - return result.raw + return result[:] def tostereo(cp, size, fac1, fac2): @@ -361,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): @@ -382,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): @@ -428,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) @@ -443,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): @@ -470,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 @@ -482,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. + * b...@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/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py --- a/lib_pypy/pyrepl/readline.py +++ b/lib_pypy/pyrepl/readline.py @@ -77,6 +77,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 @@ -90,6 +91,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: @@ -208,14 +216,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 @@ -146,7 +146,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 @@ -162,7 +162,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 @@ -701,7 +701,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 @@ -24,17 +24,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 @@ -1141,10 +1141,10 @@ import _rawffi S = _rawffi.Structure((40, 1)) s = S(autofree=True) - addr = buffer(s)._pypy_raw_address() + addr = memoryview(s)._pypy_raw_address() assert type(addr) is int - assert buffer(s)._pypy_raw_address() == addr - assert buffer(s, 10)._pypy_raw_address() == addr + 10 + assert memoryview(s)._pypy_raw_address() == addr + assert memoryview(s)[10:]._pypy_raw_address() == addr + 10 def test_union(self): import _rawffi 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: + 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 @@ -2843,6 +2843,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 @@ -272,40 +272,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 +381,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) + return 0; + return 1; +}; + +EXPORT long left = 10; +EXPORT long top = 20; +EXPORT long right = 30; +EXPORT long bottom = 40; + +EXPORT RECT ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr, + RECT *er, POINT fp, RECT gr) +{ + /*Check input */ + if (ar.left + br->left + dr.left + er->left + gr.left != left * 5) + { + ar.left = 100; _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit