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

electronicru at codespeak.net electronicru at codespeak.net
Thu Mar 11 11:13:29 CET 2010


Author: electronicru
Date: Thu Mar 11 11:13:27 2010
New Revision: 72092

Modified:
   pypy/branch/micronumpy/pypy/module/micronumpy/array.py
   pypy/branch/micronumpy/pypy/module/micronumpy/dtype.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
Log:
Added many tests and fixed many old errors for sd/mdarray;
fixed Ellipsis behavior, None behavior in indices; newaxis added and tested.
TODO: multiindexing sdarrays.


Modified: pypy/branch/micronumpy/pypy/module/micronumpy/array.py
==============================================================================
--- pypy/branch/micronumpy/pypy/module/micronumpy/array.py	(original)
+++ pypy/branch/micronumpy/pypy/module/micronumpy/array.py	Thu Mar 11 11:13:27 2010
@@ -13,17 +13,19 @@
     pass
 
 def validate_index(array, space, w_i):
-    try:
-        index_dimensionality = space.int_w(space.len(w_i))
-        array_dimensionality = len(array.shape)
-        if index_dimensionality > array_dimensionality:
-            raise OperationError(space.w_IndexError,
-                    space.wrap("Index dimensionality (%d) "
-                        "greater than array dimensionality (%d)."
-                        % (index_dimensionality, array_dimensionality)))
-    except OperationError, e:
-        if e.match(space, space.w_TypeError): pass
-        else: raise
+    index_dimensionality = space.int_w(space.len(w_i))
+    array_dimensionality = len(array.shape)
+    for w_index in space.fixedview(w_i):
+        if not ( space.is_true(space.isinstance(w_index, space.w_int)) or
+                space.is_true(space.isinstance(w_index, space.w_slice)) or
+                space.is_true(space.isinstance(w_index, space.w_list)) or
+                space.is_w(w_index, space.w_Ellipsis) ):
+            raise OperationError(space.w_ValueError,
+                    space.wrap("each subindex must be either a slice, "
+                        "an integer, Ellipsis, or newaxis"))
+    if index_dimensionality > array_dimensionality:
+        raise OperationError(space.w_IndexError,
+                space.wrap("invalid index")) # all as in numpy
 
 def mul_operation():
     def mul(x, y): return x * y
@@ -79,7 +81,7 @@
         except OperationError, e:
             if e.match(space, space.w_TypeError):
                 break
-            elif e.match(space, space.IndexError):
+            elif e.match(space, space.w_IndexError):
                 break #as numpy does
             else:
                 raise

Modified: pypy/branch/micronumpy/pypy/module/micronumpy/dtype.py
==============================================================================
--- pypy/branch/micronumpy/pypy/module/micronumpy/dtype.py	(original)
+++ pypy/branch/micronumpy/pypy/module/micronumpy/dtype.py	Thu Mar 11 11:13:27 2010
@@ -123,11 +123,11 @@
 
     def sdarray(self, space, length, w_dtype):
         from pypy.module.micronumpy.sdarray import sdresult
-        return sdresult(self.typecode(space))(space, length, w_dtype)
+        return sdresult(self.typecode(space, w_dtype))(space, length, w_dtype)
 
     def mdarray(self, space, shape, w_dtype):
         from pypy.module.micronumpy.mdarray import mdresult
-        return mdresult(self.typecode(space))(space, shape, w_dtype)
+        return mdresult(self.typecode(space, w_dtype))(space, shape, w_dtype)
 
 dtypes = DynamicTypes()
 iterable_type = dtypes.iterable_type
@@ -135,3 +135,5 @@
 result_mapping = dtypes.result_mapping
 get_dtype = dtypes.get_dtype
 retrieve_dtype = dtypes.retrieve_dtype
+sdarray = dtypes.sdarray
+mdarray = dtypes.mdarray

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	Thu Mar 11 11:13:27 2010
@@ -3,11 +3,13 @@
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.baseobjspace import W_Root, UnpackValueError
 from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.listobject import W_ListObject
+from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.rlib.debug import make_sure_not_resized
 
 from pypy.module.micronumpy.array import BaseNumArray
 from pypy.module.micronumpy.array import base_typedef
-from pypy.module.micronumpy.array import construct_array
+from pypy.module.micronumpy.array import construct_array, infer_shape
 from pypy.module.micronumpy.array import array as array_fromseq
 from pypy.module.micronumpy.array import validate_index
 from pypy.module.micronumpy.array import \
@@ -15,7 +17,8 @@
 
 from pypy.module.micronumpy.dtype import unwrap_int, coerce_int
 from pypy.module.micronumpy.dtype import unwrap_float, coerce_float
-from pypy.module.micronumpy.dtype import create_factory
+from pypy.module.micronumpy.dtype import create_factory, result_mapping
+from pypy.module.micronumpy.dtype import retrieve_dtype
 
 def compute_pos(space, indexes, dim):
     current = 1
@@ -44,9 +47,13 @@
     extract = [0]
     slicelen = stride #saved
     unoptimized = True
-    for i in range(len(slices)):
+    lenslices = len(slices)
+    add = 0 # add to index
+    for i in range(lenslices):
         factor = slicelen / strides[i-1] if i>0 else 1
         w_index = slices[i]
+        i += add
+        # somewhere here must be newaxis handling
         if isinstance(w_index, W_SliceObject):
             l = shape[i]
             stride = strides[i]
@@ -65,7 +72,15 @@
                         extract[j] += start
                     unoptimized = False
                 else:
-                    TESTME
+                    newextract = make_sure_not_resized([0]*len(extract)*factor)
+                    prestride = strides[i-1]
+                    for j in range(len(extract)):
+                        jf = j*factor
+                        st = extract[j]
+                        for k in range(factor):
+                            newextract[jf+k] = st + start
+                            st += prestride
+                    extract = newextract
                 slicelen = stride*slen
             else:
                 if unoptimized:
@@ -78,21 +93,71 @@
                             newextract[js + k] = st + index*stride
                             index += step
                 else:
-                    TESTME
+                    newextract = make_sure_not_resized([0]*len(extract)*factor*slen)
+                    prestride = strides[i-1]
+                    for j in range(len(extract)):
+                        st = extract[j]
+                        jfs = j*factor*slen
+                        for f in range(factor):
+                            fs = f*slen
+                            index = start
+                            for k in range(slen):
+                                newextract[jfs+fs+k] = st + index*stride
+                                index +=step
+                            st += prestride
+                    unoptimized = True
                 extract = newextract
                 slicelen = stride
         elif space.is_w(w_index, space.w_Ellipsis):
-            newshape.append(shape[i])
+            howmuch = len(shape) - lenslices - add
+            add += howmuch 
+            newshape.extend(shape[i:i+howmuch+1])
             unoptimized = False
+        elif space.is_w(w_index, space.w_None):
+            newshape[len(newshape)-2:len(newshape)-1] = [1]
+            add -= 1
+        elif isinstance(w_index, W_ListObject): #newaxis -- an array contains
+                                                #indices to extract
+            #raise OperationError(space.w_NotImplementedError,
+                    #space.wrap("newaxis are not implemented yet"))
+            ixshape = infer_shape(space, w_index)
+            axisarray = MultiDimIntArray(space, ixshape, 'i')
+            axisarray.load_iterable(w_index) # let an exception propagate, if one
+                                             # as in numpy
+            newshape.extend(ixshape)
+            indices = axisarray.storage
+            nind = len(indices)
+            del axisarray
+            stride = strides[i]
+            dim = shape[i]
+            if not unoptimized:
+                newextract = make_sure_not_resized([0] * len(extract) * factor)
+                prestride = strides[i-1]
+                for j in range(len(extract)):
+                    ex = extract[j]
+                    jf = j * factor
+                    for k in range(factor):
+                        newextract[jf + k] = ex
+                        ex += prestride
+            else:
+                newextract = make_sure_not_resized(extract[:])
+
+            extract = newextract
+            newextract = make_sure_not_resized([0]* len(extract)*nind)
+            for j in range(len(extract)):
+                jn = j*nind
+                for k in range(nind):
+                    newextract[jn + k] = extract[j] + indices[k]*stride
+
+            extract = newextract
+            slicelen = stride
+
         else: #Must be integer
-            try:
-                index = space.int_w(w_index)
-            except TypeError, e:
-                raise OperationError(space.w_IndexError,
-                                     space.wrap('Wrong index'))
+              #but we have checked.
+            index = space.int_w(w_index)
             if not (-shape[i] <= index < shape[i]):
                 raise OperationError(space.w_IndexError,
-                                     space.wrap('index out of range'))
+                                     space.wrap('index out of bounds'))
             if index < 0:
                 index += shape[i]
             stride = strides[i]
@@ -101,7 +166,7 @@
                 for j in range(len(extract)):
                     extract[j] += start
             else:
-                newextract = make_sure_not_resized([0]*len(extract)*factor)
+                newextract = make_sure_not_resized([0] * len(extract) * factor)
                 prestride = strides[i-1]
                 for j in range(len(extract)):
                     jf = j * factor
@@ -110,10 +175,11 @@
                         newextract[jf + k] = st + start
                         st += prestride
                 extract = newextract
+                unoptimized = True
             #No adding for shape
             slicelen = stride
 
-    newshape.extend(shape[i+1:]) #add rest of shape
+    newshape.extend(shape[i+add+1:]) #add rest of shape
     #all slices are absolutely eqi-length
     return newshape, extract, slicelen
 
@@ -135,8 +201,9 @@
 
     def create_math_operation(f):
         opname = f.__name__
-        def math_operation(self, w_x):
+        def common_math_operation(self, w_x, reversed):
             space = self.space
+            inverse = False
             try:
                 space.iter(w_x)
             except OperationError, e:
@@ -145,46 +212,73 @@
                 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
-                                                )
+                result = mdresult(result_t)(space, self.shape,
+                                            retrieve_dtype(space, result_t))
                 operation = result.__class__.client_scalar[opname]
             else:
-                op2 = array_fromseq(space, w_x)
+                op2 = array_fromseq(space, w_x, None)
                 if len(op2.shape) > len(self.shape):
                     self, op2 = op2, self
+                    inverse = True
                 lss = len(self.shape)
                 ls = len(op2.shape)
-                if not op2.shape == self.shape[lss-ls:lss]:
+                if not (list(op2.shape) == self.shape[lss-ls:lss] or
+                        list(op2.shape) == self.shape[:ls]):
                     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)
+                result = mdresult(result_t)(space, self.shape,
+                                            retrieve_dtype(space, result_t))
                 operation = result.__class__.client_fixedview[opname]
 
-            operation(result, self, op2)
+            operation(result, self, op2, inverse^reversed)
 
             w_result = space.wrap(result)
             return w_result
+
+        def math_operation(self, w_x):
+            return common_math_operation(self, w_x, False)
         math_operation.unwrap_spec = ['self', W_Root]
-        math_operation.__name__ = 'descr_'+opname
-        return math_operation
+        math_operation.__name__ = '%s_descr_%s'%(str(data_type), opname)
+
+        def reversed_math_operation(self, w_x):
+            return common_math_operation(self, w_x, True)
+        reversed_math_operation.unwrap_spec = ['self', W_Root]
+        reversed_math_operation.__name__ = '%s_descr_r%s'%(str(data_type), opname)
+
+        return math_operation, reversed_math_operation
 
     def create_client_math_operation(f):
-        def scalar_operation(self, source, x):
+        def scalar_operation(self, source, x, inversed):
             for i in range(len(source.storage)):
-                self.storage[i] = data_type(f(source.storage[i], x))
+                y = source.storage[i]
+                self.storage[i] = data_type(f(x, y) if inversed else f(y, x))
 
-        def fixedview_operation(self, source1, source2):
+        def fixedview_operation(self, source1, source2, inversed):
             #Here len(s1.storage)>=len(s2.storage)
+            ls1 = len(source1.storage)
+            ls2 = len(source2.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]))
+            if list(source2.shape) == source1.shape[ls1 - ls2:ls1]:
+                for i in range(ll):
+                    il = i*l2
+                    for j in range(l2):
+                        idx = il + j
+                        a = source1.storage[idx]
+                        b = source2.storage[j]
+                        self.storage[idx] = data_type(f(b, a) if inversed
+                                                 else f(a, b))
+            else:
+                for i in range(l2):
+                    il = i*ll
+                    for j in range(ll):
+                        idx = il + j
+                        a = source1.storage[idx]
+                        b = source2.storage[i]
+                        self.storage[idx] = data_type(f(b, a) if inversed
+                                                 else f(a, b))
 
         return scalar_operation, fixedview_operation
 
@@ -209,10 +303,10 @@
                                             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)
+        descr_mul, descr_rmul = create_math_operation(mul)
+        descr_div, descr_rdiv = create_math_operation(div)
+        descr_add, descr_radd = create_math_operation(add)
+        descr_sub, descr_rsub = create_math_operation(sub)
 
         def load_iterable(self, w_xs):
             self._internal_load(w_xs, self.shape, [])
@@ -221,7 +315,8 @@
             space = self.space
             length = shape[0]
             shapemismatch = OperationError(space.w_ValueError,
-                                           space.wrap('shape mismatch'))
+                                           space.wrap('setting an array element'
+                                                      'with a sequence'))
             try:
                 xs = space.fixedview(w_xs, length)
             except UnpackValueError:
@@ -261,13 +356,8 @@
             except OperationError, e:
                 if not e.match(space, space.w_TypeError):
                     raise
-
-            try:
-                space.iter(w_index)
-            except OperationError, e:
-                if not e.match(space, space.w_TypeError):
-                    raise
-                w_index = space.newlist([w_index])
+            if not isinstance(w_index, W_TupleObject):
+                w_index = space.newtuple([w_index])
             validate_index(self, space, w_index)
             try:
                 indexes = self._unpack_indexes(space, w_index)
@@ -290,15 +380,10 @@
 
         def descr_setitem(self, w_index, w_value):
             space = self.space
+            if not isinstance(w_index, W_TupleObject):
+                w_index = space.newtuple([w_index])
             validate_index(self, space, w_index)
             try:
-                space.iter(w_index)
-            except OperationError, e:
-                if not (e.match(space, space.w_IndexError) or
-                        e.match(space, space.w_TypeError)):
-                    raise
-                w_index = space.newlist([w_index])
-            try:
                 indexes = self._unpack_indexes(space, w_index)
             except OperationError, e:
                 if not (e.match(space, space.w_IndexError) or
@@ -317,29 +402,50 @@
                         self.storage[start:start + lslice] = [value] * lslice
                     return
                 arr = array_fromseq(space, w_value, None)
+                larr = len(arr.storage)
                 ls = len(arr.shape)
                 lss = len(shape)
-                if not (ls <= lss and list(arr.shape) == shape[lss-ls:lss]):
-                    raise OperationError(space.w_ValueError, #FIXME: throws when it shouldn't
-                                         space.wrap('array dimensions '
-                                         'are not compatible for copy'))
-                #we may exit earlier, but we are true purists and wonna check
-                if len(regions) == 0: return
-                l = len(arr.storage)
-                if lslice > l: #long slice
-                    xxx
-                    iters = lslice // l
-                    assert lslice == l * iters
-                    for start in regions:
-                        for i in range(iters):
-                            self.storage[start:start + l] = arr.storage
-                            start += l
-                else:
+                noncompat = OperationError(space.w_ValueError, #FIXME: throws when it shouldn't
+                                     space.wrap('array dimensions '
+                                     'are not compatible for copy'))
+                if ls > lss:
+                    raise noncompat
+                if list(arr.shape) == shape[lss-ls:lss]:
+                    if len(regions) == 0: return
                     i = 0
-                    for start in regions:
-                        self.storage[start:start + l] = arr.storage[i:i + lslice]
-                        if i > l:
-                            i = i-l
+                    if lslice > larr:
+                        for start in regions:
+                            for j in range(0, lslice, larr):
+                                self.storage[start:start + larr] = arr.storage[:]
+                                start += larr
+                    else:
+                        for start in regions:
+                            self.storage[start:start + lslice] =\
+                                    arr.storage[i:i + lslice]
+                            i += lslice
+                            if i > larr:
+                                i -= larr
+                elif list(arr.shape) == shape[:ls]:
+                    if len(regions) == 0: return
+                    if len(regions) < larr:
+                        factor = larr // len(regions)
+                        slen = lslice // factor
+                        for j in range(len(regions)):
+                            start = regions[j]
+                            jf = j*factor
+                            for k in range(factor):
+                                self.storage[start:start + slen] = \
+                                        make_sure_not_resized(
+                                                [arr.storage[jf + k]] * slen)
+                                start += slen
+                    else:
+                        i = 0
+                        for item in arr.storage:
+                            for start in regions[i:i+larr]:
+                                self.storage[start:start + lslice] = [item] * lslice
+                            i += larr
+                else:
+                    raise noncompat
             else:
                 pos = compute_pos(space, indexes, self.shape)
                 self.storage[pos] = coerce(space, w_value)
@@ -362,7 +468,19 @@
                     __len__ = interp2app(MultiDimArray.descr_len),
                     __getitem__ = interp2app(MultiDimArray.descr_getitem),
                     __setitem__ = interp2app(MultiDimArray.descr_setitem),
+
+                    __add__ = interp2app(MultiDimArray.descr_add),
+                    __sub__ = interp2app(MultiDimArray.descr_sub),
+                    __mul__ = interp2app(MultiDimArray.descr_mul),
+                    __div__ = interp2app(MultiDimArray.descr_div),
+
+                    __radd__ = interp2app(MultiDimArray.descr_radd),
+                    __rsub__ = interp2app(MultiDimArray.descr_rsub),
+                    __rmul__ = interp2app(MultiDimArray.descr_rmul),
+                    __rdiv__ = interp2app(MultiDimArray.descr_rdiv),
+
                     __str__ = interp2app(MultiDimArray.descr_str),
+
                     dtype = GetSetProperty(descr_dtype, cls = MultiDimArray),
                     shape = GetSetProperty(descr_shape, cls = MultiDimArray),
                    )

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	Thu Mar 11 11:13:27 2010
@@ -5,6 +5,7 @@
 from pypy.rlib.debug import make_sure_not_resized
 
 from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.tupleobject import W_TupleObject
 
 from pypy.module.micronumpy.array import BaseNumArray
 from pypy.module.micronumpy.array import base_typedef
@@ -60,18 +61,21 @@
                         )
 
     def create_client_math_operation(f):
-        def scalar_operation(self, source, x):
+        def scalar_operation(self, source, x, inverse):
             for i in range(len(source.storage)):
-                self.storage[i] = f(source.storage[i], x)
+                y = source.storage[i]
+                self.storage[i] = f(x, y) if inverse else f(y, x)
 
-        def fixedview_operation(self, a, b):
+        def fixedview_operation(self, source1, source2, inverse):
             for i in range(self.len()):
-                self.storage[i] = f(a.storage[i], b.storage[i])
+                a = source1.storage[i]
+                b = source2.storage[i]
+                self.storage[i] = f(b, a) if inverse else f(a, b)
         return scalar_operation, fixedview_operation
 
     def create_math_operation(f):
         opname = f.__name__
-        def math_operation(self, w_x):
+        def common_math_operation(self, w_x, reversed):
             space = self.space
             try:
                 space.iter(w_x)
@@ -81,10 +85,9 @@
                 result_t = result_mapping(space,
                                           (space.type(w_x), self.dtype))
                 x = coerce(space, w_x)
-                result = sdresult(result_t)(space,
-                                            self.len(), retrieve_dtype(space, result_t)
-                                           )
-                client_scalar[opname](result, self, x)
+                result = sdresult(result_t)(space, self.len(),
+                                            retrieve_dtype(space, result_t))
+                operation = result.__class__.client_scalar[opname]
             else:
                 operand_length = space.int_w(space.len(w_x))
                 if operand_length != self.len():
@@ -93,33 +96,31 @@
                                        " broadcast to the same shape"))
                 dtype_w = retrieve_dtype(space, iterable_type(space, w_x))
                 result_t = result_mapping(space, (dtype_w, self.dtype))
-                xs = sdresult(dtype_w.code)(space, operand_length, dtype_w)
+                xs = sdresult(result_t)(space, operand_length, 
+                                        retrieve_dtype(space, result_t))
                 xs.load_iterable(w_x)
-                result = sdresult(result_t)(
-                                            space, self.len(), retrieve_dtype(space, result_t)
-                                           )
-                client_fixedview[opname](result, self, xs)
+                result = sdresult(result_t)(space, self.len(),
+                                            retrieve_dtype(space, result_t))
+                x = xs
+                operation = result.__class__.client_fixedview[opname]
+
+            operation(result, self, x, reversed)
 
             return space.wrap(result)
+
+        def math_operation(self, w_x):
+            return common_math_operation(self, w_x, False)
         math_operation.unwrap_spec = ['self', W_Root]
         math_operation.__name__ = "%s_descr_%s" % (str(data_type), opname)
-        return math_operation
 
-    client_scalar = {}
-    client_fixedview = {}
+        def reversed_math_operation(self, w_x):
+            return common_math_operation(self, w_x, True)
+        reversed_math_operation.unwrap_spec = ['self', W_Root]
+        reversed_math_operation.__name__ = "%s_descr_r%s" % (str(data_type), opname)
+
+        return math_operation, reversed_math_operation
+
 
-    mul = mul_operation()
-    client_scalar['mul'], client_fixedview['mul'] = \
-                                        create_client_math_operation(mul)
-    div = div_operation()
-    client_scalar['div'], client_fixedview['div'] = \
-                                        create_client_math_operation(div)
-    add = add_operation()
-    client_scalar['add'], client_fixedview['add'] = \
-                                        create_client_math_operation(add)
-    sub = sub_operation()
-    client_scalar['sub'], client_fixedview['sub'] = \
-                                        create_client_math_operation(sub)
 
     class NumArray(BaseSingleDimArray):
         def __init__(self, space, length, dtype):
@@ -130,10 +131,28 @@
             self.dtype = dtype
             make_sure_not_resized(self.storage)
 
-        descr_mul = create_math_operation(mul)
-        descr_div = create_math_operation(div)
-        descr_add = create_math_operation(add)
-        descr_sub = create_math_operation(sub)
+        # Since we can't pass dtype to client_*,
+        # we must always use ones for *client* dtype, e.g. bound to his class.
+
+        client_scalar = {}
+        client_fixedview = {}
+
+        mul = mul_operation()
+        client_scalar['mul'], client_fixedview['mul'] = \
+                                            create_client_math_operation(mul)
+        div = div_operation()
+        client_scalar['div'], client_fixedview['div'] = \
+                                            create_client_math_operation(div)
+        add = add_operation()
+        client_scalar['add'], client_fixedview['add'] = \
+                                            create_client_math_operation(add)
+        sub = sub_operation()
+        client_scalar['sub'], client_fixedview['sub'] = \
+                                            create_client_math_operation(sub)
+        descr_mul, descr_rmul = create_math_operation(mul)
+        descr_div, descr_rdiv = create_math_operation(div)
+        descr_add, descr_radd = create_math_operation(add)
+        descr_sub, descr_rsub = create_math_operation(sub)
 
         def load_iterable(self, w_values):
             space = self.space
@@ -168,10 +187,20 @@
                         res.storage[i] = self.storage[start]
                         start += step
                 return space.wrap(res)
+            elif space.is_w(w_index, space.w_Ellipsis):
+                res = NumArray(space, self.shape[0], self.dtype)
+                res.storage[:] = self.storage
+                return space.wrap(res)
             else:
                 try:
                     index = space.int_w(w_index)
-                except TypeError, e:
+                except OperationError, e:
+                    if not e.match(space, space.w_TypeError):
+                        raise
+                    if isinstance(w_index, W_TupleObject):
+                        raise OperationError(space.w_NotImplementedError,
+                                space.wrap('multi-indexing single-dimension'
+                                           ' arrays are not implemented yet'))
                     raise OperationError(space.w_IndexError,
                                         space.wrap("index must either be an int or a sequence"))
             try:
@@ -201,8 +230,9 @@
                     return
                 operand_length = space.int_w(space.len(w_value))
                 if operand_length != slen:
-                    raise OperationError(space.w_TypeError,
-                                                space.wrap('shape mismatch'))
+                    raise OperationError(space.w_ValueError,
+                                        space.wrap('array dimensions are not'
+                                                   ' compatible for copy'))
                 value = space.fixedview(w_value)
                 if step == 1:
                     self.storage[start:stop] = \
@@ -267,10 +297,10 @@
                                __add__ = interp2app(NumArray.descr_add),
                                __sub__ = interp2app(NumArray.descr_sub),
 
-                               __rmul__ = interp2app(NumArray.descr_mul),
-                               __rdiv__ = interp2app(NumArray.descr_div),
-                               __radd__ = interp2app(NumArray.descr_add),
-                               __rsub__ = interp2app(NumArray.descr_sub),
+                               __rmul__ = interp2app(NumArray.descr_rmul),
+                               __rdiv__ = interp2app(NumArray.descr_rdiv),
+                               __radd__ = interp2app(NumArray.descr_radd),
+                               __rsub__ = interp2app(NumArray.descr_rsub),
 
                                __getitem__ = interp2app(NumArray.descr_getitem),
                                __setitem__ = interp2app(NumArray.descr_setitem),

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	Thu Mar 11 11:13:27 2010
@@ -71,8 +71,9 @@
             data.reverse()
             ar2 = array(data)
             for operator in (mul, div, add, sub):
-                for value in xrange(1, 16):
+                for value in xrange(1, 8): #less overkill
                     assert compare(operator(ar2, value), [operator(x, value) for x in data])
+                    assert compare(operator(value, ar2), [operator(value, x) for x in data])
                 assert compare(operator(ar, ar2), [operator(x, y) for (x, y) in zip(ar, ar2)])
 
     def test_operator_result_types(self):
@@ -144,25 +145,26 @@
         assert ar[0] == 0
         ar[1] = 3
         assert ar[1] == 3
-        raises((TypeError, ValueError), ar.__getitem__, 'xyz') #FIXME: why TypeError?
+        raises((IndexError, ValueError), ar.__getitem__, 'xyz') #FIXME: why TypeError?
         raises(IndexError, ar.__getitem__, 38)
         assert ar[-2] == 0
         assert ar[-7] == 3
         assert len(ar) == 8
 
+        #setitem
         ar[2:3] = [5]
         assert ar[2] == 5
         assert compare(ar[1:3], [3, 5])
         assert compare(ar[-6:-4], [5, 0])
         assert compare(ar[-6:-8:-1], [5, 3])
 
-        #setitem
         ar[3] = 2
         assert ar[3] == 2
         ar[5] = 3.5
         assert ar[5] == 3
         raises(ValueError, ar.__setitem__, 0, [99])
         raises(ValueError, ar.__setitem__, 0, 'f')
+        raises(ValueError, ar.__setitem__, slice(2, 3), [4, 5, 6])
 
     def test_minimum(self):
         from numpy import zeros, minimum
@@ -286,7 +288,12 @@
         assert s1[1]==1
         s2 = ar[1:3]
         assert s2[0][0] == 3
-        raises(ValueError, ar.__getitem__, 'what a strange index') #FIXME: throw this exception
+        assert compare(ar[1:3, 1:3][1], [7, 8])
+        assert compare(ar[0], ar[...][0])
+        assert ar[1][2] != ar[..., 1:3][1]
+        assert not compare(ar[...][0], ar[..., 0])
+        assert compare(ar[1:3, 0::2][1], [6, 8])
+        #raises(ValueError, ar.__getitem__, 'what a strange index') #still unfixed
         raises(IndexError, ar.__getitem__, (2, 2, 2)) #too many
         raises(IndexError, ar.__getitem__, 5)
         raises(IndexError, ar.__getitem__, (0, 6))
@@ -300,10 +307,72 @@
         #setitem
         ar[2] = 3
         assert ar[2, 0] == ar[2, 1] == ar[2, 2] == 3
-        ar[2:3, 0] = [7]
+        ar[2:3] = [7]
+        ar[2:3] = [5, 6, 7]
         ar[2] = [0, 1, 2]
         assert compare(ar[0], ar[2])
         assert compare(ar[..., 0], [0, 3, 0])
+        raises(ValueError, ar.__setitem__, slice(1, 3), [1, 2, 3, 4]) #too much elems
+        raises(ValueError, ar.__setitem__, slice(0, 3),
+                [[[1], [2], [3]], [[4], [5], [6]], [[7], [8], [9]]]) #too large shape
+        raises(ValueError, ar.__setitem__, slice(3, 4), [5, 6]) #attempting to check
+
+        ar2 = array(gen_array((3, 3))) 
+        ar2[...] = [0, 1, 2] #long slice
+        #check preference
+        assert ar2[0, 0] == ar2[1, 0] == 0
+        assert ar2[1, 2] == 2
+
+        ar3 = array(gen_array((3, 3, 3)))
+        ar3[1:3] = [[0, 1, 2], [3, 4, 5]]
+        assert compare(ar3[1, 2], [2, 2, 2])
+
+    def test_newaxis(self):
+        from numpy import array
+        gen_array = self.gen_array
+        compare = self.compare
+
+        ar = array(gen_array((3, 3)))
+
+        assert compare(ar[[1, 2], 0], ar[1:3, 0])
+        assert compare(ar[ [[1, 2], [0, 1]] ] [1, 0], ar[0])
+
+    def test_mdarray_operators(self):
+        from numpy import array
+        import operator
+        compare = self.compare
+
+        data1 = [[i*3+j+1 for j in range(3)] for i in range(3)]
+        data2 = [[i*3+j for j in range(3, 0, -1)] for i in range(3, 0, -1)]
+
+        ar1 = array(data1)
+        ar2 = array(data2)
+
+        const = 13
+
+        for f in (operator.add,
+                  operator.sub,
+                  operator.mul,
+                  operator.div):
+            res = f(ar1, ar2)
+            for i in range(3):
+                assert compare(res[i],
+                        [f(a, b) for a, b in zip(data1[i], data2[i])])
+            rres = f(ar2, ar1)
+            for i in range(3):
+                assert compare(rres[i],
+                        [f(b, a) for a, b in zip(data1[i], data2[i])])
+
+            cres = f(ar1, const)
+            for i in range(3):
+                assert compare(cres[i],
+                        [f(a, const) for a in data1[i]])
+
+            crres = f(const, ar2)
+            for i in range(3):
+                assert compare(crres[i],
+                        [f(const, b) for b in data2[i]])
+
 
 class AppTestDType(object):
     def setup_class(cls):



More information about the Pypy-commit mailing list