[pypy-commit] pypy fix-result-types: hg merge default
rlamy
noreply at buildbot.pypy.org
Wed May 13 19:52:35 CEST 2015
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: fix-result-types
Changeset: r77313:460e06d4da59
Date: 2015-05-13 18:52 +0100
http://bitbucket.org/pypy/pypy/changeset/460e06d4da59/
Log: hg merge default
diff too long, truncating to 2000 out of 2055 lines
diff --git a/lib-python/2.7/socket.py b/lib-python/2.7/socket.py
--- a/lib-python/2.7/socket.py
+++ b/lib-python/2.7/socket.py
@@ -145,6 +145,34 @@
name = hostname
return name
+class RefCountingWarning(UserWarning):
+ pass
+
+def _do_reuse_or_drop(socket, methname):
+ try:
+ method = getattr(socket, methname)
+ except (AttributeError, TypeError):
+ warnings.warn("""'%s' object has no _reuse/_drop methods
+{{
+ You make use (or a library you are using makes use) of the internal
+ classes '_socketobject' and '_fileobject' in socket.py, initializing
+ them with custom objects. On PyPy, these custom objects need two
+ extra methods, _reuse() and _drop(), that maintain an explicit
+ reference counter. When _drop() has been called as many times as
+ _reuse(), then the object should be freed.
+
+ Without these methods, you get the warning here. This is to
+ prevent the following situation: if your (or the library's) code
+ relies on reference counting for prompt closing, then on PyPy, the
+ __del__ method will be called later than on CPython. You can
+ easily end up in a situation where you open and close a lot of
+ (high-level) '_socketobject' or '_fileobject', but the (low-level)
+ custom objects will accumulate before their __del__ are called.
+ You quickly risk running out of file descriptors, for example.
+}}""" % (socket.__class__.__name__,), RefCountingWarning, stacklevel=3)
+ else:
+ method()
+
_socketmethods = (
'bind', 'connect', 'connect_ex', 'fileno', 'listen',
@@ -182,19 +210,7 @@
if _sock is None:
_sock = _realsocket(family, type, proto)
else:
- # PyPy note about refcounting: implemented with _reuse()/_drop()
- # on the class '_socket.socket'. Python 3 did it differently
- # with a reference counter on this class 'socket._socketobject'
- # instead, but it is a less compatible change.
-
- # Note that a few libraries (like eventlet) poke at the
- # private implementation of socket.py, passing custom
- # objects to _socketobject(). These libraries need the
- # following fix for use on PyPy: the custom objects need
- # methods _reuse() and _drop() that maintains an explicit
- # reference counter, starting at 0. When it drops back to
- # zero, close() must be called.
- _sock._reuse()
+ _do_reuse_or_drop(_sock, '_reuse')
self._sock = _sock
@@ -228,13 +244,13 @@
def close(self):
s = self._sock
self._sock = _closedsocket()
- s._drop()
+ _do_reuse_or_drop(s, '_drop')
close.__doc__ = _realsocket.close.__doc__
def accept(self):
sock, addr = self._sock.accept()
sockobj = _socketobject(_sock=sock)
- sock._drop() # already a copy in the _socketobject()
+ _do_reuse_or_drop(sock, '_drop') # already a copy in the _socketobject()
return sockobj, addr
accept.__doc__ = _realsocket.accept.__doc__
@@ -290,14 +306,7 @@
"_close"]
def __init__(self, sock, mode='rb', bufsize=-1, close=False):
- # Note that a few libraries (like eventlet) poke at the
- # private implementation of socket.py, passing custom
- # objects to _fileobject(). These libraries need the
- # following fix for use on PyPy: the custom objects need
- # methods _reuse() and _drop() that maintains an explicit
- # reference counter, starting at 0. When it drops back to
- # zero, close() must be called.
- sock._reuse()
+ _do_reuse_or_drop(sock, '_reuse')
self._sock = sock
self.mode = mode # Not actually used in this version
if bufsize < 0:
@@ -338,7 +347,7 @@
if self._close:
s.close()
else:
- s._drop()
+ _do_reuse_or_drop(s, '_drop')
def __del__(self):
try:
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -81,3 +81,11 @@
.. branch: can_cast
Implement np.can_cast, np.min_scalar_type and missing dtype comparison operations.
+
+.. branch: numpy-fixes
+Fix some error related to object dtype, non-contiguous arrays, inplement parts of
+__array_interface__, __array_priority__, __array_wrap__
+
+.. branch: cells-local-stack
+Unify the PyFrame.cells and Pyframe.locals_stack_w lists, making frame objects
+1 or 3 words smaller.
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -105,7 +105,7 @@
self)
for i in funccallunrolling:
if i < nargs:
- new_frame.locals_stack_w[i] = args_w[i]
+ new_frame.locals_cells_stack_w[i] = args_w[i]
return new_frame.run()
elif nargs >= 1 and fast_natural_arity == Code.PASSTHROUGHARGS1:
assert isinstance(code, gateway.BuiltinCodePassThroughArguments1)
@@ -171,7 +171,7 @@
self)
for i in xrange(nargs):
w_arg = frame.peekvalue(nargs-1-i)
- new_frame.locals_stack_w[i] = w_arg
+ new_frame.locals_cells_stack_w[i] = w_arg
return new_frame.run()
@@ -182,13 +182,13 @@
self)
for i in xrange(nargs):
w_arg = frame.peekvalue(nargs-1-i)
- new_frame.locals_stack_w[i] = w_arg
+ new_frame.locals_cells_stack_w[i] = w_arg
ndefs = len(self.defs_w)
start = ndefs - defs_to_load
i = nargs
for j in xrange(start, ndefs):
- new_frame.locals_stack_w[i] = self.defs_w[j]
+ new_frame.locals_cells_stack_w[i] = self.defs_w[j]
i += 1
return new_frame.run()
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -209,7 +209,7 @@
# speed hack
fresh_frame = jit.hint(frame, access_directly=True,
fresh_virtualizable=True)
- args.parse_into_scope(None, fresh_frame.locals_stack_w, func.name,
+ args.parse_into_scope(None, fresh_frame.locals_cells_stack_w, func.name,
sig, func.defs_w)
fresh_frame.init_cells()
return frame.run()
@@ -221,7 +221,7 @@
# speed hack
fresh_frame = jit.hint(frame, access_directly=True,
fresh_virtualizable=True)
- args.parse_into_scope(w_obj, fresh_frame.locals_stack_w, func.name,
+ args.parse_into_scope(w_obj, fresh_frame.locals_cells_stack_w, func.name,
sig, func.defs_w)
fresh_frame.init_cells()
return frame.run()
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -69,10 +69,9 @@
w_globals = None
pycode = None # code object executed by that frame
- locals_stack_w = None # the list of all locals and valuestack
+ locals_cells_stack_w = None # the list of all locals, cells and the valuestack
valuestackdepth = 0 # number of items on valuestack
lastblock = None
- cells = None # cells
# other fields:
@@ -93,9 +92,14 @@
self.space = space
self.w_globals = w_globals
self.pycode = code
- self.locals_stack_w = [None] * (code.co_nlocals + code.co_stacksize)
- self.valuestackdepth = code.co_nlocals
- make_sure_not_resized(self.locals_stack_w)
+ ncellvars = len(code.co_cellvars)
+ nfreevars = len(code.co_freevars)
+ size = code.co_nlocals + ncellvars + nfreevars + code.co_stacksize
+ # the layout of this list is as follows:
+ # | local vars | cells | stack |
+ self.locals_cells_stack_w = [None] * size
+ self.valuestackdepth = code.co_nlocals + ncellvars + nfreevars
+ make_sure_not_resized(self.locals_cells_stack_w)
check_nonneg(self.valuestackdepth)
#
if space.config.objspace.honor__builtins__:
@@ -136,6 +140,11 @@
self.__class__.__module__, self.__class__.__name__,
self.pycode, self.get_last_lineno())
+ def _getcell(self, varindex):
+ cell = self.locals_cells_stack_w[varindex + self.pycode.co_nlocals]
+ assert isinstance(cell, Cell)
+ return cell
+
def mark_as_escaped(self):
"""
Must be called on frames that are exposed to applevel, e.g. by
@@ -181,8 +190,6 @@
else:
return self.space.builtin
- _NO_CELLS = []
-
@jit.unroll_safe
def initialize_frame_scopes(self, outer_func, code):
# regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
@@ -201,8 +208,7 @@
nfreevars = len(code.co_freevars)
if not nfreevars:
if not ncellvars:
- self.cells = self._NO_CELLS
- return # no self.cells needed - fast path
+ return # no cells needed - fast path
elif outer_func is None:
space = self.space
raise OperationError(space.w_TypeError,
@@ -215,11 +221,13 @@
if closure_size != nfreevars:
raise ValueError("code object received a closure with "
"an unexpected number of free variables")
- self.cells = [None] * (ncellvars + nfreevars)
+ index = code.co_nlocals
for i in range(ncellvars):
- self.cells[i] = Cell()
+ self.locals_cells_stack_w[index] = Cell()
+ index += 1
for i in range(nfreevars):
- self.cells[i + ncellvars] = outer_func.closure[i]
+ self.locals_cells_stack_w[index] = outer_func.closure[i]
+ index += 1
def run(self):
"""Start this frame's execution."""
@@ -283,14 +291,24 @@
# stack manipulation helpers
def pushvalue(self, w_object):
depth = self.valuestackdepth
- self.locals_stack_w[depth] = w_object
+ self.locals_cells_stack_w[depth] = w_object
self.valuestackdepth = depth + 1
+ def _check_stack_index(self, index):
+ # will be completely removed by the optimizer if only used in an assert
+ # and if asserts are disabled
+ code = self.pycode
+ ncellvars = len(code.co_cellvars)
+ nfreevars = len(code.co_freevars)
+ stackstart = code.co_nlocals + ncellvars + nfreevars
+ return index >= stackstart
+
def popvalue(self):
depth = self.valuestackdepth - 1
- assert depth >= self.pycode.co_nlocals, "pop from empty value stack"
- w_object = self.locals_stack_w[depth]
- self.locals_stack_w[depth] = None
+ assert self._check_stack_index(depth)
+ assert depth >= 0
+ w_object = self.locals_cells_stack_w[depth]
+ self.locals_cells_stack_w[depth] = None
self.valuestackdepth = depth
return w_object
@@ -316,25 +334,26 @@
def peekvalues(self, n):
values_w = [None] * n
base = self.valuestackdepth - n
- assert base >= self.pycode.co_nlocals
+ assert self._check_stack_index(base)
+ assert base >= 0
while True:
n -= 1
if n < 0:
break
- values_w[n] = self.locals_stack_w[base+n]
+ values_w[n] = self.locals_cells_stack_w[base+n]
return values_w
@jit.unroll_safe
def dropvalues(self, n):
n = hint(n, promote=True)
finaldepth = self.valuestackdepth - n
- assert finaldepth >= self.pycode.co_nlocals, (
- "stack underflow in dropvalues()")
+ assert self._check_stack_index(finaldepth)
+ assert finaldepth >= 0
while True:
n -= 1
if n < 0:
break
- self.locals_stack_w[finaldepth+n] = None
+ self.locals_cells_stack_w[finaldepth+n] = None
self.valuestackdepth = finaldepth
@jit.unroll_safe
@@ -361,34 +380,27 @@
# Contrast this with CPython where it's PEEK(-1).
index_from_top = hint(index_from_top, promote=True)
index = self.valuestackdepth + ~index_from_top
- assert index >= self.pycode.co_nlocals, (
- "peek past the bottom of the stack")
- return self.locals_stack_w[index]
+ assert self._check_stack_index(index)
+ assert index >= 0
+ return self.locals_cells_stack_w[index]
def settopvalue(self, w_object, index_from_top=0):
index_from_top = hint(index_from_top, promote=True)
index = self.valuestackdepth + ~index_from_top
- assert index >= self.pycode.co_nlocals, (
- "settop past the bottom of the stack")
- self.locals_stack_w[index] = w_object
+ assert self._check_stack_index(index)
+ assert index >= 0
+ self.locals_cells_stack_w[index] = w_object
@jit.unroll_safe
def dropvaluesuntil(self, finaldepth):
depth = self.valuestackdepth - 1
finaldepth = hint(finaldepth, promote=True)
+ assert finaldepth >= 0
while depth >= finaldepth:
- self.locals_stack_w[depth] = None
+ self.locals_cells_stack_w[depth] = None
depth -= 1
self.valuestackdepth = finaldepth
- def save_locals_stack(self):
- return self.locals_stack_w[:self.valuestackdepth]
-
- def restore_locals_stack(self, items_w):
- self.locals_stack_w[:len(items_w)] = items_w
- self.init_cells()
- self.dropvaluesuntil(len(items_w))
-
def make_arguments(self, nargs):
return Arguments(self.space, self.peekvalues(nargs))
@@ -411,24 +423,16 @@
w = space.wrap
nt = space.newtuple
- cells = self.cells
- if cells is None:
- w_cells = space.w_None
- else:
- w_cells = space.newlist([space.wrap(cell) for cell in cells])
-
if self.get_w_f_trace() is None:
f_lineno = self.get_last_lineno()
else:
f_lineno = self.getorcreatedebug().f_lineno
nlocals = self.pycode.co_nlocals
- values_w = self.locals_stack_w[nlocals:self.valuestackdepth]
- w_valuestack = maker.slp_into_tuple_with_nulls(space, values_w)
+ values_w = self.locals_cells_stack_w
+ w_locals_cells_stack = maker.slp_into_tuple_with_nulls(space, values_w)
w_blockstack = nt([block._get_state_(space) for block in self.get_blocklist()])
- w_fastlocals = maker.slp_into_tuple_with_nulls(
- space, self.locals_stack_w[:nlocals])
if self.last_exception is None:
w_exc_value = space.w_None
w_tb = space.w_None
@@ -441,7 +445,7 @@
w(self.f_backref()),
w(self.get_builtin()),
w(self.pycode),
- w_valuestack,
+ w_locals_cells_stack,
w_blockstack,
w_exc_value, # last_exception
w_tb, #
@@ -449,7 +453,6 @@
w(self.last_instr),
w(self.frame_finished_execution),
w(f_lineno),
- w_fastlocals,
space.w_None, #XXX placeholder for f_locals
#f_restricted requires no additional data!
@@ -458,7 +461,7 @@
w(d.instr_lb),
w(d.instr_ub),
w(d.instr_prev_plus_one),
- w_cells,
+ w(self.valuestackdepth),
]
return nt(tup_state)
@@ -467,24 +470,20 @@
from pypy.module._pickle_support import maker # helper fns
from pypy.interpreter.pycode import PyCode
from pypy.interpreter.module import Module
- args_w = space.unpackiterable(w_args, 18)
- w_f_back, w_builtin, w_pycode, w_valuestack, w_blockstack, w_exc_value, w_tb,\
- w_globals, w_last_instr, w_finished, w_f_lineno, w_fastlocals, w_f_locals, \
- w_f_trace, w_instr_lb, w_instr_ub, w_instr_prev_plus_one, w_cells = args_w
+ args_w = space.unpackiterable(w_args, 17)
+ w_f_back, w_builtin, w_pycode, w_locals_cells_stack, w_blockstack, w_exc_value, w_tb,\
+ w_globals, w_last_instr, w_finished, w_f_lineno, w_f_locals, \
+ w_f_trace, w_instr_lb, w_instr_ub, w_instr_prev_plus_one, w_stackdepth = args_w
new_frame = self
pycode = space.interp_w(PyCode, w_pycode)
- if space.is_w(w_cells, space.w_None):
- closure = None
- cellvars = []
- else:
- from pypy.interpreter.nestedscope import Cell
- cells_w = space.unpackiterable(w_cells)
- cells = [space.interp_w(Cell, w_cell) for w_cell in cells_w]
- ncellvars = len(pycode.co_cellvars)
- cellvars = cells[:ncellvars]
- closure = cells[ncellvars:]
+ values_w = maker.slp_from_tuple_with_nulls(space, w_locals_cells_stack)
+ nfreevars = len(pycode.co_freevars)
+ closure = None
+ if nfreevars:
+ base = pycode.co_nlocals + len(pycode.co_cellvars)
+ closure = values_w[base: base + nfreevars]
# do not use the instance's __init__ but the base's, because we set
# everything like cells from here
@@ -502,9 +501,12 @@
assert space.interp_w(Module, w_builtin) is space.builtin
new_frame.set_blocklist([unpickle_block(space, w_blk)
for w_blk in space.unpackiterable(w_blockstack)])
- values_w = maker.slp_from_tuple_with_nulls(space, w_valuestack)
- for w_value in values_w:
- new_frame.pushvalue(w_value)
+ self.locals_cells_stack_w = values_w[:]
+ valuestackdepth = space.int_w(w_stackdepth)
+ if not self._check_stack_index(valuestackdepth):
+ raise OperationError(space.w_ValueError, space.wrap("invalid stackdepth"))
+ assert valuestackdepth >= 0
+ self.valuestackdepth = valuestackdepth
if space.is_w(w_exc_value, space.w_None):
new_frame.last_exception = None
else:
@@ -517,8 +519,6 @@
new_frame.frame_finished_execution = space.is_true(w_finished)
d = new_frame.getorcreatedebug()
d.f_lineno = space.int_w(w_f_lineno)
- fastlocals_w = maker.slp_from_tuple_with_nulls(space, w_fastlocals)
- new_frame.locals_stack_w[:len(fastlocals_w)] = fastlocals_w
if space.is_w(w_f_trace, space.w_None):
d.w_f_trace = None
@@ -529,8 +529,6 @@
d.instr_ub = space.int_w(w_instr_ub)
d.instr_prev_plus_one = space.int_w(w_instr_prev_plus_one)
- self._setcellvars(cellvars)
-
def hide(self):
return self.pycode.hidden_applevel
@@ -544,10 +542,10 @@
scope_len = len(scope_w)
if scope_len > self.pycode.co_nlocals:
raise ValueError, "new fastscope is longer than the allocated area"
- # don't assign directly to 'locals_stack_w[:scope_len]' to be
+ # don't assign directly to 'locals_cells_stack_w[:scope_len]' to be
# virtualizable-friendly
for i in range(scope_len):
- self.locals_stack_w[i] = scope_w[i]
+ self.locals_cells_stack_w[i] = scope_w[i]
self.init_cells()
def getdictscope(self):
@@ -573,7 +571,7 @@
varnames = self.getcode().getvarnames()
for i in range(min(len(varnames), self.getcode().co_nlocals)):
name = varnames[i]
- w_value = self.locals_stack_w[i]
+ w_value = self.locals_cells_stack_w[i]
if w_value is not None:
self.space.setitem_str(d.w_locals, name, w_value)
else:
@@ -592,7 +590,7 @@
freevarnames = freevarnames + self.pycode.co_freevars
for i in range(len(freevarnames)):
name = freevarnames[i]
- cell = self.cells[i]
+ cell = self._getcell(i)
try:
w_value = cell.get()
except ValueError:
@@ -631,7 +629,7 @@
# into the locals dict used by the class.
for i in range(len(freevarnames)):
name = freevarnames[i]
- cell = self.cells[i]
+ cell = self._getcell(i)
w_value = self.space.finditem_str(w_locals, name)
if w_value is not None:
cell.set(w_value)
@@ -639,24 +637,21 @@
@jit.unroll_safe
def init_cells(self):
"""
- Initialize cellvars from self.locals_stack_w.
+ Initialize cellvars from self.locals_cells_stack_w.
"""
args_to_copy = self.pycode._args_as_cellvars
+ index = self.pycode.co_nlocals
for i in range(len(args_to_copy)):
argnum = args_to_copy[i]
if argnum >= 0:
- self.cells[i].set(self.locals_stack_w[argnum])
+ cell = self.locals_cells_stack_w[index]
+ assert isinstance(cell, Cell)
+ cell.set(self.locals_cells_stack_w[argnum])
+ index += 1
def getclosure(self):
return None
- def _setcellvars(self, cellvars):
- ncellvars = len(self.pycode.co_cellvars)
- if len(cellvars) != ncellvars:
- raise OperationError(self.space.w_TypeError,
- self.space.wrap("bad cellvars"))
- self.cells[:ncellvars] = cellvars
-
def fget_code(self, space):
return space.wrap(self.getcode())
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -485,7 +485,7 @@
def LOAD_FAST(self, varindex, next_instr):
# access a local variable directly
- w_value = self.locals_stack_w[varindex]
+ w_value = self.locals_cells_stack_w[varindex]
if w_value is None:
self._load_fast_failed(varindex)
self.pushvalue(w_value)
@@ -505,7 +505,7 @@
def STORE_FAST(self, varindex, next_instr):
w_newvalue = self.popvalue()
assert w_newvalue is not None
- self.locals_stack_w[varindex] = w_newvalue
+ self.locals_cells_stack_w[varindex] = w_newvalue
def getfreevarname(self, index):
freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars
@@ -517,7 +517,7 @@
def LOAD_DEREF(self, varindex, next_instr):
# nested scopes: access a variable through its cell object
- cell = self.cells[varindex]
+ cell = self._getcell(varindex)
try:
w_value = cell.get()
except ValueError:
@@ -536,12 +536,12 @@
def STORE_DEREF(self, varindex, next_instr):
# nested scopes: access a variable through its cell object
w_newvalue = self.popvalue()
- cell = self.cells[varindex]
+ cell = self._getcell(varindex)
cell.set(w_newvalue)
def LOAD_CLOSURE(self, varindex, next_instr):
# nested scopes: access the cell object
- cell = self.cells[varindex]
+ cell = self._getcell(varindex)
w_value = self.space.wrap(cell)
self.pushvalue(w_value)
@@ -911,12 +911,12 @@
LOAD_GLOBAL._always_inline_ = True
def DELETE_FAST(self, varindex, next_instr):
- if self.locals_stack_w[varindex] is None:
+ if self.locals_cells_stack_w[varindex] is None:
varname = self.getlocalvarname(varindex)
raise oefmt(self.space.w_UnboundLocalError,
"local variable '%s' referenced before assignment",
varname)
- self.locals_stack_w[varindex] = None
+ self.locals_cells_stack_w[varindex] = None
def BUILD_TUPLE(self, itemcount, next_instr):
items = self.popvalues(itemcount)
diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py
--- a/pypy/module/_continuation/interp_continuation.py
+++ b/pypy/module/_continuation/interp_continuation.py
@@ -35,10 +35,10 @@
w_args, w_kwds = __args__.topacked()
bottomframe = space.createframe(get_entrypoint_pycode(space),
get_w_module_dict(space), None)
- bottomframe.locals_stack_w[0] = space.wrap(self)
- bottomframe.locals_stack_w[1] = w_callable
- bottomframe.locals_stack_w[2] = w_args
- bottomframe.locals_stack_w[3] = w_kwds
+ bottomframe.locals_cells_stack_w[0] = space.wrap(self)
+ bottomframe.locals_cells_stack_w[1] = w_callable
+ bottomframe.locals_cells_stack_w[2] = w_args
+ bottomframe.locals_cells_stack_w[3] = w_kwds
bottomframe.last_exception = get_cleared_operation_error(space)
self.bottomframe = bottomframe
#
diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -12,8 +12,8 @@
stop = start
start = 0
if dtype is None:
- test = _numpypy.multiarray.array([start, stop, step, 0])
- dtype = test.dtype
+ # find minimal acceptable dtype but not less than int
+ dtype = _numpypy.multiarray.result_type(start, stop, step, int)
length = math.ceil((float(stop) - start) / step)
length = int(length)
arr = _numpypy.multiarray.empty(length, dtype=dtype)
diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py
--- a/pypy/module/micronumpy/boxes.py
+++ b/pypy/module/micronumpy/boxes.py
@@ -197,6 +197,9 @@
def descr_hash(self, space):
return space.hash(self.item(space))
+ def descr___array_priority__(self, space):
+ return space.wrap(0.0)
+
def descr_index(self, space):
return space.index(self.item(space))
@@ -680,6 +683,8 @@
__hash__ = interp2app(W_GenericBox.descr_hash),
+ __array_priority__ = GetSetProperty(W_GenericBox.descr___array_priority__),
+
tolist = interp2app(W_GenericBox.item),
item = interp2app(W_GenericBox.descr_item),
transpose = interp2app(W_GenericBox.descr_transpose),
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -203,6 +203,12 @@
assert isinstance(w_obj, BoolObject)
return bool(w_obj.intval)
+ def gt(self, w_lhs, w_rhs):
+ return BoolObject(self.int_w(w_lhs) > self.int_w(w_rhs))
+
+ def lt(self, w_lhs, w_rhs):
+ return BoolObject(self.int_w(w_lhs) < self.int_w(w_rhs))
+
def is_w(self, w_obj, w_what):
return w_obj is w_what
@@ -235,8 +241,7 @@
def call_method(self, w_obj, s, *args):
# XXX even the hacks have hacks
- return None
- #return getattr(w_obj, 'descr_' + s)(self, *args)
+ return getattr(w_obj, 'descr_' + s)(self, *args)
@specialize.arg(1)
def interp_w(self, tp, what):
diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -11,7 +11,7 @@
from pypy.module.micronumpy.iterators import ArrayIter
from pypy.module.micronumpy.strides import (Chunk, Chunks, NewAxisChunk,
RecordChunk, calc_strides, calc_new_strides, shape_agreement,
- calculate_broadcast_strides, calc_backstrides)
+ calculate_broadcast_strides, calc_backstrides, calc_start)
from rpython.rlib.objectmodel import keepalive_until_here
from rpython.rtyper.annlowlevel import cast_gcref_to_instance
from pypy.interpreter.baseobjspace import W_Root
@@ -90,8 +90,9 @@
new_shape, self, orig_array)
return None
- def get_view(self, space, orig_array, dtype, new_shape):
- strides, backstrides = calc_strides(new_shape, dtype,
+ def get_view(self, space, orig_array, dtype, new_shape, strides=None, backstrides=None):
+ if not strides:
+ strides, backstrides = calc_strides(new_shape, dtype,
self.order)
return SliceArray(self.start, strides, backstrides, new_shape,
self, orig_array, dtype=dtype)
@@ -323,15 +324,27 @@
def __exit__(self, typ, value, traceback):
keepalive_until_here(self)
-
+
def get_buffer(self, space, readonly):
return ArrayBuffer(self, readonly)
def astype(self, space, dtype):
- strides, backstrides = calc_strides(self.get_shape(), dtype,
- self.order)
- impl = ConcreteArray(self.get_shape(), dtype, self.order,
- strides, backstrides)
+ # copy the general pattern of the strides
+ # but make the array storage contiguous in memory
+ shape = self.get_shape()
+ strides = self.get_strides()
+ if len(strides) > 0:
+ mins = strides[0]
+ t_elsize = dtype.elsize
+ for s in strides:
+ if s < mins:
+ mins = s
+ t_strides = [s * t_elsize / mins for s in strides]
+ backstrides = calc_backstrides(t_strides, shape)
+ else:
+ t_strides = []
+ backstrides = []
+ impl = ConcreteArray(shape, dtype, self.order, t_strides, backstrides)
loop.setslice(space, impl.get_shape(), impl, self)
return impl
@@ -426,8 +439,9 @@
gcstruct = _create_objectstore(storage, length, dtype.elsize)
else:
storage = dtype.itemtype.malloc(length * dtype.elsize, zero=zero)
+ start = calc_start(shape, strides)
ConcreteArrayNotOwning.__init__(self, shape, dtype, order, strides, backstrides,
- storage)
+ storage, start=start)
self.gcstruct = gcstruct
def __del__(self):
@@ -519,6 +533,9 @@
return self.__class__(self.start, new_strides, new_backstrides, new_shape,
self, orig_array)
+ def sort(self, space, w_axis, w_order):
+ from .selection import sort_array
+ return sort_array(self, space, w_axis, w_order)
class NonWritableSliceArray(SliceArray):
def descr_setitem(self, space, orig_array, w_index, w_value):
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
@@ -124,19 +124,21 @@
copy = True
if copy:
shape = w_object.get_shape()
- elems_w = [None] * w_object.get_size()
- 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)
+ w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order)
+ if support.product(shape) == 1:
+ w_arr.set_scalar_value(dtype.coerce(space,
+ w_object.implementation.getitem(0)))
+ else:
+ loop.setslice(space, shape, w_arr.implementation, w_object.implementation)
+ return w_arr
else:
imp = w_object.implementation
+ w_base = imp.base() or w_object
with imp as storage:
sz = support.product(w_object.get_shape()) * dtype.elsize
return W_NDimArray.from_shape_and_storage(space,
w_object.get_shape(), storage, dtype, storage_bytes=sz,
- w_base=w_object, start=imp.start)
+ w_base=w_base, start=imp.start)
else:
# not an array
shape, elems_w = strides.find_shape_and_elems(space, w_object, dtype)
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
@@ -97,6 +97,8 @@
finally:
self.iter.reset(self.state, mutate=True)
+ def descr___array_wrap__(self, space, obj):
+ return obj
W_FlatIterator.typedef = TypeDef("numpy.flatiter",
base = GetSetProperty(W_FlatIterator.descr_base),
@@ -116,4 +118,5 @@
__le__ = interp2app(W_FlatIterator.descr_le),
__gt__ = interp2app(W_FlatIterator.descr_gt),
__ge__ = interp2app(W_FlatIterator.descr_ge),
+ __array_wrap__ = interp2app(W_NDimArray.descr___array_wrap__),
)
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -22,9 +22,8 @@
# handle array_priority
# w_lhs and w_rhs could be of different ndarray subtypes. Numpy does:
# 1. if __array_priorities__ are equal and one is an ndarray and the
- # other is a subtype, flip the order
- # 2. elif rhs.__array_priority__ is higher, flip the order
- # Now return the subtype of the first one
+ # other is a subtype, return a subtype
+ # 2. elif rhs.__array_priority__ is higher, return the type of rhs
w_ndarray = space.gettypefor(W_NDimArray)
lhs_type = space.type(w_lhs)
@@ -38,10 +37,15 @@
if not space.is_true(space.issubtype(rhs_type, w_ndarray)):
rhs_type = space.type(w_rhs.base)
rhs_for_subtype = w_rhs.base
+
+ w_highpriority = w_lhs
+ highpriority_subtype = lhs_for_subtype
if space.is_w(lhs_type, w_ndarray) and not space.is_w(rhs_type, w_ndarray):
- lhs_for_subtype = rhs_for_subtype
-
- # TODO handle __array_priorities__ and maybe flip the order
+ highpriority_subtype = rhs_for_subtype
+ w_highpriority = w_rhs
+ if support.is_rhs_priority_higher(space, w_lhs, w_rhs):
+ highpriority_subtype = rhs_for_subtype
+ w_highpriority = w_rhs
if w_lhs.get_size() == 1:
w_left = w_lhs.get_scalar_value().convert_to(space, calc_dtype)
@@ -60,9 +64,11 @@
right_iter.track_index = False
if out is None:
- out = W_NDimArray.from_shape(space, shape, res_dtype,
- w_instance=lhs_for_subtype)
- out_iter, out_state = out.create_iter(shape)
+ w_ret = W_NDimArray.from_shape(space, shape, res_dtype,
+ w_instance=highpriority_subtype)
+ else:
+ w_ret = out
+ out_iter, out_state = w_ret.create_iter(shape)
shapelen = len(shape)
while not out_iter.done(out_state):
call2_driver.jit_merge_point(shapelen=shapelen, func=func,
@@ -76,7 +82,9 @@
out_iter.setitem(out_state, func(calc_dtype, w_left, w_right).convert_to(
space, res_dtype))
out_state = out_iter.next(out_state)
- return out
+ if out is None:
+ w_ret = space.call_method(w_highpriority, '__array_wrap__', w_ret)
+ return w_ret
call1_driver = jit.JitDriver(
name='numpy_call1',
@@ -88,8 +96,10 @@
obj_iter.track_index = False
if out is None:
- out = W_NDimArray.from_shape(space, shape, res_dtype, w_instance=w_obj)
- out_iter, out_state = out.create_iter(shape)
+ w_ret = W_NDimArray.from_shape(space, shape, res_dtype, w_instance=w_obj)
+ else:
+ w_ret = out
+ out_iter, out_state = w_ret.create_iter(shape)
shapelen = len(shape)
while not out_iter.done(out_state):
call1_driver.jit_merge_point(shapelen=shapelen, func=func,
@@ -98,7 +108,9 @@
out_iter.setitem(out_state, func(calc_dtype, elem).convert_to(space, res_dtype))
out_state = out_iter.next(out_state)
obj_state = obj_iter.next(obj_state)
- return out
+ if out is None:
+ w_ret = space.call_method(w_obj, '__array_wrap__', w_ret)
+ return w_ret
call_many_to_one_driver = jit.JitDriver(
name='numpy_call_many_to_one',
@@ -209,7 +221,7 @@
while not target_iter.done(target_state):
setslice_driver.jit_merge_point(shapelen=shapelen, dtype=dtype)
val = source_iter.getitem(source_state)
- if dtype.is_str_or_unicode():
+ if dtype.is_str_or_unicode() or dtype.is_record():
val = dtype.coerce(space, val)
else:
val = val.convert_to(space, dtype)
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -569,6 +569,11 @@
def fdel___pypy_data__(self, space):
self.w_pypy_data = None
+ __array_priority__ = 0.0
+
+ def descr___array_priority__(self, space):
+ return space.wrap(self.__array_priority__)
+
def descr_argsort(self, space, w_axis=None, w_kind=None, w_order=None):
# happily ignore the kind
# create a contiguous copy of the array
@@ -797,6 +802,7 @@
new_shape = [s for s in cur_shape if s != 1]
if len(cur_shape) == len(new_shape):
return self
+ # XXX need to call __array_wrap__
return wrap_impl(space, space.type(self), self,
self.implementation.get_view(
space, self, self.get_dtype(), new_shape))
@@ -844,28 +850,40 @@
if old_itemsize != new_itemsize:
raise OperationError(space.w_ValueError, space.wrap(
"new type not compatible with array."))
+ strides = None
+ backstrides = None
+ base = self
else:
- if not is_c_contiguous(impl) and not is_f_contiguous(impl):
- if old_itemsize != new_itemsize:
+ base = impl.base()
+ if base is None:
+ base = self
+ strides = impl.get_strides()[:]
+ backstrides = impl.get_backstrides()[:]
+ if old_itemsize != new_itemsize:
+ if not is_c_contiguous(impl) and not is_f_contiguous(impl):
raise OperationError(space.w_ValueError, space.wrap(
"new type not compatible with array."))
- # Strides, shape does not change
- v = impl.astype(space, dtype)
- return wrap_impl(space, w_type, self, v)
- strides = impl.get_strides()
- if dims == 1 or strides[0] <strides[-1]:
- # Column-major, resize first dimension
- if new_shape[0] * old_itemsize % new_itemsize != 0:
+ # Adapt the smallest dim to the new itemsize
+ if self.get_order() == 'F':
+ minstride = strides[0]
+ mini = 0
+ else:
+ minstride = strides[-1]
+ mini = len(strides) - 1
+ for i in range(len(strides)):
+ if strides[i] < minstride:
+ minstride = strides[i]
+ mini = i
+ if new_shape[mini] * old_itemsize % new_itemsize != 0:
raise OperationError(space.w_ValueError, space.wrap(
"new type not compatible with array."))
- new_shape[0] = new_shape[0] * old_itemsize / new_itemsize
- else:
- # Row-major, resize last dimension
- if new_shape[-1] * old_itemsize % new_itemsize != 0:
- raise OperationError(space.w_ValueError, space.wrap(
- "new type not compatible with array."))
- new_shape[-1] = new_shape[-1] * old_itemsize / new_itemsize
- v = impl.get_view(space, self, dtype, new_shape)
+ new_shape[mini] = new_shape[mini] * old_itemsize / new_itemsize
+ strides[mini] = strides[mini] * new_itemsize / old_itemsize
+ backstrides[mini] = strides[mini] * new_shape[mini]
+ if dtype.is_object() != impl.dtype.is_object():
+ raise oefmt(space.w_ValueError, 'expect trouble in ndarray.view,'
+ ' one of target dtype or dtype is object dtype')
+ v = impl.get_view(space, base, dtype, new_shape, strides, backstrides)
w_ret = wrap_impl(space, w_type, self, v)
return w_ret
@@ -928,6 +946,7 @@
return ufunc(self, space, w_other, w_out)
except OperationError, e:
if e.match(space, space.w_ValueError):
+ # and 'operands could not be broadcast together' in str(e.get_w_value(space)):
return space.w_False
raise e
@@ -1048,7 +1067,7 @@
# ----------------------- reduce -------------------------------
- def _reduce_ufunc_impl(ufunc_name, cumulative=False):
+ def _reduce_ufunc_impl(ufunc_name, cumulative=False, bool_result=False):
@unwrap_spec(keepdims=bool)
def impl(self, space, w_axis=None, w_dtype=None, w_out=None, keepdims=False):
if space.is_none(w_out):
@@ -1057,6 +1076,8 @@
raise oefmt(space.w_TypeError, 'output must be an array')
else:
out = w_out
+ if bool_result:
+ w_dtype = descriptor.get_dtype_cache(space).w_booldtype
return getattr(ufuncs.get(space), ufunc_name).reduce(
space, self, w_axis, keepdims, out, w_dtype, cumulative=cumulative)
return func_with_new_name(impl, "reduce_%s_impl_%d" % (ufunc_name, cumulative))
@@ -1065,8 +1086,8 @@
descr_prod = _reduce_ufunc_impl("multiply")
descr_max = _reduce_ufunc_impl("maximum")
descr_min = _reduce_ufunc_impl("minimum")
- descr_all = _reduce_ufunc_impl('logical_and')
- descr_any = _reduce_ufunc_impl('logical_or')
+ descr_all = _reduce_ufunc_impl('logical_and', bool_result=True)
+ descr_any = _reduce_ufunc_impl('logical_or', bool_result=True)
descr_cumsum = _reduce_ufunc_impl('add', cumulative=True)
descr_cumprod = _reduce_ufunc_impl('multiply', cumulative=True)
@@ -1497,6 +1518,7 @@
__array_finalize__ = interp2app(W_NDimArray.descr___array_finalize__),
__array_prepare__ = interp2app(W_NDimArray.descr___array_prepare__),
__array_wrap__ = interp2app(W_NDimArray.descr___array_wrap__),
+ __array_priority__ = GetSetProperty(W_NDimArray.descr___array_priority__),
__array__ = interp2app(W_NDimArray.descr___array__),
)
diff --git a/pypy/module/micronumpy/selection.py b/pypy/module/micronumpy/selection.py
--- a/pypy/module/micronumpy/selection.py
+++ b/pypy/module/micronumpy/selection.py
@@ -120,7 +120,7 @@
ArgSort = make_timsort_class(arg_getitem, arg_setitem, arg_length,
arg_getitem_slice, arg_lt)
- def argsort(arr, space, w_axis, itemsize):
+ def argsort(arr, space, w_axis):
if w_axis is space.w_None:
# note that it's fine ot pass None here as we're not going
# to pass the result around (None is the link to base in slices)
@@ -138,7 +138,7 @@
if len(arr.get_shape()) == 1:
for i in range(arr.get_size()):
raw_storage_setitem(storage, i * INT_SIZE, i)
- r = Repr(INT_SIZE, itemsize, arr.get_size(), arr_storage,
+ r = Repr(INT_SIZE, arr.strides[0], arr.get_size(), arr_storage,
storage, 0, arr.start)
ArgSort(r).sort()
else:
@@ -174,8 +174,7 @@
itemtype = arr.dtype.itemtype
for tp in all_types:
if isinstance(itemtype, tp[0]):
- return cache._lookup(tp)(arr, space, w_axis,
- itemtype.get_element_size())
+ return cache._lookup(tp)(arr, space, w_axis)
# XXX this should probably be changed
raise oefmt(space.w_NotImplementedError,
"sorting of non-numeric types '%s' is not implemented",
@@ -272,7 +271,7 @@
ArgSort = make_timsort_class(arg_getitem, arg_setitem, arg_length,
arg_getitem_slice, arg_lt)
- def sort(arr, space, w_axis, itemsize):
+ def sort(arr, space, w_axis):
if w_axis is space.w_None:
# note that it's fine to pass None here as we're not going
# to pass the result around (None is the link to base in slices)
@@ -284,7 +283,7 @@
axis = space.int_w(w_axis)
with arr as storage:
if len(arr.get_shape()) == 1:
- r = Repr(itemsize, arr.get_size(), storage,
+ r = Repr(arr.strides[0], arr.get_size(), storage,
arr.start)
ArgSort(r).sort()
else:
@@ -313,8 +312,7 @@
"sorting of non-native byteorder not supported yet")
for tp in all_types:
if isinstance(itemtype, tp[0]):
- return cache._lookup(tp)(arr, space, w_axis,
- itemtype.get_element_size())
+ return cache._lookup(tp)(arr, space, w_axis)
# XXX this should probably be changed
raise oefmt(space.w_NotImplementedError,
"sorting of non-numeric types '%s' is not implemented",
diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -429,6 +429,17 @@
n_old_elems_to_use *= old_shape[oldI]
return new_strides[:]
+def calc_start(shape, strides):
+ ''' Strides can be negative for non-contiguous data.
+ Calculate the appropriate positive starting position so
+ the indexing still works properly
+ '''
+ start = 0
+ for i in range(len(shape)):
+ if strides[i] < 0:
+ start -= strides[i] * (shape[i] - 1)
+ return start
+
@jit.unroll_safe
def is_c_contiguous(arr):
shape = arr.get_shape()
diff --git a/pypy/module/micronumpy/support.py b/pypy/module/micronumpy/support.py
--- a/pypy/module/micronumpy/support.py
+++ b/pypy/module/micronumpy/support.py
@@ -152,3 +152,9 @@
def get_storage_as_int(storage, start=0):
return rffi.cast(lltype.Signed, storage) + start
+def is_rhs_priority_higher(space, w_lhs, w_rhs):
+ w_zero = space.wrap(0.0)
+ w_priority_l = space.findattr(w_lhs, space.wrap('__array_priority__')) or w_zero
+ w_priority_r = space.findattr(w_rhs, space.wrap('__array_priority__')) or w_zero
+ # XXX what is better, unwrapping values or space.gt?
+ return space.is_true(space.gt(w_priority_r, w_priority_l))
diff --git a/pypy/module/micronumpy/test/test_complex.py b/pypy/module/micronumpy/test/test_complex.py
--- a/pypy/module/micronumpy/test/test_complex.py
+++ b/pypy/module/micronumpy/test/test_complex.py
@@ -331,6 +331,12 @@
complex(float('nan'), 0)], dtype=complex)) == \
[False, True, True, False, False]).all()
+ def test_sign_for_complex_nan(self):
+ from numpy import array, nan, sign, isnan
+ C = array([nan], dtype=complex)
+ res = sign(C)
+ assert isnan(res.real)
+ assert res.imag == 0+0j
def test_square(self):
from numpy import square
@@ -480,12 +486,16 @@
assert c[i] == max(a[i], b[i])
- def test_abs_overflow(self):
- from numpy import array, absolute, isinf
+ def test_complex_overflow(self):
+ from numpy import array, absolute, isinf, complex128, floor_divide
a = array(complex(1.5e308,1.5e308))
# Prints a RuntimeWarning, but does not raise
b = absolute(a)
assert isinf(b)
+ c = array([1.e+110, 1.e-110], dtype=complex128)
+ d = floor_divide(c**2, c)
+ assert (d == [1.e+110, 0]).all()
+
def test_basic(self):
@@ -592,7 +602,7 @@
# but numpy.raises a TypeError
if '__pypy__' in sys.builtin_module_names:
exct, excm = TypeError, 'readonly attribute'
- else:
+ else :
exct, excm = AttributeError, 'is not writable'
exc = raises(exct, 'c2.real = 10.')
assert excm in exc.value[0]
diff --git a/pypy/module/micronumpy/test/test_iterators.py b/pypy/module/micronumpy/test/test_iterators.py
--- a/pypy/module/micronumpy/test/test_iterators.py
+++ b/pypy/module/micronumpy/test/test_iterators.py
@@ -66,6 +66,29 @@
assert s.offset == 1
assert s._indices == [1,0]
+ def test_one_in_shape(self):
+ strides = [16, 4, 8]
+ shape = [3, 4, 1]
+ backstrides = [x * (y - 1) for x,y in zip(strides, shape)]
+ assert backstrides == [32, 12, 0]
+ i = ArrayIter(MockArray(shape, strides), support.product(shape), shape,
+ strides, backstrides)
+ assert not i.contiguous
+ s = i.reset()
+ for j in range(3):
+ s = i.next(s)
+ assert s.offset == 12
+ assert not i.done(s)
+ assert s._indices == [0, 3, 0]
+ while not i.done(s):
+ old_indices = s._indices[:]
+ old_offset = s.offset
+ s = i.next(s)
+ assert s.offset == 0
+ assert s._indices == [0, 0, 0]
+ assert old_indices == [2, 3, 0]
+ assert old_offset == 44
+
def test_iterator_goto(self):
shape = [3, 5]
strides = [1, 3]
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
@@ -237,7 +237,7 @@
assert np.WRAP is 1
assert np.RAISE is 2
- def test_ndarray(self):
+ def test_creation(self):
from numpy import ndarray, array, dtype, flatiter
assert type(ndarray) is type
@@ -269,6 +269,12 @@
assert a.flags['C']
assert not a.flags['F']
+ x = array([[0, 2], [1, 1], [2, 0]])
+ y = array(x.T, dtype=float)
+ assert (y == x.T).all()
+ y = array(x.T, copy=False)
+ assert (y == x.T).all()
+
def test_ndmin(self):
from numpy import array
@@ -459,7 +465,7 @@
assert b.dtype is dtype(complex)
def test_arange(self):
- from numpy import arange, dtype
+ from numpy import arange, dtype, array
a = arange(3)
assert (a == [0, 1, 2]).all()
assert a.dtype is dtype(int)
@@ -480,6 +486,9 @@
assert len(a) == 8
assert arange(False, True, True).dtype is dtype(int)
+ a = arange(array([10]))
+ assert a.shape == (10,)
+
def test_copy(self):
from numpy import arange, array
a = arange(5)
@@ -1809,7 +1818,7 @@
y = x.view(dtype='int16')
def test_view_of_slice(self):
- from numpy import empty
+ from numpy import empty, dtype
x = empty([6], 'uint32')
x.fill(0xdeadbeef)
s = x[::3]
@@ -1817,7 +1826,19 @@
assert exc.value[0] == 'new type not compatible with array.'
s[...] = 2
v = s.view(x.__class__)
+ assert v.strides == s.strides
+ assert v.base is s.base
assert (v == 2).all()
+ y = empty([6,6], 'uint32')
+ s = y.swapaxes(0, 1)
+ v = s.view(y.__class__)
+ assert v.strides == (4, 24)
+
+ a = empty([3, 2, 1], dtype='float64')
+ b = a.view(dtype('uint32'))
+ assert b.strides == (16, 8, 4)
+ assert b.shape == (3, 2, 2)
+ b.fill(0xdeadbeef)
def test_tolist_scalar(self):
from numpy import dtype
@@ -2182,8 +2203,13 @@
assert (b == [False, True, True]).all()
assert b.dtype == 'bool'
+ a = arange(11)[::-1]
+ b = a.astype('int32')
+ assert (b == a).all()
+
a = arange(6, dtype='f4').reshape(2,3)
- b = a.astype('i4')
+ b = a.T.astype('i4')
+ assert (a.T.strides == b.strides)
a = array('x').astype('S3').dtype
assert a.itemsize == 3
@@ -2203,6 +2229,12 @@
exc = raises(ValueError, a.astype, 'i8')
assert exc.value.message.startswith('invalid literal for int()')
+ a = arange(5, dtype=complex)
+ b = a.real
+ c = b.astype("int64")
+ assert c.shape == b.shape
+ assert c.strides == (8,)
+
def test_base(self):
from numpy import array
assert array(1).base is None
@@ -3821,6 +3853,14 @@
([4, 5, 6], [5.5, 6.5, 7.5, 8.5, 9.5])], dtype=d)
assert len(list(a[0])) == 2
+
+ mdtype = dtype([('a', bool), ('b', bool), ('c', bool)])
+ a = array([0, 0, 0, 1, 1])
+ # this creates a value of (x, x, x) in b for each x in a
+ b = array(a, dtype=mdtype)
+ assert b.shape == a.shape
+ c = array([(x, x, x) for x in [0, 0, 0, 1, 1]], dtype=mdtype)
+ assert (b == c).all()
def test_3d_record(self):
from numpy import dtype, array
diff --git a/pypy/module/micronumpy/test/test_object_arrays.py b/pypy/module/micronumpy/test/test_object_arrays.py
--- a/pypy/module/micronumpy/test/test_object_arrays.py
+++ b/pypy/module/micronumpy/test/test_object_arrays.py
@@ -52,8 +52,6 @@
import numpy as np
import sys
- if '__pypy__' in sys.builtin_module_names:
- skip('need to refactor use of raw_xxx_op in types to make this work')
a = np.array(["foo"], dtype=object)
b = np.array([1], dtype=object)
d = np.array([complex(1, 10)], dtype=object)
@@ -166,4 +164,3 @@
a = np.array([(1, 'object')], dt)
# Wrong way - should complain about writing buffer to object dtype
raises(ValueError, np.array, [1, 'object'], dt)
-
diff --git a/pypy/module/micronumpy/test/test_selection.py b/pypy/module/micronumpy/test/test_selection.py
--- a/pypy/module/micronumpy/test/test_selection.py
+++ b/pypy/module/micronumpy/test/test_selection.py
@@ -82,6 +82,13 @@
#assert (a == b).all(), \
# 'a,orig,dtype %r,%r,%r' % (a,c,dtype)
+ def test_sort_noncontiguous(self):
+ from numpy import array
+ x = array([[2, 10], [1, 11]])
+ assert (x[:, 0].argsort() == [1, 0]).all()
+ x[:, 0].sort()
+ assert (x == [[1, 10], [2, 11]]).all()
+
# tests from numpy/tests/test_multiarray.py
def test_sort_corner_cases(self):
# test ordering for floats and complex containing nans. It is only
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
@@ -80,19 +80,46 @@
a = array(range(5))
b = matrix(a)
assert isinstance(b, matrix)
+ assert b.__array_priority__ == 0.0
assert (b == a).all()
a = array(5)[()]
for s in [matrix, ndarray]:
b = a.view(s)
assert b == a
assert type(b) is type(a)
+ a = matrix(array(range(5)))
+ for s in [matrix, ndarray]:
+ b = ndarray.view(a, s)
+ assert (b == a).all()
+ assert type(b) is s
def test_subtype_like_matrix(self):
import numpy as np
arr = np.array([1,2,3])
ret = np.ndarray.__new__(np.ndarray, arr.shape, arr.dtype, buffer=arr)
+ assert ret.__array_priority__ == 0.0
assert (arr == ret).all()
+
+ def test_priority(self):
+ from numpy import ndarray, arange, add
+ class DoReflected(object):
+ __array_priority__ = 10
+ def __radd__(self, other):
+ return 42
+ class A(object):
+ def __add__(self, other):
+ return NotImplemented
+
+
+ a = arange(10)
+ b = DoReflected()
+ c = A()
+ assert c + b == 42
+ assert a.__add__(b) is NotImplemented # not an exception
+ assert b.__radd__(a) == 42
+ assert a + b == 42
+
def test_finalize(self):
#taken from http://docs.scipy.org/doc/numpy/user/basics.subclassing.html#simple-example-adding-an-extra-attribute-to-ndarray
import numpy as np
@@ -276,7 +303,11 @@
def test_array_of_subtype(self):
import numpy as N
- # numpy's matrix class caused an infinite loop
+ # this part of numpy's matrix class causes an infinite loop
+ # on cpython
+ import sys
+ if '__pypy__' not in sys.builtin_module_names:
+ skip('does not pass on cpython')
class matrix(N.ndarray):
def __new__(subtype, data, dtype=None, copy=True):
print('matrix __new__')
@@ -326,7 +357,7 @@
return ret
def __array_finalize__(self, obj):
- print('matrix __array_finalize__')
+ print('matrix __array_finalize__',obj)
self._getitem = False
if (isinstance(obj, matrix) and obj._getitem): return
ndim = self.ndim
@@ -349,7 +380,7 @@
return
def __getitem__(self, index):
- print('matrix __getitem__')
+ print('matrix __getitem__',index)
self._getitem = True
try:
@@ -400,7 +431,7 @@
def test_setstate_no_version(self):
# Some subclasses of ndarray, like MaskedArray, do not use
- # version in __setstare__
+ # version in __setstate__
from numpy import ndarray, array
from pickle import loads, dumps
import sys, new
@@ -593,3 +624,51 @@
a = asarray(fp[5:6][:,4])
assert (a == vals).all()
+ def test__array_wrap__(self):
+ ''' Straight from the documentation of __array_wrap__
+ '''
+ import numpy as np
+
+ class MySubClass(np.ndarray):
+ output = ''
+
+ def __new__(cls, input_array, info=None):
+ obj = np.array(input_array).view(cls)
+ obj.info = info
+ return obj
+
+ def __array_finalize__(self, obj):
+ self.output += 'In __array_finalize__:'
+ self.output += ' self is %s' % repr(self)
+ self.output += ' obj is %s\n' % repr(obj)
+ print self.output
+ if obj is None: return
+ self.info = getattr(obj, 'info', None)
+
+ def __array_wrap__(self, out_arr, context=None):
+ self.output += 'In __array_wrap__:'
+ self.output += ' self is %s' % repr(self)
+ self.output += ' arr is %r\n' % (out_arr,)
+ # then just call the parent
+ ret = np.ndarray.__array_wrap__(self, out_arr, context)
+ print 'wrap',self.output
+ return ret
+
+ obj = MySubClass(np.arange(5), info='spam')
+ assert obj.output.startswith('In __array_finalize')
+ obj.output = ''
+ print 'np.arange(5) + 1'
+ arr2 = np.arange(5) + 1
+ assert len(obj.output) < 1
+ print 'np.add(arr2, obj)'
+ ret = np.add(arr2, obj)
+ assert obj.output.startswith('In __array_wrap')
+ assert 'finalize' not in obj.output
+ assert ret.info == 'spam'
+ print 'np.negative(obj)'
+ ret = np.negative(obj)
+ assert ret.info == 'spam'
+ print 'obj.sum()'
+ ret = obj.sum()
+ print type(ret)
+ assert ret.info == 'spam'
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
@@ -30,7 +30,26 @@
log2e = 1. / log2
log10 = math.log(10)
-
+'''
+if not we_are_translated():
+ _raw_storage_setitem_unaligned = raw_storage_setitem_unaligned
+ _raw_storage_getitem_unaligned = raw_storage_getitem_unaligned
+ def raw_storage_setitem_unaligned(storage, offset, value):
+ assert offset >=0
+ try:
+ assert offset < storage._obj.getlength()
+ except AttributeError:
+ pass
+ return _raw_storage_setitem_unaligned(storage, offset, value)
+
+ def raw_storage_getitem_unaligned(T, storage, offset):
+ assert offset >=0
+ try:
+ assert offset < storage._obj.getlength()
+ except AttributeError:
+ pass
+ return _raw_storage_getitem_unaligned(T, storage, offset)
+'''
def simple_unary_op(func):
specialize.argtype(1)(func)
@functools.wraps(func)
@@ -291,11 +310,15 @@
@raw_binary_op
def logical_and(self, v1, v2):
- return bool(v1) and bool(v2)
+ if bool(v1) and bool(v2):
+ return Bool._True
+ return Bool._False
@raw_binary_op
def logical_or(self, v1, v2):
- return bool(v1) or bool(v2)
+ if bool(v1) or bool(v2):
+ return Bool._True
+ return Bool._False
@raw_unary_op
def logical_not(self, v):
@@ -757,6 +780,8 @@
def sign(self, v):
if v == 0.0:
return 0.0
+ if rfloat.isnan(v):
+ return rfloat.NAN
return rfloat.copysign(1.0, v)
@raw_unary_op
@@ -1324,11 +1349,15 @@
@raw_binary_op
def logical_and(self, v1, v2):
- return self._cbool(v1) and self._cbool(v2)
+ if self._cbool(v1) and self._cbool(v2):
+ return Bool._True
+ return Bool._False
@raw_binary_op
def logical_or(self, v1, v2):
- return self._cbool(v1) or self._cbool(v2)
+ if self._cbool(v1) or self._cbool(v2):
+ return Bool._True
+ return Bool._False
@raw_unary_op
def logical_not(self, v):
@@ -1352,12 +1381,30 @@
@complex_binary_op
def floordiv(self, v1, v2):
- try:
- ab = v1[0]*v2[0] + v1[1]*v2[1]
- bb = v2[0]*v2[0] + v2[1]*v2[1]
- return math.floor(ab/bb), 0.
- except ZeroDivisionError:
- return rfloat.NAN, 0.
+ (r1, i1), (r2, i2) = v1, v2
+ if r2 < 0:
+ abs_r2 = -r2
+ else:
+ abs_r2 = r2
+ if i2 < 0:
+ abs_i2 = -i2
+ else:
+ abs_i2 = i2
+ if abs_r2 >= abs_i2:
+ if abs_r2 == 0.0:
+ return rfloat.NAN, 0.
+ else:
+ ratio = i2 / r2
+ denom = r2 + i2 * ratio
+ rr = (r1 + i1 * ratio) / denom
+ elif rfloat.isnan(r2):
+ rr = rfloat.NAN
+ else:
+ ratio = r2 / i2
+ denom = r2 * ratio + i2
+ assert i2 != 0.0
+ rr = (r1 * ratio + i1) / denom
+ return math.floor(rr), 0.
#complex mod does not exist in numpy
#@simple_binary_op
@@ -1394,15 +1441,17 @@
sign of complex number could be either the point closest to the unit circle
or {-1,0,1}, for compatability with numpy we choose the latter
'''
+ if rfloat.isnan(v[0]) or rfloat.isnan(v[1]):
+ return rfloat.NAN, 0
if v[0] == 0.0:
if v[1] == 0:
- return 0,0
+ return 0, 0
if v[1] > 0:
- return 1,0
- return -1,0
+ return 1, 0
+ return -1, 0
if v[0] > 0:
- return 1,0
- return -1,0
+ return 1, 0
+ return -1, 0
def fmax(self, v1, v2):
if self.ge(v1, v2) or self.isnan(v2):
@@ -1856,14 +1905,14 @@
@raw_binary_op
def logical_and(self, v1, v2):
if self._obool(v1):
- return self.space.bool_w(v2)
- return self.space.bool_w(v1)
+ return self.box(v2)
+ return self.box(v1)
@raw_binary_op
def logical_or(self, v1, v2):
if self._obool(v1):
- return self.space.bool_w(v1)
- return self.space.bool_w(v2)
+ return self.box(v1)
+ return self.box(v2)
@raw_unary_op
def logical_not(self, v):
@@ -2110,11 +2159,15 @@
@str_binary_op
def logical_and(self, v1, v2):
- return bool(v1) and bool(v2)
+ if bool(v1) and bool(v2):
+ return Bool._True
+ return Bool._False
@str_binary_op
def logical_or(self, v1, v2):
- return bool(v1) or bool(v2)
+ if bool(v1) or bool(v2):
+ return Bool._True
+ return Bool._False
@str_unary_op
def logical_not(self, v):
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -17,7 +17,8 @@
from pypy.module.micronumpy.ctors import numpify
from pypy.module.micronumpy.nditer import W_NDIter, coalesce_iter
from pypy.module.micronumpy.strides import shape_agreement
-from pypy.module.micronumpy.support import _parse_signature, product, get_storage_as_int
+from pypy.module.micronumpy.support import (_parse_signature, product,
+ get_storage_as_int, is_rhs_priority_higher)
from .casting import (
find_unaryop_result_dtype, find_binop_result_dtype, can_cast_type)
@@ -29,6 +30,21 @@
return not dtype.itemtype.bool(val)
+def _find_array_wrap(*args, **kwds):
+ '''determine an appropriate __array_wrap__ function to call for the outputs.
+ If an output argument is provided, then it is wrapped
+ with its own __array_wrap__ not with the one determined by
+ the input arguments.
+
+ if the provided output argument is already an array,
+ the wrapping function is None (which means no wrapping will
+ be done --- not even PyArray_Return).
+
+ A NULL is placed in output_wrap for outputs that
+ should just have PyArray_Return called.
+ '''
+ raise NotImplementedError()
+
class W_Ufunc(W_Root):
_immutable_fields_ = [
"name", "promote_to_largest", "promote_to_float", "promote_bools", "nin",
@@ -201,7 +217,7 @@
axis += shapelen
assert axis >= 0
dtype = decode_w_dtype(space, dtype)
- if self.comparison_func:
+ if self.bool_result:
dtype = get_dtype_cache(space).w_booldtype
elif dtype is None:
dtype = find_unaryop_result_dtype(
@@ -217,6 +233,7 @@
raise oefmt(space.w_ValueError,
"zero-size array to reduction operation %s "
"which has no identity", self.name)
+ call__array_wrap__ = True
if shapelen > 1 and axis < shapelen:
temp = None
if cumulative:
@@ -249,6 +266,7 @@
",".join([str(x) for x in shape]),
",".join([str(x) for x in out.get_shape()]),
)
+ call__array_wrap__ = False
dtype = out.get_dtype()
else:
out = W_NDimArray.from_shape(space, shape, dtype,
@@ -257,11 +275,15 @@
if self.identity is not None:
out.fill(space, self.identity.convert_to(space, dtype))
return out
- return loop.do_axis_reduce(space, shape, self.func, obj, dtype,
+ loop.do_axis_reduce(space, shape, self.func, obj, dtype,
axis, out, self.identity, cumulative,
temp)
+ if call__array_wrap__:
+ out = space.call_method(obj, '__array_wrap__', out)
+ return out
if cumulative:
if out:
+ call__array_wrap__ = False
if out.get_shape() != [obj.get_size()]:
raise OperationError(space.w_ValueError, space.wrap(
"out of incompatible size"))
@@ -270,8 +292,11 @@
w_instance=obj)
loop.compute_reduce_cumulative(space, obj, out, dtype, self.func,
self.identity)
+ if call__array_wrap__:
+ out = space.call_method(obj, '__array_wrap__', out)
return out
if out:
+ call__array_wrap__ = False
if out.ndims() > 0:
raise oefmt(space.w_ValueError,
"output parameter for reduction operation %s has "
@@ -284,10 +309,16 @@
return out
if keepdims:
shape = [1] * len(obj_shape)
- out = W_NDimArray.from_shape(space, [1] * len(obj_shape), dtype,
- w_instance=obj)
+ out = W_NDimArray.from_shape(space, shape, dtype, w_instance=obj)
out.implementation.setitem(0, res)
- return out
+ res = out
+ elif not space.is_w(space.type(w_obj), space.gettypefor(W_NDimArray)):
+ # subtypes return a ndarray subtype, not a scalar
+ out = W_NDimArray.from_shape(space, [1], dtype, w_instance=obj)
+ out.implementation.setitem(0, res)
+ res = out
+ if call__array_wrap__:
+ res = space.call_method(obj, '__array_wrap__', res)
return res
def descr_outer(self, space, __args__):
@@ -314,6 +345,32 @@
extobj_w = space.newlist([space.wrap(8192), space.wrap(0), space.w_None])
return extobj_w
+def _has_reflected_op(space, w_obj, op):
+ refops ={ 'add': 'radd',
+ 'subtract': 'rsub',
+ 'multiply': 'rmul',
+ 'divide': 'rdiv',
+ 'true_divide': 'rtruediv',
+ 'floor_divide': 'rfloordiv',
+ 'remainder': 'rmod',
+ 'power': 'rpow',
+ 'left_shift': 'rlshift',
+ 'right_shift': 'rrshift',
+ 'bitwise_and': 'rand',
+ 'bitwise_xor': 'rxor',
+ 'bitwise_or': 'ror',
+ #/* Comparisons */
+ 'equal': 'eq',
+ 'not_equal': 'ne',
+ 'greater': 'lt',
+ 'less': 'gt',
+ 'greater_equal': 'le',
+ 'less_equal': 'ge',
+ }
+ if op not in refops:
+ return False
+ return space.getattr(w_obj, space.wrap('__' + refops[op] + '__')) is not None
+
class W_Ufunc1(W_Ufunc):
_immutable_fields_ = ["func", "bool_result"]
nin = 1
@@ -425,19 +482,19 @@
class W_Ufunc2(W_Ufunc):
- _immutable_fields_ = ["func", "comparison_func", "done_func"]
+ _immutable_fields_ = ["func", "bool_result", "done_func"]
nin = 2
nout = 1
nargs = 3
signature = None
def __init__(self, func, name, promote_to_largest=False, promote_to_float=False,
- promote_bools=False, identity=None, comparison_func=False, int_only=False,
+ promote_bools=False, identity=None, bool_result=False, int_only=False,
allow_bool=True, allow_complex=True, complex_to_float=False):
W_Ufunc.__init__(self, name, promote_to_largest, promote_to_float, promote_bools,
identity, int_only, allow_bool, allow_complex, complex_to_float)
self.func = func
- self.comparison_func = comparison_func
+ self.bool_result = bool_result
if name == 'logical_and':
self.done_func = done_if_false
elif name == 'logical_or':
@@ -462,6 +519,15 @@
else:
[w_lhs, w_rhs] = args_w
w_out = None
+ if not isinstance(w_rhs, W_NDimArray):
+ # numpy implementation detail, useful for things like numpy.Polynomial
+ # FAIL with NotImplemented if the other object has
+ # the __r<op>__ method and has __array_priority__ as
+ # an attribute (signalling it can handle ndarray's)
+ # and is not already an ndarray or a subtype of the same type.
+ r_greater = is_rhs_priority_higher(space, w_lhs, w_rhs)
+ if r_greater and _has_reflected_op(space, w_rhs, self.name):
+ return space.w_NotImplemented
w_lhs = numpify(space, w_lhs)
w_rhs = numpify(space, w_rhs)
w_ldtype = w_lhs.get_dtype(space)
@@ -469,20 +535,20 @@
if w_ldtype.is_object() or w_rdtype.is_object():
pass
elif w_ldtype.is_str() and w_rdtype.is_str() and \
- self.comparison_func:
+ self.bool_result:
pass
elif (w_ldtype.is_str()) and \
- self.comparison_func and w_out is None:
+ self.bool_result and w_out is None:
if self.name in ('equal', 'less_equal', 'less'):
return space.wrap(False)
return space.wrap(True)
elif (w_rdtype.is_str()) and \
- self.comparison_func and w_out is None:
+ self.bool_result and w_out is None:
if self.name in ('not_equal','less', 'less_equal'):
return space.wrap(True)
return space.wrap(False)
elif w_ldtype.is_flexible() or w_rdtype.is_flexible():
- if self.comparison_func:
+ if self.bool_result:
if self.name == 'equal' or self.name == 'not_equal':
res = w_ldtype.eq(space, w_rdtype)
if not res:
@@ -520,7 +586,7 @@
else:
out = w_out
calc_dtype = out.get_dtype()
- if self.comparison_func:
+ if self.bool_result:
res_dtype = get_dtype_cache(space).w_booldtype
else:
res_dtype = calc_dtype
@@ -645,6 +711,7 @@
assert isinstance(outargs0, W_NDimArray)
res_dtype = outargs0.get_dtype()
new_shape = inargs0.get_shape()
+ # XXX use _find_array_wrap and wrap outargs using __array_wrap__
if len(outargs) < 2:
return loop.call_many_to_one(space, new_shape, func,
res_dtype, inargs, outargs[0])
@@ -737,6 +804,7 @@
for i in range(self.nout):
w_val = space.getitem(outs, space.wrap(i))
outiters[i].descr_setitem(space, space.w_Ellipsis, w_val)
+ # XXX use _find_array_wrap and wrap outargs using __array_wrap__
if len(outargs) > 1:
return space.newtuple([convert_to_array(space, o) for o in outargs])
return outargs[0]
@@ -989,8 +1057,7 @@
-def ufunc_dtype_caller(space, ufunc_name, op_name, nin, comparison_func,
- bool_result):
+def ufunc_dtype_caller(space, ufunc_name, op_name, nin, bool_result):
def get_op(dtype):
try:
return getattr(dtype.itemtype, op_name)
@@ -1008,7 +1075,7 @@
elif nin == 2:
def impl(res_dtype, lvalue, rvalue):
res = get_op(res_dtype)(lvalue, rvalue)
- if comparison_func:
+ if bool_result:
return dtype_cache.w_booldtype.box(res)
return res
return func_with_new_name(impl, ufunc_name)
@@ -1035,21 +1102,19 @@
("left_shift", "lshift", 2, {"int_only": True}),
("right_shift", "rshift", 2, {"int_only": True}),
- ("equal", "eq", 2, {"comparison_func": True}),
- ("not_equal", "ne", 2, {"comparison_func": True}),
- ("less", "lt", 2, {"comparison_func": True}),
- ("less_equal", "le", 2, {"comparison_func": True}),
- ("greater", "gt", 2, {"comparison_func": True}),
- ("greater_equal", "ge", 2, {"comparison_func": True}),
+ ("equal", "eq", 2, {"bool_result": True}),
+ ("not_equal", "ne", 2, {"bool_result": True}),
+ ("less", "lt", 2, {"bool_result": True}),
+ ("less_equal", "le", 2, {"bool_result": True}),
+ ("greater", "gt", 2, {"bool_result": True}),
+ ("greater_equal", "ge", 2, {"bool_result": True}),
("isnan", "isnan", 1, {"bool_result": True}),
("isinf", "isinf", 1, {"bool_result": True}),
("isfinite", "isfinite", 1, {"bool_result": True}),
- ('logical_and', 'logical_and', 2, {'comparison_func': True,
- 'identity': 1}),
- ('logical_or', 'logical_or', 2, {'comparison_func': True,
- 'identity': 0}),
- ('logical_xor', 'logical_xor', 2, {'comparison_func': True}),
+ ('logical_and', 'logical_and', 2, {'identity': 1}),
+ ('logical_or', 'logical_or', 2, {'identity': 0}),
+ ('logical_xor', 'logical_xor', 2, {'bool_result': True}),
('logical_not', 'logical_not', 1, {'bool_result': True}),
("maximum", "max", 2),
@@ -1131,7 +1196,6 @@
extra_kwargs["identity"] = identity
func = ufunc_dtype_caller(space, ufunc_name, op_name, nin,
- comparison_func=extra_kwargs.get("comparison_func", False),
bool_result=extra_kwargs.get("bool_result", False),
)
if nin == 1:
diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -19,8 +19,8 @@
PyFrame._virtualizable_ = ['last_instr', 'pycode',
- 'valuestackdepth', 'locals_stack_w[*]',
- 'cells[*]',
+ 'valuestackdepth',
+ 'locals_cells_stack_w[*]',
'debugdata',
'last_exception',
'lastblock',
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -435,7 +435,6 @@
guard_value(i4, 1, descr=...)
guard_isnull(p5, descr=...)
guard_nonnull_class(p12, ConstClass(W_IntObject), descr=...)
- guard_value(i8, 0, descr=...)
guard_value(p2, ConstPtr(ptr21), descr=...)
i22 = getfield_gc_pure(p12, descr=<FieldS pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
i24 = int_lt(i22, 5000)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -67,11 +67,10 @@
assert loop.match("""
f31 = raw_load(i9, i29, descr=<ArrayF 8>)
guard_not_invalidated(descr=...)
- i32 = cast_float_to_int(f31)
- i33 = int_and(i32, 255)
- guard_true(i33, descr=...)
i34 = getarrayitem_raw(#, #, descr=<ArrayU 1>) # XXX what are these?
guard_value(i34, #, descr=...) # XXX don't appear in
+ i32 = float_ne(f31, 0.000000)
More information about the pypy-commit
mailing list