[pypy-svn] r71544 - in pypy/branch/micronumpy/pypy/module/micronumpy: . test

electronicru at codespeak.net electronicru at codespeak.net
Sat Feb 27 20:13:29 CET 2010


Author: electronicru
Date: Sat Feb 27 20:13:27 2010
New Revision: 71544

Modified:
   pypy/branch/micronumpy/pypy/module/micronumpy/__init__.py
   pypy/branch/micronumpy/pypy/module/micronumpy/mdarray.py
   pypy/branch/micronumpy/pypy/module/micronumpy/sdarray.py
   pypy/branch/micronumpy/pypy/module/micronumpy/test/test_numpy.py
   pypy/branch/micronumpy/pypy/module/micronumpy/ufunc.py
Log:
Fixed nonsquare matrices issue, still working around dot() function.
TODO: test operators on multi-dimension arrays.


Modified: pypy/branch/micronumpy/pypy/module/micronumpy/__init__.py
==============================================================================
--- pypy/branch/micronumpy/pypy/module/micronumpy/__init__.py	(original)
+++ pypy/branch/micronumpy/pypy/module/micronumpy/__init__.py	Sat Feb 27 20:13:27 2010
@@ -11,5 +11,6 @@
         'ndarray'  : 'array.ndarray',
         'zeros'    : 'array.zeros',
         'minimum'  : 'ufunc.minimum',
+        'dot'      : 'ufunc.dot',
         }
 

Modified: pypy/branch/micronumpy/pypy/module/micronumpy/mdarray.py
==============================================================================
--- pypy/branch/micronumpy/pypy/module/micronumpy/mdarray.py	(original)
+++ pypy/branch/micronumpy/pypy/module/micronumpy/mdarray.py	Sat Feb 27 20:13:27 2010
@@ -2,6 +2,7 @@
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.baseobjspace import W_Root
+from pypy.objspace.std.sliceobject import W_SliceObject
 from pypy.rlib.debug import make_sure_not_resized
 
 from pypy.module.micronumpy.array import BaseNumArray
@@ -9,6 +10,8 @@
 from pypy.module.micronumpy.array import construct_array
 from pypy.module.micronumpy.array import array as array_fromseq
 from pypy.module.micronumpy.array import validate_index
+from pypy.module.micronumpy.array import \
+        mul_operation, div_operation, add_operation, sub_operation
 
 from pypy.module.micronumpy.dtype import unwrap_int, coerce_int
 from pypy.module.micronumpy.dtype import unwrap_float, coerce_float
@@ -17,8 +20,7 @@
 def compute_pos(space, indexes, dim):
     current = 1
     pos = 0
-    indexes.reverse()
-    for i in range(len(indexes)):
+    for i in range(len(indexes)-1, -1, -1):
         index = indexes[i]
         d = dim[i]
         if index >= d or index <= -d - 1:
@@ -47,7 +49,7 @@
     slicelen = i #saved
     for i in range(len(slices)):
         w_index = slices[i]
-        if space.is_true(space.isinstance(w_index, space.w_slice)):
+        if isinstance(w_index, W_SliceObject):
             newextract = []
             l = shape[i]
             stride = strides[i]
@@ -96,17 +98,94 @@
 def descr_shape(space, self):
     return space.newtuple([space.wrap(dim) for dim in self.shape])
 
+MUL = mul_operation()
+DIV = div_operation()
+ADD = add_operation()
+SUB = sub_operation()
+
 def create_mdarray(data_type, unwrap, coerce):
+
+    def create_math_operation(f):
+        opname = f.__name__
+        def math_operation(self, w_x):
+            space = self.space
+            try:
+                space.iter(w_x)
+            except OperationError, e:
+                if not e.match(space, space.w_TypeError):
+                    raise
+                result_t = result_mapping(space,
+                                            (space.type(w_x), self.dtype))
+                op2 = coerce(space, w_x)
+                result = sdresult(space, result_t)(
+                                                space, self.len(), result_t
+                                                )
+                operation = result.__class__.client_scalar[opname]
+            else:
+                op2 = array_fromseq(space, w_x)
+                if len(op2.shape) > len(self.shape):
+                    self, op2 = op2, self
+                lss = len(self.shape)
+                ls = len(op2.shape)
+                if not op2.shape == self.shape[lss-ls:lss]:
+                    raise OperationError(space.w_ValueError,
+                            space.wrap("shape mismatch: objects cannot be"
+                                         " broadcast to the same shape"))
+                result_t = result_mapping(space, (self.dtype, op2.dtype))
+                result = mdresult(space, result_t)(space, self.shape, result_t)
+                operation = result.__class__.client_fixedview[opname]
+
+            operation(result, self, op2)
+
+            w_result = space.wrap(result)
+            return w_result
+        math_operation.unwrap_spec = ['self', W_Root]
+        math_operation.__name__ = 'descr_'+opname
+        return math_operation
+
+    def create_client_math_operation(f):
+        def scalar_operation(self, source, x):
+            for i in range(len(source.storage)):
+                self.storage[i] = data_type(f(source.storage[i], x))
+
+        def fixedview_operation(self, source1, source2):
+            #Here len(s1.storage)>=len(s2.storage)
+            ll = len(source1.storage)//len(source2.storage)
+            l2 = len(source2.storage)
+            for i in range(ll):
+                for j in range(l2):
+                    idx=i*l2+j
+                    self.storage[idx] = data_type(f(source1.storage[idx],
+                                                    source2.storage[j]))
+
+        return scalar_operation, fixedview_operation
+
     class MultiDimArray(BaseMultiDimArray):
         def __init__(self, space, shape, w_dtype):
-            self.shape = shape
+            self.shape = make_sure_not_resized(shape)
             self.space = space
             self.dtype = w_dtype
             size = 1
             for dimension in shape:
                 size *= dimension
-            self.storage = [data_type(0.0)] * size
-            make_sure_not_resized(self.storage)
+            self.storage = make_sure_not_resized([data_type(0.0)] * size)
+
+        client_scalar = {}
+        client_fixedview = {}
+
+        client_scalar['mul'], client_fixedview['mul'] = \
+                                            create_client_math_operation(MUL)
+        client_scalar['div'], client_fixedview['div'] = \
+                                            create_client_math_operation(DIV)
+        client_scalar['add'], client_fixedview['add'] = \
+                                            create_client_math_operation(ADD)
+        client_scalar['sub'], client_fixedview['sub'] = \
+                                            create_client_math_operation(SUB)
+        descr_mul = create_math_operation(MUL)
+        descr_div = create_math_operation(DIV)
+        descr_add = create_math_operation(ADD)
+        descr_sub = create_math_operation(SUB)
+
 
         def load_iterable(self, w_xs):
             self._internal_load(w_xs, self.shape, [])

Modified: pypy/branch/micronumpy/pypy/module/micronumpy/sdarray.py
==============================================================================
--- pypy/branch/micronumpy/pypy/module/micronumpy/sdarray.py	(original)
+++ pypy/branch/micronumpy/pypy/module/micronumpy/sdarray.py	Sat Feb 27 20:13:27 2010
@@ -1,4 +1,5 @@
 from pypy.interpreter.baseobjspace import W_Root, Wrappable
+from pypy.objspace.std.sliceobject import W_SliceObject
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.gateway import interp2app
@@ -30,7 +31,51 @@
 def descr_shape(space, self):
     return space.newtuple([space.wrap(self.len())])
 
+
+
+MUL = mul_operation()
+DIV = div_operation()
+ADD = add_operation()
+SUB = sub_operation()
+COPY = copy_operation()
+
 def create_sdarray(data_type, unwrap, coerce):
+
+    def create_math_operation(f):
+        opname = f.__name__
+        def math_operation(self, w_x):
+            space = self.space
+            try:
+                space.iter(w_x)
+            except OperationError, e:
+                if not e.match(space, space.w_TypeError):
+                    raise
+                result_t = result_mapping(space,
+                                            (space.type(w_x), self.dtype))
+                op2 = coerce(space, w_x)
+                result = sdresult(space, result_t)(space, self.len(), result_t)
+                operation = result.__class__.client_scalar[opname]
+            else:
+                lop = space.int_w(space.len(w_x))
+                if lop != self.len():
+                    raise OperationError(space.w_ValueError,
+                            space.wrap("shape mismatch: objects cannot be"
+                                         " broadcast to the same shape"))
+                dtype = iterable_type(space, w_x)
+                result_t = result_mapping(space, (dtype, self.dtype))
+                op2 = sdresult(space, dtype)(space, lop, dtype)
+                op2.load_iterable(w_x)
+                result = sdresult(space, result_t)(space, self.len(), result_t)
+                operation = result.__class__.client_fixedview[opname]
+
+            operation(result, self, op2)
+
+            w_result = space.wrap(result)
+            return w_result
+        math_operation.unwrap_spec = ['self', W_Root]
+        math_operation.__name__ = 'descr_'+opname
+        return math_operation
+
     class SingleDimIterator(Wrappable):
         def __init__(self, space, array, i):
             self.space = space
@@ -57,12 +102,6 @@
                         next = interp2app(SingleDimIterator.descr_next)
                         )
 
-    mul = mul_operation()
-    div = div_operation()
-    add = add_operation()
-    sub = sub_operation()
-    copy = copy_operation()
-
     def create_client_math_operation(f):
         def scalar_operation(self, source, x):
             for i in range(len(source.storage)):
@@ -74,78 +113,31 @@
                     data_type(f(source1.storage[i], source2.storage[i]))
         return scalar_operation, fixedview_operation
 
-    def create_math_operation(f):
-        opname = f.__name__
-        def math_operation(self, w_x):
-            space = self.space
-            try:
-                space.iter(w_x)
-            except OperationError, e:
-                if not e.match(space, space.w_TypeError):
-                    raise
-                result_t = result_mapping(space,
-                                            (space.type(w_x), self.dtype))
-                op2 = coerce(space, w_x)
-                result = sdresult(space, result_t)(
-                                                space, self.len(), result_t
-                                                )
-                operation = result.__class__.client_scalar[opname]
-            else:
-                lop = space.int_w(space.len(w_x))
-                if lop != self.len():
-                    raise OperationError(space.w_ValueError,
-                            space.wrap("shape mismatch: objects cannot be"
-                                " broadcast to the same shape"))
-                dtype = iterable_type(space, w_x)
-                result_t = result_mapping(space, (dtype, self.dtype))
-                op2 = sdresult(space, dtype)(space, lop, dtype)
-                op2.load_iterable(w_x)
-                result = sdresult(space, result_t)(
-                                                space, self.len(), result_t
-                                                )
-                operation = result.__class__.client_fixedview[opname]
-
-            operation(result, self, op2)
-
-            w_result = space.wrap(result)
-            return w_result
-        math_operation.unwrap_spec = ['self', W_Root]
-        return math_operation
-
-
     class NumArray(BaseSingleDimArray):
         def __init__(self, space, length, dtype):
             self.shape = (length,)
             self.space = space
-            self.storage = [data_type(0.0)] * length
+            self.storage = make_sure_not_resized([data_type(0.0)] * length)
             self.dtype = dtype
-            make_sure_not_resized(self.storage)
 
         
         client_scalar = {}
         client_fixedview = {}
 
         client_scalar['mul'], client_fixedview['mul'] = \
-                                            create_client_math_operation(mul)
+                                            create_client_math_operation(MUL)
         client_scalar['div'], client_fixedview['div'] = \
-                                            create_client_math_operation(div)
+                                            create_client_math_operation(DIV)
         client_scalar['add'], client_fixedview['add'] = \
-                                            create_client_math_operation(add)
+                                            create_client_math_operation(ADD)
         client_scalar['sub'], client_fixedview['sub'] = \
-                                            create_client_math_operation(sub)
-
-
-        descr_mul = create_math_operation(mul)
-        descr_mul.__name__ = 'descr_mul'
-
-        descr_div = create_math_operation(div)
-        descr_div.__name__ = 'descr_div'
+                                            create_client_math_operation(SUB)
 
-        descr_add = create_math_operation(add)
-        descr_add.__name__ = 'descr_add'
 
-        descr_sub = create_math_operation(sub)
-        descr_sub.__name__ = 'descr_sub'
+        descr_mul = create_math_operation(MUL)
+        descr_div = create_math_operation(DIV)
+        descr_add = create_math_operation(ADD)
+        descr_sub = create_math_operation(SUB)
 
         def load_iterable(self, w_values):
             space = self.space
@@ -160,7 +152,7 @@
 
         def descr_getitem(self, w_index):
             space = self.space
-            if space.is_true(space.isinstance(w_index, space.w_slice)):
+            if isinstance(w_index, W_SliceObject):
                 start, stop, step, slen = w_index.indices4(space, self.len())
                 res = sdresult(space, self.dtype)(space, slen, self.dtype)
                 if step == 1:
@@ -185,7 +177,7 @@
 
         def descr_setitem(self, w_index, w_value):
             space = self.space
-            if space.is_true(space.isinstance(w_index, space.w_slice)):
+            if isinstance(w_index, W_SliceObject):
                 start, stop, step, slen = w_index.indices4(space, self.len())
                 try:
                     space.iter(w_value)

Modified: pypy/branch/micronumpy/pypy/module/micronumpy/test/test_numpy.py
==============================================================================
--- pypy/branch/micronumpy/pypy/module/micronumpy/test/test_numpy.py	(original)
+++ pypy/branch/micronumpy/pypy/module/micronumpy/test/test_numpy.py	Sat Feb 27 20:13:27 2010
@@ -27,7 +27,7 @@
         from numpy import array
         from operator import mul, div, add, sub
         d = range(1, self.length)
-        #FIXME: overkill...
+        #skip('overkill...')
         for data_type in (int, float):
             data = [data_type(x) for x in d]
             ar = array(data)
@@ -40,7 +40,6 @@
                 assert compare(operator(ar, ar2), [operator(x, y) for (x, y) in zip(ar, ar2)])
 
     def test_operator_result_types(self):
-        #skip("Haven't implemented dispatching for array/array operations")
         from operator import mul, div, add, sub
         from numpy import array
         types = {
@@ -163,7 +162,6 @@
         ar = array(gen_array((3,3)))
         assert len(ar) == 3
 
-        skip("Non-square matrices throw IndexError")
         #2x3
         ar = array(gen_array((2,3)))
         assert len(ar) == 2

Modified: pypy/branch/micronumpy/pypy/module/micronumpy/ufunc.py
==============================================================================
--- pypy/branch/micronumpy/pypy/module/micronumpy/ufunc.py	(original)
+++ pypy/branch/micronumpy/pypy/module/micronumpy/ufunc.py	Sat Feb 27 20:13:27 2010
@@ -1,6 +1,11 @@
-from pypy.module.micronumpy.array import array, zeros, ndarray
+from pypy.module.micronumpy.array import array, zeros, ndarray
+from pypy.module.micronumpy.array import construct_array
+from pypy.module.micronumpy.dtype import result_mapping
+from pypy.module.micronumpy.sdarray import sdresult
+from pypy.module.micronumpy.mdarray import mdresult, compute_pos
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root
 from pypy.interpreter.error import OperationError
+from pypy.rlib.debug import make_sure_not_resized
 
 def minimum(space, w_a, w_b):
     if not isinstance(w_a, ndarray) or not isinstance(w_b, ndarray):
@@ -9,7 +14,8 @@
     if w_a.len()!= w_b.len():
         raise OperationError(space.w_ValueError,
                              space.wrap("minimum of arrays of different length"))
-    res = zeros(space, space.wrap(w_a.len()), w_a.dtype)
+    dtype = result_mapping(space, (w_a.dtype, w_b.dtype))
+    res = construct_array(space, w_a.shape, dtype)
     for i in range(len(w_a.storage)):
         one = w_a.storage[i]
         two = w_b.storage[i]
@@ -19,3 +25,89 @@
             res.storage[i] = two
     return space.wrap(res)
 minimum.unwrap_spec = [ObjSpace, W_Root, W_Root]
+
+def dot(space, w_a, w_b):
+    if not isinstance(w_a, ndarray) or not isinstance(w_b, ndarray):
+        raise OperationError(space.w_TypeError,
+                space.wrap("expecting ndarray object"))
+
+    if len(w_b.shape) == 1:
+        the_b = mdresult(space, w_b.dtype)(space, [w_b.shape[0], 1], w_b.dtype)
+        the_b.storage[:] = w_b.storage
+        w_b = the_b
+
+    if len(w_a.shape)%2:
+        the_a = mdresult(space, w_a.dtype)(space, [1]+w_a.shape, w_a.dtype)
+        the_a.storage[:] = w_a.storage
+        w_a = the_a
+    ah, aw = w_a.shape[0], w_a.shape[1]
+    als = len(w_a.shape)
+
+    if len(w_b.shape)%2:
+        the_b = mdresult(space, w_b.dtype)(space, [1]+w_b.shape, w_b.dtype)
+        the_b.storage[:] = w_b.storage
+        w_b = the_b
+    bh, bw = w_a.shape[0], w_a.shape[1]
+    bls = len(w_b.shape)
+
+
+    if aw == bh == 1:
+        return dot(space, w_b, w_a)
+
+    shapemismatch = OperationError(space.w_TypeError,
+                             space.wrap('shape mismatch'))
+
+    if aw != bh:
+        raise shapemismatch
+
+    if als != bls:
+        raise shapemismatch
+    
+
+    data = _dotit(space, w_a, w_b, als, [], [])
+    if len(data) == 1:
+        return space.wrap(data[0])
+    shape = make_sure_not_resized([0]*als)
+    for i in range(0, als, 2):
+        shape[i] = w_a.shape[i]
+        shape[i+1] = w_b.shape[i+1]
+
+    dtype = result_mapping(space, (w_a.dtype, w_b.dtype))
+
+    res = construct_array(space, shape, dtype)
+    res.storage[:] = data
+    return space.wrap(res)
+dot.unwrap_spec = [ObjSpace, W_Root, W_Root]
+
+def _dotit(space, w_a, w_b, ls, indices1, indices2):
+    if len(indices1) == ls:
+        return w_a.storage[compute_pos(indices1)] * \
+               w_b.storage[compute_pos(indices2)]
+    else:
+        shift = len(indices1)
+        h = w_a.shape[shift]
+        w = w_b.shape[shift+1]
+        l = w_a.shape[shift+1]
+        if l != w_b.shape[shift]:
+            raise shapemismatch
+        total = []
+        for i in range(h):
+            for j in range(w):
+                #check if numbers on next level
+                if shift+2 == als:
+                    sum = 0
+                    for k in range(l):
+                        sum += _dotit(indices1+[i, l], indices2+[l, j])
+                    total.append(sum)
+                else:
+                    sum = None
+                    for k in range(l):
+                        arg = _dotit(indices1+[i, l], indices2+[l, j])
+                        if sum == None:
+                            sum = arg
+                        else:
+                            for idx in range(len(sum)):
+                                sum[idx] += arg[idx]
+                    total.extend(sum)
+
+        return make_sure_not_resized(total)



More information about the Pypy-commit mailing list