[pypy-commit] pypy remove-iter-smm: hg merge default
Manuel Jacob
noreply at buildbot.pypy.org
Wed May 22 22:16:02 CEST 2013
Author: Manuel Jacob
Branch: remove-iter-smm
Changeset: r64478:b1e0c5ec2b32
Date: 2013-05-22 21:56 +0200
http://bitbucket.org/pypy/pypy/changeset/b1e0c5ec2b32/
Log: hg merge default
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
@@ -7,7 +7,7 @@
appleveldefs = {
}
interpleveldefs = {
- '__version__': 'space.wrap("0.6")',
+ '__version__': 'space.wrap("0.7")',
'load_library': 'libraryobj.load_library',
@@ -30,6 +30,8 @@
'typeoffsetof': 'func.typeoffsetof',
'rawaddressof': 'func.rawaddressof',
'getcname': 'func.getcname',
+ 'newp_handle': 'handle.newp_handle',
+ 'from_handle': 'handle.from_handle',
'_get_types': 'func._get_types',
'string': 'func.string',
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -394,6 +394,19 @@
return self.length
+class W_CDataHandle(W_CData):
+ _attrs_ = ['w_keepalive']
+ _immutable_fields_ = ['w_keepalive']
+
+ def __init__(self, space, cdata, ctype, w_keepalive):
+ W_CData.__init__(self, space, cdata, ctype)
+ self.w_keepalive = w_keepalive
+
+ def _repr_extra(self):
+ w_repr = self.space.repr(self.w_keepalive)
+ return "handle to %s" % (self.space.str_w(w_repr),)
+
+
W_CData.typedef = TypeDef(
'CData',
__module__ = '_cffi_backend',
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -172,8 +172,8 @@
class W_CTypePointer(W_CTypePtrBase):
- _attrs_ = ['is_file', 'cache_array_type']
- _immutable_fields_ = ['is_file', 'cache_array_type?']
+ _attrs_ = ['is_file', 'cache_array_type', 'is_void_ptr']
+ _immutable_fields_ = ['is_file', 'cache_array_type?', 'is_void_ptr']
kind = "pointer"
cache_array_type = None
@@ -186,6 +186,7 @@
extra = " *"
self.is_file = (ctitem.name == "struct _IO_FILE" or
ctitem.name == "struct $FILE")
+ self.is_void_ptr = isinstance(ctitem, ctypevoid.W_CTypeVoid)
W_CTypePtrBase.__init__(self, space, size, extra, 2, ctitem)
def newp(self, w_init):
diff --git a/pypy/module/_cffi_backend/handle.py b/pypy/module/_cffi_backend/handle.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cffi_backend/handle.py
@@ -0,0 +1,93 @@
+import weakref
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.gateway import unwrap_spec
+from pypy.module._cffi_backend import ctypeobj, ctypeptr, cdataobj
+from pypy.module._weakref.interp__weakref import dead_ref
+from rpython.rtyper.lltypesystem import lltype, rffi
+
+
+def reduced_value(s):
+ while True:
+ divide = s & 1
+ s >>= 1
+ if not divide:
+ return s
+
+# ____________________________________________________________
+
+
+class CffiHandles:
+ def __init__(self, space):
+ self.handles = []
+ self.look_distance = 0
+
+ def reserve_next_handle_index(self):
+ # The reservation ordering done here is tweaked for pypy's
+ # memory allocator. We look from index 'look_distance'.
+ # Look_distance increases from 0. But we also look at
+ # "look_distance/2" or "/4" or "/8", etc. If we find that one
+ # of these secondary locations is free, we assume it's because
+ # there was recently a minor collection; so we reset
+ # look_distance to 0 and start again from the lowest locations.
+ length = len(self.handles)
+ for d in range(self.look_distance, length):
+ if self.handles[d]() is None:
+ self.look_distance = d + 1
+ return d
+ s = reduced_value(d)
+ if self.handles[s]() is None:
+ break
+ # restart from the beginning
+ for d in range(0, length):
+ if self.handles[d]() is None:
+ self.look_distance = d + 1
+ return d
+ # full! extend, but don't use '!=' here
+ self.handles = self.handles + [dead_ref] * (length // 3 + 5)
+ self.look_distance = length + 1
+ return length
+
+ def store_handle(self, index, content):
+ self.handles[index] = weakref.ref(content)
+
+ def fetch_handle(self, index):
+ if 0 <= index < len(self.handles):
+ return self.handles[index]()
+ return None
+
+def get(space):
+ return space.fromcache(CffiHandles)
+
+# ____________________________________________________________
+
+ at unwrap_spec(w_ctype=ctypeobj.W_CType)
+def newp_handle(space, w_ctype, w_x):
+ if (not isinstance(w_ctype, ctypeptr.W_CTypePointer) or
+ not w_ctype.is_void_ptr):
+ raise operationerrfmt(space.w_TypeError,
+ "needs 'void *', got '%s'", w_ctype.name)
+ index = get(space).reserve_next_handle_index()
+ _cdata = rffi.cast(rffi.CCHARP, index + 1)
+ new_cdataobj = cdataobj.W_CDataHandle(space, _cdata, w_ctype, w_x)
+ get(space).store_handle(index, new_cdataobj)
+ return new_cdataobj
+
+ at unwrap_spec(w_cdata=cdataobj.W_CData)
+def from_handle(space, w_cdata):
+ ctype = w_cdata.ctype
+ if (not isinstance(ctype, ctypeptr.W_CTypePtrOrArray) or
+ not ctype.can_cast_anything):
+ raise operationerrfmt(space.w_TypeError,
+ "expected a 'cdata' object with a 'void *' out "
+ "of new_handle(), got '%s'", ctype.name)
+ index = rffi.cast(lltype.Signed, w_cdata._cdata)
+ original_cdataobj = get(space).fetch_handle(index - 1)
+ #
+ if isinstance(original_cdataobj, cdataobj.W_CDataHandle):
+ return original_cdataobj.w_keepalive
+ else:
+ if index == 0:
+ msg = "cannot use from_handle() on NULL pointer"
+ else:
+ msg = "'void *' value does not correspond to any object"
+ raise OperationError(space.w_RuntimeError, space.wrap(msg))
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
@@ -2732,6 +2732,32 @@
assert x != cast(BIntP, 12344)
assert hash(x) == hash(cast(BIntP, 12345))
+def test_new_handle():
+ import _weakref
+ BVoidP = new_pointer_type(new_void_type())
+ BCharP = new_pointer_type(new_primitive_type("char"))
+ class mylist(list):
+ pass
+ o = mylist([2, 3, 4])
+ x = newp_handle(BVoidP, o)
+ assert repr(x) == "<cdata 'void *' handle to [2, 3, 4]>"
+ assert x
+ assert from_handle(x) is o
+ assert from_handle(cast(BCharP, x)) is o
+ wr = _weakref.ref(o)
+ del o
+ import gc; gc.collect()
+ assert wr() is not None
+ assert from_handle(x) == list((2, 3, 4))
+ assert from_handle(cast(BCharP, x)) == list((2, 3, 4))
+ del x
+ for i in range(3):
+ if wr() is not None:
+ import gc; gc.collect()
+ assert wr() is None
+ py.test.raises(RuntimeError, from_handle, cast(BCharP, 0))
+
+
def test_version():
# this test is here mostly for PyPy
- assert __version__ == "0.6"
+ assert __version__ == "0.7"
diff --git a/pypy/module/_cffi_backend/test/test_handle.py b/pypy/module/_cffi_backend/test/test_handle.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cffi_backend/test/test_handle.py
@@ -0,0 +1,59 @@
+import random
+from pypy.module._cffi_backend.handle import CffiHandles, reduced_value
+
+
+def test_reduced_value():
+ assert reduced_value(0) == 0
+ assert reduced_value(1) == 0
+ assert reduced_value(2) == 1
+ assert reduced_value(3) == 0
+ assert reduced_value(4) == 2
+ assert reduced_value(5) == 1
+ assert reduced_value(6) == 3
+ assert reduced_value(7) == 0
+ assert reduced_value(8) == 4
+ assert reduced_value(9) == 2
+ assert reduced_value(10) == 5
+ assert reduced_value(11) == 1
+
+
+class PseudoWeakRef(object):
+ _content = 42
+
+ def __call__(self):
+ return self._content
+
+
+def test_cffi_handles_1():
+ ch = CffiHandles(None)
+ expected_content = {}
+ for i in range(10000):
+ index = ch.reserve_next_handle_index()
+ assert 0 <= index < len(ch.handles)
+ assert ch.handles[index]() is None
+ pwr = PseudoWeakRef()
+ expected_content[index] = pwr
+ ch.handles[index] = pwr
+ assert len(ch.handles) < 13500
+ for index, pwr in expected_content.items():
+ assert ch.handles[index] is pwr
+
+def test_cffi_handles_2():
+ ch = CffiHandles(None)
+ expected_content = {}
+ for i in range(10000):
+ index = ch.reserve_next_handle_index()
+ assert 0 <= index < len(ch.handles)
+ assert ch.handles[index]() is None
+ pwr = PseudoWeakRef()
+ expected_content[index] = pwr
+ ch.handles[index] = pwr
+ #
+ if len(expected_content) > 20:
+ r = random.choice(list(expected_content))
+ pwr = expected_content.pop(r)
+ pwr._content = None
+ #
+ assert len(ch.handles) < 100
+ for index, pwr in expected_content.items():
+ assert ch.handles[index] is pwr
diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -11,7 +11,6 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib.rawstorage import free_raw_storage, raw_storage_getitem,\
raw_storage_setitem, RAW_STORAGE
-from pypy.module.micronumpy.arrayimpl.sort import argsort_array
from rpython.rlib.debug import make_sure_not_resized
@@ -70,6 +69,7 @@
new_backstrides = [0] * ndims
for nd in range(ndims):
new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd]
+ assert isinstance(orig_array, W_NDimArray) or orig_array is None
return SliceArray(self.start, new_strides, new_backstrides,
new_shape, self, orig_array)
else:
@@ -324,6 +324,7 @@
orig_array)
def argsort(self, space, w_axis):
+ from pypy.module.micronumpy.arrayimpl.sort import argsort_array
return argsort_array(self, space, w_axis)
def base(self):
@@ -356,13 +357,13 @@
self.strides = strides
self.backstrides = backstrides
self.shape = shape
+ if dtype is None:
+ dtype = parent.dtype
if isinstance(parent, SliceArray):
parent = parent.parent # one level only
self.parent = parent
self.storage = parent.storage
self.order = parent.order
- if dtype is None:
- dtype = parent.dtype
self.dtype = dtype
self.size = support.product(shape) * self.dtype.itemtype.get_element_size()
self.start = start
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -2,6 +2,7 @@
from pypy.module.micronumpy.arrayimpl import base
from pypy.module.micronumpy.base import W_NDimArray, convert_to_array
from pypy.module.micronumpy import support
+from pypy.module.micronumpy.interp_boxes import W_GenericBox
from pypy.interpreter.error import OperationError
class ScalarIterator(base.BaseArrayIterator):
@@ -48,6 +49,7 @@
return self.value
def set_scalar_value(self, w_val):
+ assert isinstance(w_val, W_GenericBox)
self.value = w_val.convert_to(self.dtype)
def copy(self, space):
@@ -73,7 +75,7 @@
dtype = self.dtype.float_type or self.dtype
if len(w_arr.get_shape()) > 0:
raise OperationError(space.w_ValueError, space.wrap(
- "could not broadcast input array from shape " +
+ "could not broadcast input array from shape " +
"(%s) into shape ()" % (
','.join([str(x) for x in w_arr.get_shape()],))))
if self.dtype.is_complex_type():
@@ -102,7 +104,7 @@
dtype = self.dtype.float_type
if len(w_arr.get_shape()) > 0:
raise OperationError(space.w_ValueError, space.wrap(
- "could not broadcast input array from shape " +
+ "could not broadcast input array from shape " +
"(%s) into shape ()" % (
','.join([str(x) for x in w_arr.get_shape()],))))
self.value = self.dtype.itemtype.composite(
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -27,10 +27,10 @@
from pypy.module.micronumpy.arrayimpl import concrete, scalar
if not shape:
- impl = scalar.Scalar(dtype)
+ impl = scalar.Scalar(dtype.base)
else:
- strides, backstrides = calc_strides(shape, dtype, order)
- impl = concrete.ConcreteArray(shape, dtype, order, strides,
+ strides, backstrides = calc_strides(shape, dtype.base, order)
+ impl = concrete.ConcreteArray(shape, dtype.base, order, strides,
backstrides)
return W_NDimArray(impl)
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -268,14 +268,30 @@
class W_VoidBox(W_FlexibleBox):
- @unwrap_spec(item=str)
- def descr_getitem(self, space, item):
+ def descr_getitem(self, space, w_item):
+ from pypy.module.micronumpy.types import VoidType
+ if space.isinstance_w(w_item, space.w_str):
+ item = space.str_w(w_item)
+ elif space.isinstance_w(w_item, space.w_int):
+ #Called by iterator protocol
+ indx = space.int_w(w_item)
+ try:
+ item = self.dtype.fieldnames[indx]
+ except IndexError:
+ raise OperationError(space.w_IndexError,
+ space.wrap("Iterated over too many fields %d" % indx))
+ else:
+ raise OperationError(space.w_IndexError, space.wrap(
+ "Can only access fields of record with int or str"))
try:
ofs, dtype = self.dtype.fields[item]
except KeyError:
raise OperationError(space.w_IndexError,
space.wrap("Field %s does not exist" % item))
- read_val = dtype.itemtype.read(self.arr, self.ofs, ofs, dtype)
+ if isinstance(dtype.itemtype, VoidType):
+ read_val = dtype.itemtype.readarray(self.arr, self.ofs, ofs, dtype)
+ else:
+ read_val = dtype.itemtype.read(self.arr, self.ofs, ofs, dtype)
if isinstance (read_val, W_StringBox):
# StringType returns a str
return space.wrap(dtype.itemtype.to_str(read_val))
@@ -373,7 +389,7 @@
W_LongDoubleBox = W_Float64Box
W_CLongDoubleBox = W_Complex64Box
-
+
W_GenericBox.typedef = TypeDef("generic",
__module__ = "numpypy",
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -46,11 +46,11 @@
class W_Dtype(W_Root):
- _immutable_fields_ = ["itemtype", "num", "kind"]
+ _immutable_fields_ = ["itemtype", "num", "kind", "shape"]
def __init__(self, itemtype, num, kind, name, char, w_box_type,
alternate_constructors=[], aliases=[],
- fields=None, fieldnames=None, native=True):
+ fields=None, fieldnames=None, native=True, shape=[], subdtype=None):
self.itemtype = itemtype
self.num = num
self.kind = kind
@@ -63,6 +63,12 @@
self.fieldnames = fieldnames
self.native = native
self.float_type = None
+ self.shape = list(shape)
+ self.subdtype = subdtype
+ if not subdtype:
+ self.base = self
+ else:
+ self.base = subdtype.base
@specialize.argtype(1)
def box(self, value):
@@ -78,7 +84,8 @@
return self.itemtype.coerce(space, self, w_item)
def getitem(self, arr, i):
- return self.itemtype.read(arr, i, 0)
+ item = self.itemtype.read(arr, i, 0)
+ return item
def getitem_bool(self, arr, i):
return self.itemtype.read_bool(arr, i, 0)
@@ -111,8 +118,15 @@
def descr_get_alignment(self, space):
return space.wrap(self.itemtype.alignment)
+ def descr_get_base(self, space):
+ return space.wrap(self.base)
+
+ def descr_get_subdtype(self, space):
+ return space.newtuple([space.wrap(self.subdtype), self.descr_get_shape(space)])
+
def descr_get_shape(self, space):
- return space.newtuple([])
+ w_shape = [space.wrap(dim) for dim in self.shape]
+ return space.newtuple(w_shape)
def eq(self, space, w_other):
w_other = space.call_function(space.gettypefor(W_Dtype), w_other)
@@ -279,15 +293,22 @@
ofs_and_items = []
fieldnames = []
for w_elem in lst_w:
- w_fldname, w_flddesc = space.fixedview(w_elem, 2)
- subdtype = descr__new__(space, space.gettypefor(W_Dtype), w_flddesc)
+ size = 1
+ w_shape = space.newtuple([])
+ if space.len_w(w_elem) == 3:
+ w_fldname, w_flddesc, w_shape = space.fixedview(w_elem)
+ if not base.issequence_w(space, w_shape):
+ w_shape = space.newtuple([w_shape,])
+ else:
+ w_fldname, w_flddesc = space.fixedview(w_elem)
+ subdtype = descr__new__(space, space.gettypefor(W_Dtype), w_flddesc, w_shape=w_shape)
fldname = space.str_w(w_fldname)
if fldname in fields:
raise OperationError(space.w_ValueError, space.wrap("two fields with the same name"))
assert isinstance(subdtype, W_Dtype)
fields[fldname] = (offset, subdtype)
ofs_and_items.append((offset, subdtype.itemtype))
- offset += subdtype.itemtype.get_element_size()
+ offset += subdtype.itemtype.get_element_size() * size
fieldnames.append(fldname)
itemtype = types.RecordType(ofs_and_items, offset)
return W_Dtype(itemtype, 20, VOIDLTR, "void" + str(8 * itemtype.get_element_size()),
@@ -333,10 +354,24 @@
raise OperationError(space.w_NotImplementedError, space.wrap(
"dtype from spec"))
-def descr__new__(space, w_subtype, w_dtype, w_align=None, w_copy=None):
+def descr__new__(space, w_subtype, w_dtype, w_align=None, w_copy=None, w_shape=None):
# w_align and w_copy are necessary for pickling
cache = get_dtype_cache(space)
+ if w_shape is not None and (space.isinstance_w(w_shape, space.w_int) or space.len_w(w_shape) > 0):
+ subdtype = descr__new__(space, w_subtype, w_dtype, w_align, w_copy)
+ assert isinstance(subdtype, W_Dtype)
+ size = 1
+ if space.isinstance_w(w_shape, space.w_int):
+ w_shape = space.newtuple([w_shape])
+ shape = []
+ for w_dim in space.fixedview(w_shape):
+ dim = space.int_w(w_dim)
+ shape.append(dim)
+ size *= dim
+ return W_Dtype(types.VoidType(subdtype.itemtype.get_element_size() * size), 20, VOIDLTR, "void" + str(8 * subdtype.itemtype.get_element_size() * size),
+ "V", space.gettypefor(interp_boxes.W_VoidBox), shape=shape, subdtype=subdtype)
+
if space.is_none(w_dtype):
return cache.w_float64dtype
elif space.isinstance_w(w_dtype, w_subtype):
@@ -355,6 +390,8 @@
"data type %s not understood" % name))
elif space.isinstance_w(w_dtype, space.w_list):
return dtype_from_list(space, w_dtype)
+ elif space.isinstance_w(w_dtype, space.w_tuple):
+ return descr__new__(space, w_subtype, space.getitem(w_dtype, space.wrap(0)), w_align, w_copy, w_shape=space.getitem(w_dtype, space.wrap(1)))
elif space.isinstance_w(w_dtype, space.w_dict):
return dtype_from_dict(space, w_dtype)
for dtype in cache.builtin_dtypes:
@@ -391,6 +428,8 @@
name = interp_attrproperty('name', cls=W_Dtype),
fields = GetSetProperty(W_Dtype.descr_get_fields),
names = GetSetProperty(W_Dtype.descr_get_names),
+ subdtype = GetSetProperty(W_Dtype.descr_get_subdtype),
+ base = GetSetProperty(W_Dtype.descr_get_base),
)
W_Dtype.typedef.acceptable_as_base_class = False
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -21,7 +21,7 @@
from rpython.rlib.rstring import StringBuilder
from pypy.module.micronumpy.arrayimpl.base import BaseArrayImplementation
-def _find_shape(space, w_size):
+def _find_shape(space, w_size, dtype):
if space.is_none(w_size):
return []
if space.isinstance_w(w_size, space.w_int):
@@ -29,6 +29,7 @@
shape = []
for w_item in space.fixedview(w_size):
shape.append(space.int_w(w_item))
+ shape += dtype.shape
return shape[:]
class __extend__(W_NDimArray):
@@ -829,7 +830,7 @@
space.wrap("unsupported param"))
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
- shape = _find_shape(space, w_shape)
+ shape = _find_shape(space, w_shape, dtype)
if not shape:
return W_NDimArray.new_scalar(space, dtype)
return W_NDimArray.from_shape(shape, dtype)
@@ -842,10 +843,10 @@
"""
from rpython.rtyper.lltypesystem import rffi
from rpython.rlib.rawstorage import RAW_STORAGE_PTR
- shape = _find_shape(space, w_shape)
storage = rffi.cast(RAW_STORAGE_PTR, addr)
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
+ shape = _find_shape(space, w_shape, dtype)
return W_NDimArray.from_shape_and_storage(shape, storage, dtype)
W_NDimArray.typedef = TypeDef(
@@ -1029,7 +1030,7 @@
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
)
- shape = _find_shape(space, w_shape)
+ shape = _find_shape(space, w_shape, dtype)
if not shape:
return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
return space.wrap(W_NDimArray.from_shape(shape, dtype=dtype, order=order))
@@ -1039,7 +1040,7 @@
dtype = space.interp_w(interp_dtype.W_Dtype,
space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
)
- shape = _find_shape(space, w_shape)
+ shape = _find_shape(space, w_shape, dtype)
if not shape:
return W_NDimArray.new_scalar(space, dtype, space.wrap(0))
arr = W_NDimArray.from_shape(shape, dtype=dtype, order=order)
diff --git a/pypy/module/micronumpy/iter.py b/pypy/module/micronumpy/iter.py
--- a/pypy/module/micronumpy/iter.py
+++ b/pypy/module/micronumpy/iter.py
@@ -32,13 +32,13 @@
shape dimension
which is back 25 and forward 1,
which is x.strides[1] * (x.shape[1] - 1) + x.strides[0]
-so if we precalculate the overflow backstride as
+so if we precalculate the overflow backstride as
[x.strides[i] * (x.shape[i] - 1) for i in range(len(x.shape))]
we can go faster.
All the calculations happen in next()
next_skip_x() tries to do the iteration for a number of steps at once,
-but then we cannot gaurentee that we only overflow one single shape
+but then we cannot gaurentee that we only overflow one single shape
dimension, perhaps we could overflow times in one big step.
"""
@@ -170,7 +170,8 @@
self.dtype.setitem(self.array, self.offset, elem)
def getitem(self):
- return self.dtype.getitem(self.array, self.offset)
+ item = self.dtype.getitem(self.array, self.offset)
+ return item
def getitem_bool(self):
return self.dtype.getitem_bool(self.array, self.offset)
@@ -288,12 +289,13 @@
self.dim = dim
self.array = array
self.dtype = array.dtype
-
+
def setitem(self, elem):
self.dtype.setitem(self.array, self.offset, elem)
def getitem(self):
- return self.dtype.getitem(self.array, self.offset)
+ item = self.dtype.getitem(self.array, self.offset)
+ return item
@jit.unroll_safe
def next(self):
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -275,7 +275,7 @@
from numpypy import array, dtype
from cPickle import loads, dumps
a = array([1,2,3])
- if self.ptr_size == 8:
+ if self.ptr_size == 8:
assert a.dtype.__reduce__() == (dtype, ('i8', 0, 1), (3, '<', None, None, None, -1, -1, 0))
else:
assert a.dtype.__reduce__() == (dtype, ('i4', 0, 1), (3, '<', None, None, None, -1, -1, 0))
@@ -726,7 +726,7 @@
x = int8(42).ravel()
assert x.dtype == int8
assert (x == array(42)).all()
-
+
class AppTestStrUnicodeDtypes(BaseNumpyAppTest):
@@ -781,6 +781,7 @@
assert d.num == 20
assert d.itemsize == 20
assert d.kind == 'V'
+ assert d.base == d
assert d.type is void
assert d.char == 'V'
assert d.names == ("x", "y", "z", "value")
@@ -793,6 +794,27 @@
d = dtype({'names': ['a', 'b', 'c'],
})
+ def test_create_subarrays(self):
+ from numpypy import dtype
+ d = dtype([("x", "float", (2,)), ("y", "int", (2,))])
+ assert d.itemsize == 32
+ assert d.name == "void256"
+ keys = d.fields.keys()
+ assert "x" in keys
+ assert "y" in keys
+ assert d["x"].shape == (2,)
+ assert d["x"].itemsize == 16
+ e = dtype([("x", "float", 2), ("y", "int", 2)])
+ assert e.fields.keys() == keys
+ assert e['x'].shape == (2,)
+
+ dt = dtype((float, 10))
+ assert dt.shape == (10,)
+ assert dt.kind == 'V'
+ assert dt.fields == None
+ assert dt.subdtype == (dtype(float), (10,))
+ assert dt.base == dtype(float)
+
class AppTestNotDirect(BaseNumpyAppTest):
def setup_class(cls):
BaseNumpyAppTest.setup_class.im_func(cls)
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -18,10 +18,12 @@
def get_element_size():
return 1
+ def __init__(self):
+ self.base = self
+
def get_size(self):
return 1
-
def create_slice(a, chunks):
return Chunks(chunks).apply(W_NDimArray(a)).implementation
@@ -2699,6 +2701,56 @@
assert a[0]['y'] == 2
assert a[1]['y'] == 1
+ def test_subarrays(self):
+ from numpypy import dtype, array, zeros
+
+ d = dtype([("x", "int", 3), ("y", "float", 5)])
+ a = array([([1, 2, 3], [0.5, 1.5, 2.5, 3.5, 4.5]), ([4, 5, 6], [5.5, 6.5, 7.5, 8.5, 9.5])], dtype=d)
+
+ assert (a[0]["x"] == [1, 2, 3]).all()
+ assert (a[0]["y"] == [0.5, 1.5, 2.5, 3.5, 4.5]).all()
+ assert (a[1]["x"] == [4, 5, 6]).all()
+ assert (a[1]["y"] == [5.5, 6.5, 7.5, 8.5, 9.5]).all()
+
+ a[0]["x"][0] = 200
+ assert a[0]["x"][0] == 200
+
+ d = dtype([("x", "int", (2, 3))])
+ a = array([([[1, 2, 3], [4, 5, 6]],)], dtype=d)
+
+ assert a[0]["x"].dtype == dtype("int64")
+ assert a[0]["x"][0].dtype == dtype("int64")
+
+ assert (a[0]["x"][0] == [1, 2, 3]).all()
+ assert (a[0]["x"] == [[1, 2, 3], [4, 5, 6]]).all()
+
+ d = dtype((float, (10, 10)))
+ a = zeros((3,3), dtype=d)
+ assert a[0, 0].shape == (10, 10)
+ assert a.shape == (3, 3, 10, 10)
+ a[0, 0] = 500
+ assert (a[0, 0, 0] == 500).all()
+ assert a[0, 0, 0].shape == (10,)
+
+ def test_multidim_subarray(self):
+ from numpypy import dtype, array
+
+ d = dtype([("x", "int", (2, 3))])
+ a = array([([[1, 2, 3], [4, 5, 6]],)], dtype=d)
+
+ assert a[0]["x"].dtype == dtype("int64")
+ assert a[0]["x"][0].dtype == dtype("int64")
+
+ assert (a[0]["x"][0] == [1, 2, 3]).all()
+ assert (a[0]["x"] == [[1, 2, 3], [4, 5, 6]]).all()
+
+ def test_list_record(self):
+ from numpypy import dtype, array
+
+ d = dtype([("x", "int", 3), ("y", "float", 5)])
+ a = array([([1, 2, 3], [0.5, 1.5, 2.5, 3.5, 4.5]), ([4, 5, 6], [5.5, 6.5, 7.5, 8.5, 9.5])], dtype=d)
+
+ assert len(list(a[0])) == 2
class AppTestPyPy(BaseNumpyAppTest):
def setup_class(cls):
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -3,7 +3,9 @@
from pypy.interpreter.error import OperationError
from pypy.module.micronumpy import interp_boxes
+from pypy.module.micronumpy import support
from pypy.module.micronumpy.arrayimpl.voidbox import VoidBoxStorage
+from pypy.module.micronumpy.arrayimpl.concrete import SliceArray
from pypy.objspace.std.floatobject import float2string
from pypy.objspace.std.complexobject import str_format
from rpython.rlib import rfloat, clibffi, rcomplex
@@ -1076,7 +1078,7 @@
def to_builtin_type(self, space, box):
real,imag = self.for_computation(self.unbox(box))
- return space.newcomplex(real, imag)
+ return space.newcomplex(real, imag)
def read_bool(self, arr, i, offset):
v = self.for_computation(self._read(arr.storage, i, offset))
@@ -1217,7 +1219,7 @@
@raw_binary_op
def le(self, v1, v2):
- return self._lt(v1, v2) or self._eq(v1, v2)
+ return self._lt(v1, v2) or self._eq(v1, v2)
@raw_binary_op
def gt(self, v1, v2):
@@ -1225,7 +1227,7 @@
@raw_binary_op
def ge(self, v1, v2):
- return self._lt(v2, v1) or self._eq(v2, v1)
+ return self._lt(v2, v1) or self._eq(v2, v1)
def _bool(self, v):
return bool(v[0]) or bool(v[1])
@@ -1341,7 +1343,7 @@
return rcomplex.c_div((v[0], -v[1]), (a2, 0.))
except ZeroDivisionError:
return rfloat.NAN, rfloat.NAN
-
+
# No floor, ceil, trunc in numpy for complex
#@simple_unary_op
#def floor(self, v):
@@ -1684,6 +1686,7 @@
return space.wrap(self.to_str(box))
def build_and_convert(self, space, mydtype, box):
+ assert isinstance(box, interp_boxes.W_GenericBox)
if box.get_dtype(space).is_str_or_unicode():
arg = box.get_dtype(space).itemtype.to_str(box)
else:
@@ -1696,10 +1699,68 @@
for j in range(i + 1, self.size):
arr.storage[j] = '\x00'
return interp_boxes.W_StringBox(arr, 0, arr.dtype)
-
+
class VoidType(BaseType, BaseStringType):
T = lltype.Char
+ def _coerce(self, space, arr, ofs, dtype, w_items, shape):
+ items_w = space.fixedview(w_items)
+ for i in range(len(items_w)):
+ subdtype = dtype.subdtype
+ itemtype = subdtype.itemtype
+ if space.len_w(shape) <= 1:
+ w_box = itemtype.coerce(space, dtype.subdtype, items_w[i])
+ itemtype.store(arr, 0, ofs, w_box)
+ ofs += itemtype.get_element_size()
+ else:
+ size = 1
+ for dimension in shape[1:]:
+ size *= dimension
+ size *= itemtype.get_element_size()
+ for w_item in items_w:
+ self._coerce(space, arr, ofs, dtype, w_items, shape[1:])
+ ofs += size
+ return arr
+
+ def _coerce(self, space, arr, ofs, dtype, w_items, shape):
+ # TODO: Make sure the shape and the array match
+ items_w = space.fixedview(w_items)
+ subdtype = dtype.subdtype
+ itemtype = subdtype.itemtype
+ if len(shape) <= 1:
+ for i in range(len(items_w)):
+ w_box = itemtype.coerce(space, dtype.subdtype, items_w[i])
+ itemtype.store(arr, 0, ofs, w_box)
+ ofs += itemtype.get_element_size()
+ else:
+ for w_item in items_w:
+ size = 1
+ for dimension in shape[1:]:
+ size *= dimension
+ size *= itemtype.get_element_size()
+ self._coerce(space, arr, ofs, dtype, w_item, shape[1:])
+ ofs += size
+
+ def coerce(self, space, dtype, w_items):
+ arr = VoidBoxStorage(self.size, dtype)
+ self._coerce(space, arr, 0, dtype, w_items, dtype.shape)
+ return interp_boxes.W_VoidBox(arr, 0, dtype)
+
+ @jit.unroll_safe
+ def store(self, arr, i, ofs, box):
+ assert isinstance(box, interp_boxes.W_VoidBox)
+ for k in range(self.get_element_size()):
+ arr.storage[k + ofs] = box.arr.storage[k + box.ofs]
+
+ def readarray(self, arr, i, offset, dtype=None):
+ from pypy.module.micronumpy.base import W_NDimArray
+ if dtype is None:
+ dtype = arr.dtype
+ strides, backstrides = support.calc_strides(dtype.shape, dtype.subdtype, arr.order)
+ implementation = SliceArray(i + offset, strides, backstrides,
+ dtype.shape, arr, W_NDimArray(arr), dtype.subdtype)
+ return W_NDimArray(implementation)
+
NonNativeVoidType = VoidType
NonNativeStringType = StringType
@@ -1733,7 +1794,7 @@
if not space.issequence_w(w_item):
raise OperationError(space.w_TypeError, space.wrap(
"expected sequence"))
- if len(self.offsets_and_fields) != space.int_w(space.len(w_item)):
+ if len(self.offsets_and_fields) != space.len_w(w_item):
raise OperationError(space.w_ValueError, space.wrap(
"wrong length"))
items_w = space.fixedview(w_item)
diff --git a/pypy/objspace/std/specialisedtupleobject.py b/pypy/objspace/std/specialisedtupleobject.py
--- a/pypy/objspace/std/specialisedtupleobject.py
+++ b/pypy/objspace/std/specialisedtupleobject.py
@@ -74,7 +74,7 @@
def descr_eq(self, space, w_other):
if not isinstance(w_other, W_AbstractTupleObject):
- return space.w_NotImplementedError
+ return space.w_NotImplemented
if not isinstance(w_other, cls):
if nValues != w_other.length():
return space.w_False
diff --git a/pypy/objspace/std/test/test_specialisedtupleobject.py b/pypy/objspace/std/test/test_specialisedtupleobject.py
--- a/pypy/objspace/std/test/test_specialisedtupleobject.py
+++ b/pypy/objspace/std/test/test_specialisedtupleobject.py
@@ -216,4 +216,4 @@
class AppTestAll(test_tupleobject.AppTestW_TupleObject):
- pass
+ spaceconfig = {"objspace.std.withspecialisedtuple": True}
diff --git a/pypy/objspace/std/test/test_tupleobject.py b/pypy/objspace/std/test/test_tupleobject.py
--- a/pypy/objspace/std/test/test_tupleobject.py
+++ b/pypy/objspace/std/test/test_tupleobject.py
@@ -399,3 +399,11 @@
assert ((5,) != (N,)) is True
assert ((5,) > (N,)) is False
assert ((5,) >= (N,)) is False
+
+ def test_eq_other_type(self):
+ assert (() == object()) is False
+ assert ((1,) == object()) is False
+ assert ((1, 2) == object()) is False
+ assert (() != object()) is True
+ assert ((1,) != object()) is True
+ assert ((1, 2) != object()) is True
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -621,7 +621,8 @@
tobox = self.metainterp.heapcache.getfield(box, fielddescr)
if tobox is valuebox:
return
- self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox)
+ if tobox is not None or not self.metainterp.heapcache.is_unescaped(box) or not isinstance(valuebox, Const) or valuebox.nonnull():
+ self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox)
self.metainterp.heapcache.setfield(box, valuebox, fielddescr)
opimpl_setfield_gc_i = _opimpl_setfield_gc_any
opimpl_setfield_gc_r = _opimpl_setfield_gc_any
diff --git a/rpython/jit/metainterp/test/test_tracingopts.py b/rpython/jit/metainterp/test/test_tracingopts.py
--- a/rpython/jit/metainterp/test/test_tracingopts.py
+++ b/rpython/jit/metainterp/test/test_tracingopts.py
@@ -645,3 +645,20 @@
res = self.interp_operations(fn, [1])
assert res == -1
self.check_operations_history(guard_class=0)
+
+ def test_dont_record_setfield_gc_zeros(self):
+ class A(object):
+ pass
+
+ def make_a():
+ return A()
+ make_a._dont_inline_ = True
+
+ def fn(n):
+ a = make_a()
+ a.x = jit.promote(n)
+ return a.x
+
+ res = self.interp_operations(fn, [0])
+ assert res == 0
+ self.check_operations_history(setfield_gc=0)
More information about the pypy-commit
mailing list