Author: Maciej Fijalkowski <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit