Commits

Maciej Fijalkowski committed 200be74

implement isnan/isinf

  • Participants
  • Parent commits 27230fa
  • Branches numpy-back-to-applevel

Comments (0)

Files changed (8)

lib_pypy/numpypy/core/arrayprint.py

 
 import sys
 import _numpypy as _nt
-from _numpypy import maximum, minimum, absolute, not_equal #, isnan, isinf
+from _numpypy import maximum, minimum, absolute, not_equal, isinf, isnan
 #from _numpypy import format_longfloat, datetime_as_string, datetime_data, isna
-from fromnumeric import ravel
+from .fromnumeric import ravel
 
 
 def product(x, y): return x*y

lib_pypy/numpypy/core/fromnumeric.py

            'rank', 'size', 'around', 'round_', 'mean', 'std', 'var', 'squeeze',
            'amax', 'amin',
           ]
-          
+
 def take(a, indices, axis=None, out=None, mode='raise'):
     """
     Take elements from an array along an axis.

pypy/module/micronumpy/__init__.py

         ("tan", "tan"),
         ('bitwise_and', 'bitwise_and'),
         ('bitwise_or', 'bitwise_or'),
+        ('isnan', 'isnan'),
+        ('isinf', 'isinf'),
     ]:
         interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl
 

pypy/module/micronumpy/interp_numarray.py

 
 
 class Call1(VirtualArray):
-    def __init__(self, ufunc, name, shape, res_dtype, values):
+    def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, values):
         VirtualArray.__init__(self, name, shape, res_dtype)
         self.values = values
         self.size = values.size
         self.ufunc = ufunc
+        self.calc_dtype = calc_dtype
 
     def _del_sources(self):
         self.values = None

pypy/module/micronumpy/interp_ufuncs.py

     _immutable_fields_ = ["func", "name"]
 
     def __init__(self, func, name, promote_to_float=False, promote_bools=False,
-        identity=None):
+        identity=None, bool_result=False):
 
         W_Ufunc.__init__(self, name, promote_to_float, promote_bools, identity)
         self.func = func
+        self.bool_result = bool_result
 
     def call(self, space, args_w):
         from pypy.module.micronumpy.interp_numarray import (Call1,
 
         [w_obj] = args_w
         w_obj = convert_to_array(space, w_obj)
-        res_dtype = find_unaryop_result_dtype(space,
-            w_obj.find_dtype(),
-            promote_to_float=self.promote_to_float,
-            promote_bools=self.promote_bools,
-        )
+        calc_dtype = find_unaryop_result_dtype(space,
+                                  w_obj.find_dtype(),
+                                  promote_to_float=self.promote_to_float,
+                                  promote_bools=self.promote_bools)
+        if self.bool_result:
+            res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
+        else:
+            res_dtype = calc_dtype
         if isinstance(w_obj, Scalar):
-            return self.func(res_dtype, w_obj.value.convert_to(res_dtype))
+            return self.func(calc_dtype, w_obj.value.convert_to(calc_dtype))
 
-        w_res = Call1(self.func, self.name, w_obj.shape, res_dtype, w_obj)
+        w_res = Call1(self.func, self.name, w_obj.shape, calc_dtype, res_dtype,
+                      w_obj)
         w_obj.add_invalidates(w_res)
         return w_res
 
     return interp_dtype.get_dtype_cache(space).w_float64dtype
 
 
-def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func):
+def ufunc_dtype_caller(space, ufunc_name, op_name, argcount, comparison_func,
+                       bool_result):
+    dtype_cache = interp_dtype.get_dtype_cache(space)
     if argcount == 1:
         def impl(res_dtype, value):
-            return getattr(res_dtype.itemtype, op_name)(value)
+            res = getattr(res_dtype.itemtype, op_name)(value)
+            if bool_result:
+                return dtype_cache.w_booldtype.box(res)
+            return res
     elif argcount == 2:
-        dtype_cache = interp_dtype.get_dtype_cache(space)
         def impl(res_dtype, lvalue, rvalue):
             res = getattr(res_dtype.itemtype, op_name)(lvalue, rvalue)
             if comparison_func:
             ("less_equal", "le", 2, {"comparison_func": True}),
             ("greater", "gt", 2, {"comparison_func": True}),
             ("greater_equal", "ge", 2, {"comparison_func": True}),
+            ("isnan", "isnan", 1, {"bool_result": True}),
+            ("isinf", "isinf", 1, {"bool_result": True}),
 
             ("maximum", "max", 2),
             ("minimum", "min", 2),
 
         func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount,
             comparison_func=extra_kwargs.get("comparison_func", False),
+            bool_result=extra_kwargs.get("bool_result", False),
         )
         if argcount == 1:
             ufunc = W_Ufunc1(func, ufunc_name, **extra_kwargs)

pypy/module/micronumpy/signature.py

     def eval(self, frame, arr):
         from pypy.module.micronumpy.interp_numarray import Call1
         assert isinstance(arr, Call1)
-        v = self.child.eval(frame, arr.values).convert_to(arr.res_dtype)
-        return self.unfunc(arr.res_dtype, v)
+        v = self.child.eval(frame, arr.values).convert_to(arr.calc_dtype)
+        return self.unfunc(arr.calc_dtype, v)
 
 class Call2(Signature):
     _immutable_fields_ = ['binfunc', 'name', 'calc_dtype', 'left', 'right']

pypy/module/micronumpy/test/test_ufuncs.py

     def test_true_divide(self):
         from _numpypy import arange, array, true_divide
         assert (true_divide(arange(3), array([2, 2, 2])) == array([0, 0.5, 1])).all()
+
+    def test_isnan_isinf(self):
+        from _numpypy import isnan, isinf, float64, array
+        assert isnan(float('nan'))
+        assert isnan(float64(float('nan')))
+        assert not isnan(3)
+        assert isinf(float('inf'))
+        assert not isnan(3.5)
+        assert not isinf(3.5)
+        assert not isnan(float('inf'))
+        assert not isinf(float('nan'))
+        assert (isnan(array([0.2, float('inf'), float('nan')])) == [False, False, True]).all()
+        assert (isinf(array([0.2, float('inf'), float('nan')])) == [False, True, False]).all()
+        assert isinf(array([0.2])).dtype.kind == 'b'

pypy/module/micronumpy/types.py

         )
     return dispatcher
 
+def raw_unary_op(func):
+    specialize.argtype(1)(func)
+    @functools.wraps(func)
+    def dispatcher(self, v):
+        return func(
+            self,
+            self.for_computation(self.unbox(v))
+        )
+    return dispatcher
+
 def simple_binary_op(func):
     specialize.argtype(1, 2)(func)
     @functools.wraps(func)
     def abs(self, v):
         return abs(v)
 
+    @raw_unary_op
+    def isnan(self, v):
+        return False
+
+    @raw_unary_op
+    def isinf(self, v):
+        return False
+
     @raw_binary_op
     def eq(self, v1, v2):
         return v1 == v2
         except ValueError:
             return rfloat.NAN
 
+    @raw_unary_op
+    def isnan(self, v):
+        return rfloat.isnan(v)
+
+    @raw_unary_op
+    def isinf(self, v):
+        return rfloat.isinf(v)
+
 
 class Float32(BaseType, Float):
     T = rffi.FLOAT