[pypy-commit] pypy numpy-refactor: beat it until getitem kinda works

fijal noreply at buildbot.pypy.org
Thu Aug 30 15:25:12 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: numpy-refactor
Changeset: r56933:b56af48f1efe
Date: 2012-08-30 15:19 +0200
http://bitbucket.org/pypy/pypy/changeset/b56af48f1efe/

Log:	beat it until getitem kinda works

diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py
--- a/pypy/module/micronumpy/arrayimpl/concrete.py
+++ b/pypy/module/micronumpy/arrayimpl/concrete.py
@@ -1,6 +1,8 @@
 
 from pypy.module.micronumpy.arrayimpl import base
 from pypy.module.micronumpy import support
+from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.rlib import jit
 
 class ConcreteArrayIterator(base.BaseArrayIterator):
     def __init__(self, array):
@@ -14,7 +16,7 @@
         self.dtype.setitem(self.array, self.offset, elem)
 
     def getitem(self):
-        return self.dtype.getitem(self.array, self.offset)
+        return self.array.getitem(self.offset)
 
     def next(self):
         self.offset += self.element_size
@@ -38,7 +40,14 @@
         backstrides.reverse()
     return strides, backstrides
 
+def int_w(space, w_obj):
+    # a special version that respects both __index__ and __int__
+    # XXX add __index__ support
+    return space.int_w(space.int(w_obj))
+
 class ConcreteArray(base.BaseArrayImplementation):
+    start = 0
+    
     def __init__(self, shape, dtype, order):
         self.shape = shape
         self.size = support.product(shape) * dtype.get_size()
@@ -52,3 +61,57 @@
 
     def create_iter(self):
         return ConcreteArrayIterator(self)
+
+    def getitem(self, index):
+        return self.dtype.getitem(self, index)
+
+    # -------------------- applevel get/setitem -----------------------
+
+    @jit.unroll_safe
+    def _lookup_by_index(self, space, view_w):
+        item = self.start
+        for i, w_index in enumerate(view_w):
+            if space.isinstance_w(w_index, space.w_slice):
+                raise IndexError
+            idx = int_w(space, w_index)
+            if idx < 0:
+                idx = self.shape[i] + id
+            if idx < 0 or idx >= self.shape[0]:
+                raise operationerrfmt(space.w_IndexError,
+                      "index (%d) out of range (0<=index<%d", i, self.shape[i],
+                )
+            item += idx * self.strides[i]
+        return item
+
+    def _single_item_index(self, space, w_idx):
+        """ Return an index of single item if possible, otherwise raises
+        IndexError
+        """
+        if (space.isinstance_w(w_idx, space.w_str) or
+            space.isinstance_w(w_idx, space.w_slice) or
+            space.is_w(w_idx, space.w_None)):
+            raise IndexError
+        shape_len = len(self.shape)
+        if shape_len == 0:
+            raise OperationError(space.w_IndexError, space.wrap(
+                "0-d arrays can't be indexed"))
+        if space.isinstance_w(w_idx, space.w_tuple):
+            view_w = space.fixedview(w_idx)
+            if len(view_w) < shape_len:
+                raise IndexError
+            if len(view_w) > shape_len:
+                raise OperationError(space.w_IndexError,
+                                     space.wrap("invalid index"))
+            return self._lookup_by_index(space, view_w)
+        idx = int_w(space, w_idx)
+        return self._lookup_by_index(space, [space.wrap(idx)])
+
+    def descr_getitem(self, space, w_index):
+        try:
+            item = self._single_item_index(space, w_index)
+            return self.getitem(item)
+        except IndexError:
+            # not a single result
+            chunks = self._prepare_slice_args(space, w_index)
+            return chunks.apply(self)
+
diff --git a/pypy/module/micronumpy/arrayimpl/scalar.py b/pypy/module/micronumpy/arrayimpl/scalar.py
--- a/pypy/module/micronumpy/arrayimpl/scalar.py
+++ b/pypy/module/micronumpy/arrayimpl/scalar.py
@@ -6,9 +6,13 @@
     
     def __init__(self, dtype):
         self.value = None
+        self.dtype = dtype
 
     def get_shape(self):
         return []
 
     def set_scalar_value(self, value):
         self.value = value
+
+    def get_scalar_value(self):
+        return self.value
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -19,7 +19,7 @@
 
 def scalar_w(space, dtype, w_object):
     arr = W_NDimArray([], dtype)
-    arr.implementation.set_scalar_value(w_object)
+    arr.implementation.set_scalar_value(dtype.coerce(space, w_object))
     return arr
 
 class W_NDimArray(Wrappable):
@@ -50,12 +50,21 @@
     def descr_get_ndim(self, space):
         return space.wrap(len(self.get_shape()))
 
+    def descr_getitem(self, space, w_idx):
+        if (isinstance(w_idx, W_NDimArray) and w_idx.get_shape() == self.get_shape() and
+            w_idx.get_dtype().is_bool_type()):
+            return self.getitem_filter(space, w_idx)
+        return self.implementation.descr_getitem(space, w_idx)
+
     def create_iter(self):
         return self.implementation.create_iter()
 
     def is_scalar(self):
         return self.implementation.is_scalar
 
+    def get_scalar_value(self):
+        return self.implementation.get_scalar_value()
+
     def _binop_impl(ufunc_name):
         def impl(self, space, w_other, w_out=None):
             return getattr(interp_ufuncs.get(space), ufunc_name).call(space,
@@ -78,6 +87,8 @@
 
     __add__ = interp2app(W_NDimArray.descr_add),
 
+    __getitem__ = interp2app(W_NDimArray.descr_getitem),
+
     dtype = GetSetProperty(W_NDimArray.descr_get_dtype),
     shape = GetSetProperty(W_NDimArray.descr_get_shape,
                            W_NDimArray.descr_set_shape),
@@ -94,7 +105,10 @@
 def array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False,
           ndmin=0):
     if not space.issequence_w(w_object):
-        dtype = decode_w_dtype(space, w_dtype)
+        if w_dtype is None or space.is_w(w_dtype, space.w_None):
+            w_dtype = interp_ufuncs.find_dtype_for_scalar(space, w_object)
+        dtype = space.interp_w(interp_dtype.W_Dtype,
+          space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype))
         return scalar_w(space, dtype, w_object)
     if w_order is None or space.is_w(w_order, space.w_None):
         order = 'C'
@@ -130,8 +144,15 @@
         arr_iter.next()
     return arr
 
-def zeros(space):
-    pass
+ at unwrap_spec(order=str)
+def zeros(space, w_shape, w_dtype=None, order='C'):
+    dtype = space.interp_w(interp_dtype.W_Dtype,
+        space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+    )
+    shape = _find_shape(space, w_shape)
+    if not shape:
+        return scalar_w(space, dtype, space.wrap(0))
+    return space.wrap(W_NDimArray(shape, dtype=dtype, order=order))
 
 def ones(space):
     pass
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -323,13 +323,14 @@
             res_dtype = calc_dtype
         if w_lhs.is_scalar() and w_rhs.is_scalar():
             arr = self.func(calc_dtype,
-                w_lhs.value.convert_to(calc_dtype),
-                w_rhs.value.convert_to(calc_dtype)
+                w_lhs.get_scalar_value().convert_to(calc_dtype),
+                w_rhs.get_scalar_value().convert_to(calc_dtype)
             )
-            if out.is_scalar():
-                out.set_value(arr)
-            elif isinstance(out, W_NDimArray):
-                out.fill(space, arr)
+            if isinstance(out, W_NDimArray):
+                if out.is_scalar():
+                    out.set_scalar_value(arr)
+                else:
+                    out.fill(space, arr)
             else:
                 out = arr
             return space.wrap(out)
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
@@ -9,14 +9,16 @@
     return i
 
 def convert_to_array(space, w_obj):
-    from pypy.module.micronumpy.interp_numarray import W_NDimArray, array
+    from pypy.module.micronumpy.interp_numarray import W_NDimArray, array,\
+         scalar_w
+    from pypy.module.micronumpy import interp_ufuncs
+    
     if isinstance(w_obj, W_NDimArray):
         return w_obj
     elif space.issequence_w(w_obj):
         # Convert to array.
         return array(space, w_obj, w_order=None)
     else:
-        xxxx
         # If it's a scalar
         dtype = interp_ufuncs.find_dtype_for_scalar(space, w_obj)
         return scalar_w(space, dtype, w_obj)


More information about the pypy-commit mailing list