[pypy-svn] r46178 - in pypy/dist/pypy/rpython/numpy: . test

simonb at codespeak.net simonb at codespeak.net
Thu Aug 30 02:59:56 CEST 2007


Author: simonb
Date: Thu Aug 30 02:59:54 2007
New Revision: 46178

Modified:
   pypy/dist/pypy/rpython/numpy/aarray.py
   pypy/dist/pypy/rpython/numpy/rarray.py
   pypy/dist/pypy/rpython/numpy/test/test_array.py
Log:
numpy: progress with indexing, iterators dissapear with malloc removal

Modified: pypy/dist/pypy/rpython/numpy/aarray.py
==============================================================================
--- pypy/dist/pypy/rpython/numpy/aarray.py	(original)
+++ pypy/dist/pypy/rpython/numpy/aarray.py	Thu Aug 30 02:59:54 2007
@@ -72,20 +72,6 @@
     add = sub = mul = div = truediv = union
 
 
-class __extend__(pairtype(SomeArray, SomeInteger)):
-    def setitem((s_array, s_index), s_value):
-        if s_array.ndim == 0:
-            raise AnnotatorError()
-        if isinstance(s_value, SomeArray):
-            assert s_array.ndim == s_value.ndim + 1
-
-    def getitem((s_array, s_index)):
-        if s_array.ndim == 0:
-            raise AnnotatorError()
-        if s_array.ndim > 1:
-            return SomeArray(s_array.typecode, s_array.ndim-1)
-        return s_array.get_item_type()
-
 class __extend__(pairtype(SomeArray, SomeTuple)):
     def get_leftover_dim((s_array, s_index)):
         ndim = s_array.ndim
@@ -100,8 +86,10 @@
 
     def setitem((s_array, s_index), s_value):
         ndim = pair(s_array, s_index).get_leftover_dim()
+        if len(s_index.items)>s_array.ndim:
+            raise AnnotatorError("invalid index")
         if isinstance(s_value, SomeArray):
-            if s_value.ndim + ndim != s_array.ndim:
+            if s_value.ndim != ndim:
                 # XX allow broadcasting..
                 raise AnnotatorError("shape mismatch")
         elif ndim > 0:
@@ -109,12 +97,33 @@
 
     def getitem((s_array, s_index)):
         ndim = pair(s_array, s_index).get_leftover_dim()
+        if len(s_index.items)>s_array.ndim:
+            raise AnnotatorError("invalid index")
         if s_array.ndim == 0 and len(s_index.items):
             raise AnnotatorError("indexing rank zero array with nonempty tuple")
         if ndim > 0:
             return SomeArray(s_array.typecode, ndim)
         return s_array.get_item_type()
 
+# These two up-cast the index to SomeTuple and call above.
+class __extend__(pairtype(SomeArray, SomeSlice)):
+    def setitem((s_array, s_index), s_value):
+        s_tuple = SomeTuple([s_index])
+        return pair(s_array, s_tuple).setitem(s_value)
+
+    def getitem((s_array, s_index)):
+        s_tuple = SomeTuple([s_index])
+        return pair(s_array, s_tuple).getitem()
+
+class __extend__(pairtype(SomeArray, SomeInteger)):
+    def setitem((s_array, s_index), s_value):
+        s_tuple = SomeTuple([s_index])
+        return pair(s_array, s_tuple).setitem(s_value)
+
+    def getitem((s_array, s_index)):
+        s_tuple = SomeTuple([s_index])
+        return pair(s_array, s_tuple).getitem()
+
 numpy_typedict = {
     (SomeInteger, rffi.r_signedchar) : 'b', 
     (SomeInteger, rffi.r_short) : 'h', 
@@ -159,9 +168,9 @@
             raise AnnotatorError("List item type not supported")
         return SomeArray(typecode, ndim)
 
-    def specialize_call(self, hop):
+    def specialize_call(self, hop, i_dtype=None):
         r_array = hop.r_result
-        [v_lst] = hop.inputargs(r_array) # coerce list arg to array arg
+        v_lst = hop.inputarg(r_array, 0) # coerce list arg to array arg
         v_result = r_array.build_from_array(hop.llops, v_lst)
         return v_result
 
@@ -197,10 +206,10 @@
 #        v_result = r_array.build_from_shape(hop.llops, r_lst, v_lst)
 #        return v_result
 
-    def specialize_call(self, hop):
+    def specialize_call(self, hop, i_dtype=None):
         r_tpl = hop.args_r[0]
         # XX also call with single int arg
-        [v_tpl] = hop.inputargs(r_tpl)
+        v_tpl = hop.inputarg(r_tpl, 0)
         r_array = hop.r_result
         v_result = r_array.build_from_shape(hop.llops, r_tpl, v_tpl)
         return v_result

Modified: pypy/dist/pypy/rpython/numpy/rarray.py
==============================================================================
--- pypy/dist/pypy/rpython/numpy/rarray.py	(original)
+++ pypy/dist/pypy/rpython/numpy/rarray.py	Thu Aug 30 02:59:54 2007
@@ -2,14 +2,18 @@
 from pypy.rpython.rrange import AbstractRangeRepr
 from pypy.rpython.rint import IntegerRepr
 from pypy.rpython.rlist import AbstractBaseListRepr
+from pypy.rpython.rtuple import AbstractTupleRepr
 from pypy.rpython.error import TyperError
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE
+from pypy.rpython.rslice import AbstractSliceRepr
 from pypy.rpython.lltypesystem.lltype import \
-     GcArray, GcStruct, Signed, Ptr, Unsigned, malloc, Void
+    GcArray, GcStruct, Signed, Ptr, Unsigned, Void, FixedSizeArray, Bool,\
+    malloc, direct_arrayitems, direct_ptradd
+from pypy.rpython.lltypesystem.rtuple import TupleRepr
 from pypy.annotation.model import SomeObject, SomeInteger
 from pypy.rpython.numpy.aarray import SomeArray
-from pypy.annotation.pairtype import pairtype
+from pypy.annotation.pairtype import pairtype, pair
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.annotation import listdef
 from pypy.rpython.memory.lltypelayout import sizeof
@@ -40,47 +44,110 @@
         return shape
     return ll_get_shape
 
+NPY_INTP = Signed # index type (see Py_intptr_t)
+def ARRAY_ITER(ARRAY, INDEXARRAY):
+    ITER = Ptr(
+        GcStruct("array_iter",
+            ("nd_m1", Signed), # number of dimensions - 1 
+            ("index", NPY_INTP),
+            ("size", NPY_INTP),
+            ("coordinates", INDEXARRAY), 
+            ("dims_m1", INDEXARRAY),
+            ("strides", INDEXARRAY),
+            ("backstrides", INDEXARRAY),
+            #("factors", INDEXARRAY),
+            ("ao", ARRAY),
+            ("dataptr", Ptr(FixedSizeArray(ARRAY.TO.data.TO.OF, 1))), # pointer to current item
+            #("contiguous", Bool),
+        ))
+    return ITER
+
+def ll_mul_list(items, n):
+    result = 1
+    while n:
+        result *= items[n-1]
+        n -= 1
+    return result
+
+def gen_iter_funcs(ndim):
+    unroll_ndim = unrolling_iterable(range(ndim))
+    unroll_ndim_rev = unrolling_iterable(reversed(range(ndim)))
+
+    def ll_iter_reset(it):
+        it.index = 0
+        it.dataptr = direct_arrayitems(it.ao.data)
+        for i in unroll_ndim:
+            it.coordinates[i] = 0
+
+    def ll_iter_new(ITER, ao):
+        it = malloc(ITER)
+        it.nd_m1 = ndim - 1
+        it.size = ll_mul_list(ao.shape, ndim)
+        it.ao = ao
+        #it.factors[nd-1] = 1
+        for i in unroll_ndim:
+            it.dims_m1[i] = ao.shape[i]-1
+            it.strides[i] = ao.strides[i]
+            it.backstrides[i] = it.strides[i] * it.dims_m1[i]
+            #if i > 0:
+                #it.factors[nd-i-1] = it.factors[nd]*ao.shape[nd-i]
+    #    ll_iter_reset(it)
+        it.index = 0
+        it.dataptr = direct_arrayitems(it.ao.data)
+        for i in unroll_ndim:
+            it.coordinates[i] = 0
+        return it
+    ll_iter_new._always_inline_ = True
+    
+    def ll_iter_next(it):
+        it.index += 1
+        for i in unroll_ndim_rev:
+            if it.coordinates[i] < it.dims_m1[i]:
+                it.coordinates[i] += 1
+                it.dataptr = direct_ptradd(it.dataptr, it.strides[i])
+                break
+            it.coordinates[i] = 0
+            it.dataptr = direct_ptradd(it.dataptr, -it.backstrides[i])
+            i -= 1
+    ll_iter_next._always_inline_ = True
+
+    return ll_iter_new, ll_iter_next
+
+def ll_setitem_from_array(iter_new0, iter_next0, ITER0, array0, 
+                          slice, 
+                          iter_new1, iter_next1, ITER1, array1):
+    it0 = iter_new0(ITER0, array0)
+    it1 = iter_new1(ITER1, array1)
+    while it0.index < it0.size:
+        it0.dataptr[0] = it1.dataptr[0]
+        iter_next0(it0)
+        iter_next1(it1)
 
 class ArrayRepr(Repr):
     def __init__(self, rtyper, s_array):
         self.s_array = s_array
         self.s_value = s_array.get_item_type()
-        self.item_repr = rtyper.getrepr(self.s_value)
-        ITEM = self.item_repr.lowleveltype
-        ITEMARRAY = GcArray(ITEM, hints={'nolength':True})
-        SIZEARRAY = GcArray(Signed, hints={'nolength':True})
-        self.PTR_SIZEARRAY = Ptr(SIZEARRAY)
-        self.itemsize = sizeof(ITEM)
         self.ndim = s_array.ndim
+        self.item_repr = rtyper.getrepr(self.s_value)
+        self.ITEM = self.item_repr.lowleveltype
+        ITEMARRAY = GcArray(self.ITEM, hints={'nolength':True})
+        self.INDEXARRAY = FixedSizeArray(NPY_INTP, self.ndim)
+        self.itemsize = sizeof(self.ITEM)
         self.ARRAY = Ptr(
             GcStruct("array",
                 ("data", Ptr(ITEMARRAY)), # pointer to raw data buffer 
-                ("ndim", Signed), # number of dimensions
-                ("shape", self.PTR_SIZEARRAY), # size in each dimension
-                ("strides", self.PTR_SIZEARRAY), # bytes (?) to jump to get to the
+                ("ndim", Signed), # number of dimensions (do we need this ?)
+                ("shape", self.INDEXARRAY), # size in each dimension
+                ("strides", self.INDEXARRAY), # elements to jump to get to the
                                                  # next element in each dimension 
             ))
         self.lowleveltype = self.ARRAY
+        self.ITER = ARRAY_ITER(self.ARRAY, self.INDEXARRAY)
 
     def build_from_array(self, llops, v_array):
         cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) 
         return llops.gendirectcall(ll_build_alias, cARRAY, v_array)
 
-#    def build_from_shape(self, llops, r_tuple, v_tuple):
-#        cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) 
-#        cTUPLE = inputconst(lltype.Void, r_tuple.lowleveltype.TO)
-#        ndim = self.ndim
-#        c_ndim = inputconst(lltype.Signed, ndim)
-#        assert ndim == len(r_tuple.items_r)
-#        v_array = llops.gendirectcall(ll_allocate, cARRAY, c_ndim)
-#        c_attr = inputconst(lltype.Void, 'shape')
-#        v_shape = llops.genop('getfield', [v_array, c_attr], self.PTR_SIZEARRAY)
-#        for i in range(ndim):
-#            v_size = r_tuple.getitem_internal(llops, v_tuple, i)
-#            v_i = inputconst(lltype.Signed, i)
-#            llops.genop('setarrayitem', [v_shape, v_i, v_size])
-#        return v_array
-        
     def build_from_shape(self, llops, r_tuple, v_tuple):
         cARRAY = inputconst(lltype.Void, self.lowleveltype.TO) 
         cTUPLE = inputconst(lltype.Void, r_tuple.lowleveltype.TO)
@@ -130,21 +197,57 @@
 
 
 class __extend__(pairtype(ArrayRepr, ArrayRepr)):
-    def rtype_add((r_arr1,r_arr2), hop):
+    def rtype_add((r_arr1, r_arr2), hop):
         v_arr1, v_arr2 = hop.inputargs(r_arr1, r_arr2)
         cARRAY = hop.inputconst(Void, hop.r_result.ARRAY.TO)
         return hop.gendirectcall(ll_add, cARRAY, v_arr1, v_arr2)
 
 
 class __extend__(pairtype(ArrayRepr, IntegerRepr)):
-    def rtype_setitem((r_arr,r_int), hop):
+    def rtype_setitem((r_arr, r_int), hop):
         v_array, v_index, v_item = hop.inputargs(r_arr, Signed, r_arr.item_repr)
         return hop.gendirectcall(ll_setitem, v_array, v_index, v_item)
 
-    def rtype_getitem((r_arr,r_int), hop):
+    def rtype_getitem((r_arr, r_int), hop):
         v_array, v_index = hop.inputargs(r_arr, Signed)
         return hop.gendirectcall(ll_getitem, v_array, v_index)
 
+#class __extend__(pairtype(ArrayRepr, AbstractTupleRepr)):
+#    def rtype_setitem((r_arr, r_tpl), hop):
+#        v_array, v_tuple, v_item = hop.inputargs(r_arr, r_tpl, r_arr)
+#        return hop.gendirectcall(ll_setitem_from_array, v_array, v_tuple, v_item)
+#
+#    def rtype_getitem((r_arr, r_tpl), hop):
+#        return NotImplemented
+
+
+class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)):
+    def rtype_setitem((r_arr, r_slc), hop):
+        r_item = hop.args_r[2]
+        v_array, v_slc, v_item = hop.inputargs(r_arr, r_slc, r_item)
+        cITER0 = hop.inputconst(Void, r_arr.ITER.TO)
+        cITER1 = hop.inputconst(Void, r_item.ITER.TO)
+        iter_new0, iter_next0 = gen_iter_funcs(r_arr.ndim)        
+        iter_new1, iter_next1 = gen_iter_funcs(r_item.ndim)        
+        cnew0 = hop.inputconst(Void, iter_new0)
+        cnext0 = hop.inputconst(Void, iter_next0)
+        cnew1 = hop.inputconst(Void, iter_new1)
+        cnext1 = hop.inputconst(Void, iter_next1)
+#        return hop.gendirectcall(ll_setitem_from_array, cnext, cITER0, v_array, v_slc, cITER1, v_item)
+        return hop.gendirectcall(ll_setitem_from_array,
+            cnew0, cnext0, cITER0, v_array, v_slc, cnew1, cnext1, cITER1, v_item)
+        
+
+#class __extend__(pairtype(ArrayRepr, AbstractSliceRepr)):
+#    # promote and delegate  XX doesn't work
+#    def rtype_setitem((r_arr, r_slc), hop):
+#        r_tpl = TupleRepr(hop.rtyper, [r_slc])
+#        return pair(r_arr, r_tpl).rtype_setitem(hop)
+#
+#    def rtype_getitem((r_arr, r_slc), hop):
+#        r_tpl = TupleRepr(hop.rtyper, [r_slc])
+#        return pair(r_arr, r_tpl).rtype_getitem(hop)
+
 class __extend__(pairtype(AbstractBaseListRepr, ArrayRepr)):
     def convert_from_to((r_lst, r_arr), v, llops):
         if r_lst.listitem is None:
@@ -163,8 +266,8 @@
 def ll_allocate(ARRAY, ndim):
     array = malloc(ARRAY)
     array.ndim = ndim
-    array.shape = malloc(ARRAY.shape.TO, array.ndim)
-    array.strides = malloc(ARRAY.strides.TO, array.ndim)
+    #array.shape = malloc(ARRAY.shape.TO, array.ndim)
+    #array.strides = malloc(ARRAY.strides.TO, array.ndim)
     return array
 
 def ll_build_from_list(ARRAY, lst):

Modified: pypy/dist/pypy/rpython/numpy/test/test_array.py
==============================================================================
--- pypy/dist/pypy/rpython/numpy/test/test_array.py	(original)
+++ pypy/dist/pypy/rpython/numpy/test/test_array.py	Thu Aug 30 02:59:54 2007
@@ -86,7 +86,10 @@
             a = numpy.zeros((3,4,5))
             b = a[0]
             a[0,1,2] = 1.
-            b[0,1] = a[2]
+            b[0,1] = 2.
+            b[:] = a[1]
+            b[:,:] = a[1]
+            b[0,:] = a[1,2]
             return b
 
         t = TranslationContext()
@@ -180,7 +183,7 @@
 
     def test_specialize_array_access(self):
         def access_with_variable():
-            my_array = numpy.array(range(10))
+            my_array = numpy.array(range(10), dtype='i')
             my_array[2] = 2
             sum = 0
             for idx in range(10):
@@ -238,14 +241,41 @@
         assert res.data[0] == 1
         assert res.data[1] == 2
 
-    def X_test_specialize_view(self):
+    def test_specialize_indexing(self):
+        def f():
+            a = numpy.zeros((3,), dtype='i')
+            b = numpy.array([5,55,555])
+            a[:] = b
+            return a
+        #self.specialize_view(f)
+        res = interpret(f, [])
+        assert res.data[0] == 5
+        assert res.data[1] == 55
+        assert res.data[2] == 555
+
+    def specialize_view(self, f, args=[]):
         t = TranslationContext()
         a = t.buildannotator()
-        a = a.build_types(f, [])
+        a = a.build_types(f, args)
         r = t.buildrtyper()
         r.specialize()
+        from pypy.translator.backendopt.all import backend_optimizations
+        backend_optimizations(t, inline=True)
         t.view()
 
+#from pypy.rlib.unroll import unrolling_iterable, unrolling_zero
+#unroller = unrolling_iterable((1,2,3))
+#def deep_f(result, i):
+#    result += 1
+#    if i<5:
+#        result *= deep_f(result, i+1)
+#    return result
+#
+#def deep_unroll():
+##    i = unrolling_zero
+#    i = 0
+#    return deep_f(0, i)
+
 class Test_compile:
     def setup_class(self):
         if not test_c_compile:
@@ -265,6 +295,7 @@
         assert fn(1) == 99
         
     def test_compile_2d(self):
+        py.test.skip()
         def access_array(index):
             a = numpy.zeros((5,6))
             a[0,0] = 2



More information about the Pypy-commit mailing list