[pypy-commit] pypy default: merge numpy-fixes which further advances numpy complience

mattip noreply at buildbot.pypy.org
Wed May 13 17:54:05 CEST 2015


Author: mattip <matti.picus at gmail.com>
Branch: 
Changeset: r77309:bdf0f94b1bd2
Date: 2015-05-13 18:53 +0300
http://bitbucket.org/pypy/pypy/changeset/bdf0f94b1bd2/

Log:	merge numpy-fixes which further advances numpy complience

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/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):
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/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_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
@@ -13,7 +13,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 rpython.rlib.rawstorage import (raw_storage_setitem, free_raw_storage,
              alloc_raw_storage)
 from rpython.rtyper.lltypesystem import rffi, lltype
@@ -36,6 +37,21 @@
         assert isinstance(w_npyobj, W_NDimArray)
         return w_npyobj.get_dtype()
 
+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_ = [
@@ -209,7 +225,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(
@@ -225,6 +241,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:
@@ -257,6 +274,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,
@@ -265,11 +283,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"))
@@ -278,8 +300,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 "
@@ -292,10 +317,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__):
@@ -322,6 +353,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
@@ -390,24 +447,25 @@
         assert isinstance(w_obj, W_NDimArray)
         shape = shape_agreement(space, w_obj.get_shape(), out,
                                 broadcast_down=False)
+        # XXX call __array_wrap__ if out was not provided
         return loop.call1(space, shape, self.func, calc_dtype, res_dtype,
                           w_obj, out)
 
 
 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':
@@ -432,6 +490,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 = _get_dtype(space, w_lhs)
@@ -439,20 +506,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:
@@ -490,7 +557,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
@@ -613,6 +680,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])
@@ -705,6 +773,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]
@@ -1121,8 +1190,7 @@
     #            'supported', w_obj)
 
 
-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)
@@ -1140,7 +1208,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)
@@ -1167,21 +1235,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),
@@ -1263,7 +1329,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/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)
+            guard_true(i32, descr=...)
             i35 = getarrayitem_raw(#, #, descr=<ArrayU 1>)  # XXX equiv test_zjit
             i36 = int_add(i24, 1)
             i37 = int_add(i29, i28)
@@ -152,7 +151,7 @@
             f86 = float_add(f74, f85)
             i87 = int_add(i76, 1)
             --TICK--
-            jump(p0, p1, p3, p6, p7, p12, p14, f86, p18, i87, i62, p41, i58, p47, i40, i64, i70, descr=...)
+            jump(p0, p1, p6, p7, p8, p11, p13, f86, p17, i87, i62, p42, i58, p48, i41, i64, i70, descr=...)
         """)
 
     def test_array_flatiter_next(self):


More information about the pypy-commit mailing list