Author: Maciej Fijalkowski <fij...@gmail.com> Branch: Changeset: r44902:bb4fee3d2de9 Date: 2011-06-13 09:46 +0200 http://bitbucket.org/pypy/pypy/changeset/bb4fee3d2de9/
Log: merge default 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 @@ -46,7 +46,7 @@ def invalidated(self): for arr in self.invalidates: arr.force_if_needed() - self.invalidates = [] + del self.invalidates[:] def _binop_impl(function): signature = Signature() @@ -83,16 +83,23 @@ def descr_len(self, space): return self.get_concrete().descr_len(space) - @unwrap_spec(item=int) - def descr_getitem(self, space, item): - return self.get_concrete().descr_getitem(space, item) + def descr_getitem(self, space, w_idx): + # TODO: indexation by tuples + start, stop, step, slice_length = space.decode_index4(w_idx, self.find_size()) + if step == 0: + # Single index + return space.wrap(self.get_concrete().getitem(start)) + else: + # Slice + res = SingleDimSlice(start, stop, step, slice_length, self, self.signature.transition(SingleDimSlice.static_signature)) + return space.wrap(res) + @unwrap_spec(item=int, value=float) def descr_setitem(self, space, item, value): self.invalidated() return self.get_concrete().descr_setitem(space, item, value) - class FloatWrapper(BaseArray): """ Intermediate class representing a float literal. @@ -119,6 +126,10 @@ self.forced_result = None self.signature = signature + def _del_sources(self): + # Function for deleting references to source arrays, to allow garbage-collecting them + raise NotImplementedError + def compute(self): i = 0 signature = self.signature @@ -135,6 +146,7 @@ def force_if_needed(self): if self.forced_result is None: self.forced_result = self.compute() + self._del_sources() def get_concrete(self): self.force_if_needed() @@ -145,6 +157,13 @@ return self.forced_result.eval(i) return self._eval(i) + def find_size(self): + if self.forced_result is not None: + # The result has been computed and sources may be unavailable + return self.forced_result.find_size() + return self._find_size() + + class Call1(VirtualArray): _immutable_fields_ = ["function", "values"] @@ -153,7 +172,10 @@ self.function = function self.values = values - def find_size(self): + def _del_sources(self): + self.values = None + + def _find_size(self): return self.values.find_size() def _eval(self, i): @@ -170,7 +192,11 @@ self.left = left self.right = right - def find_size(self): + def _del_sources(self): + self.left = None + self.right = None + + def _find_size(self): try: return self.left.find_size() except ValueError: @@ -181,6 +207,53 @@ lhs, rhs = self.left.eval(i), self.right.eval(i) return self.function(lhs, rhs) +class ViewArray(BaseArray): + """ + Class for representing views of arrays, they will reflect changes of parrent arrays. Example: slices + """ + _immutable_fields_ = ["parent"] + def __init__(self, parent, signature): + BaseArray.__init__(self) + self.signature = signature + self.parent = parent + self.invalidates = parent.invalidates + + def get_concrete(self): + return self # in fact, ViewArray never gets "concrete" as it never stores data. This implementation is needed for BaseArray getitem/setitem to work, can be refactored. + + def eval(self, i): + return self.parent.eval(self.calc_index(i)) + + def getitem(self, item): + return self.parent.getitem(self.calc_index(item)) + + @unwrap_spec(item=int, value=float) + def descr_setitem(self, space, item, value): + return self.parent.descr_setitem(space, self.calc_index(item), value) + + def descr_len(self, space): + return space.wrap(self.find_size()) + + def calc_index(self, item): + raise NotImplementedError + +class SingleDimSlice(ViewArray): + _immutable_fields_ = ["start", "stop", "step", "size"] + static_signature = Signature() + + def __init__(self, start, stop, step, slice_length, parent, signature): + ViewArray.__init__(self, parent, signature) + self.start = start + self.stop = stop + self.step = step + self.size = slice_length + + def find_size(self): + return self.size + + def calc_index(self, item): + return (self.start + item * self.step) + class SingleDimArray(BaseArray): signature = Signature() @@ -215,10 +288,8 @@ def descr_len(self, space): return space.wrap(self.size) - @unwrap_spec(item=int) - def descr_getitem(self, space, item): - item = self.getindex(space, item) - return space.wrap(self.storage[item]) + def getitem(self, item): + return self.storage[item] @unwrap_spec(item=int, value=float) def descr_setitem(self, space, item, value): @@ -254,4 +325,4 @@ __sub__ = interp2app(BaseArray.descr_sub), __mul__ = interp2app(BaseArray.descr_mul), __div__ = interp2app(BaseArray.descr_div), -) \ No newline at end of file +) diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py --- a/pypy/module/micronumpy/test/test_base.py +++ b/pypy/module/micronumpy/test/test_base.py @@ -16,4 +16,4 @@ v3 = ar.descr_add(space, FloatWrapper(1.0)) assert v2.signature is v3.signature v4 = ar.descr_add(space, ar) - assert v1.signature is v4.signature \ No newline at end of file + assert v1.signature is v4.signature diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -149,3 +149,45 @@ c = b + b b[1] = 5 assert c[1] == 4 + + def test_getslice(self): + from numpy import array + a = array(range(5)) + s = a[1:5] + assert len(s) == 4 + for i in range(4): + assert s[i] == a[i+1] + + def test_getslice_step(self): + from numpy import array + a = array(range(10)) + s = a[1:9:2] + assert len(s) == 4 + for i in range(4): + assert s[i] == a[2*i+1] + + def test_slice_update(self): + from numpy import array + a = array(range(5)) + s = a[0:3] + s[1] = 10 + assert a[1] == 10 + a[2] = 20 + assert s[2] == 20 + + + def test_slice_invaidate(self): + # check that slice shares invalidation list with + from numpy import array + a = array(range(5)) + s = a[0:2] + b = array([10,11]) + c = s + b + a[0]=100 + assert c[0] == 10 + assert c[1] == 12 + d = s + b + a[1]=101 + assert d[0] == 110 + assert d[1] == 12 + diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py --- a/pypy/module/micronumpy/test/test_zjit.py +++ b/pypy/module/micronumpy/test/test_zjit.py @@ -1,8 +1,7 @@ from pypy.jit.metainterp.test.support import LLJitMixin from pypy.rpython.test.test_llinterp import interpret - from pypy.module.micronumpy.interp_numarray import (SingleDimArray, Signature, - FloatWrapper, Call1, Call2, add, mul) + FloatWrapper, Call1, Call2, SingleDimSlice, add, mul) from pypy.module.micronumpy.interp_ufuncs import negative from pypy.module.micronumpy.compile import numpy_compile @@ -95,6 +94,40 @@ # This is 3, not 2 because there is a bridge for the exit. self.check_loop_count(3) + def test_slice(self): + space = self.space + + def f(i): + step = 3 + ar = SingleDimArray(step*i) + s = SingleDimSlice(0, step*i, step, i, ar, ar.signature.transition(SingleDimSlice.static_signature)) + v = Call2(add, s, s, Signature()) + return v.get_concrete().storage[3] + + result = self.meta_interp(f, [5], listops=True, backendopt=True) + self.check_loops({'int_mul': 1, 'getarrayitem_raw': 2, 'float_add': 1, + 'setarrayitem_raw': 1, 'int_add': 1, + 'int_lt': 1, 'guard_true': 1, 'jump': 1}) + assert result == f(5) + + def test_slice2(self): + space = self.space + + def f(i): + step1 = 2 + step2 = 3 + ar = SingleDimArray(step2*i) + s1 = SingleDimSlice(0, step1*i, step1, i, ar, ar.signature.transition(SingleDimSlice.static_signature)) + s2 = SingleDimSlice(0, step2*i, step2, i, ar, ar.signature.transition(SingleDimSlice.static_signature)) + v = Call2(add, s1, s2, Signature()) + return v.get_concrete().storage[3] + + result = self.meta_interp(f, [5], listops=True, backendopt=True) + self.check_loops({'int_mul': 2, 'getarrayitem_raw': 2, 'float_add': 1, + 'setarrayitem_raw': 1, 'int_add': 1, + 'int_lt': 1, 'guard_true': 1, 'jump': 1}) + assert result == f(5) + class TestTranslation(object): def test_compile(self): x = numpy_compile('aa+f*f/a-', 10) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit