Author: Maciej Fijalkowski <[email protected]>
Branch: refactor-signature
Changeset: r50248:ee9bb45f0923
Date: 2011-12-07 16:33 +0200
http://bitbucket.org/pypy/pypy/changeset/ee9bb45f0923/
Log: in-progress
diff --git a/pypy/module/micronumpy/interp_iter.py
b/pypy/module/micronumpy/interp_iter.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_iter.py
@@ -0,0 +1,196 @@
+
+from pypy.rlib import jit
+from pypy.rlib.objectmodel import instantiate
+
+# Iterators for arrays
+# --------------------
+# all those iterators with the exception of BroadcastIterator iterate over the
+# entire array in C order (the last index changes the fastest). This will
+# yield all elements. Views iterate over indices and look towards strides and
+# backstrides to find the correct position. Notably the offset between
+# x[..., i + 1] and x[..., i] will be strides[-1]. Offset between
+# x[..., k + 1, 0] and x[..., k, i_max] will be backstrides[-2] etc.
+
+# BroadcastIterator works like that, but for indexes that don't change source
+# in the original array, strides[i] == backstrides[i] == 0
+
+class BaseIterator(object):
+ def next(self, shapelen):
+ raise NotImplementedError
+
+ def done(self):
+ raise NotImplementedError
+
+ def get_offset(self):
+ raise NotImplementedError
+
+class ArrayIterator(BaseIterator):
+ def __init__(self, size):
+ self.offset = 0
+ self.size = size
+
+ def next(self, shapelen):
+ arr = instantiate(ArrayIterator)
+ arr.size = self.size
+ arr.offset = self.offset + 1
+ return arr
+
+ def done(self):
+ return self.offset >= self.size
+
+ def get_offset(self):
+ return self.offset
+
+class OneDimIterator(BaseIterator):
+ def __init__(self, start, step, stop):
+ self.offset = start
+ self.step = step
+ self.size = stop * step + start
+
+ def next(self, shapelen):
+ arr = instantiate(OneDimIterator)
+ arr.size = self.size
+ arr.step = self.step
+ arr.offset = self.offset + self.step
+ return arr
+
+ def done(self):
+ return self.offset == self.size
+
+ def get_offset(self):
+ return self.offset
+
+class ViewIterator(BaseIterator):
+ def __init__(self, arr):
+ self.indices = [0] * len(arr.shape)
+ self.offset = arr.start
+ self.arr = arr
+ self._done = False
+
+ @jit.unroll_safe
+ def next(self, shapelen):
+ offset = self.offset
+ indices = [0] * shapelen
+ for i in range(shapelen):
+ indices[i] = self.indices[i]
+ done = False
+ for i in range(shapelen - 1, -1, -1):
+ if indices[i] < self.arr.shape[i] - 1:
+ indices[i] += 1
+ offset += self.arr.strides[i]
+ break
+ else:
+ indices[i] = 0
+ offset -= self.arr.backstrides[i]
+ else:
+ done = True
+ res = instantiate(ViewIterator)
+ res.offset = offset
+ res.indices = indices
+ res.arr = self.arr
+ res._done = done
+ return res
+
+ def done(self):
+ return self._done
+
+ def get_offset(self):
+ return self.offset
+
+class BroadcastIterator(BaseIterator):
+ '''Like a view iterator, but will repeatedly access values
+ for all iterations across a res_shape, folding the offset
+ using mod() arithmetic
+ '''
+ def __init__(self, arr, res_shape):
+ self.indices = [0] * len(res_shape)
+ self.offset = arr.start
+ #strides are 0 where original shape==1
+ self.strides = []
+ self.backstrides = []
+ for i in range(len(arr.shape)):
+ if arr.shape[i] == 1:
+ self.strides.append(0)
+ self.backstrides.append(0)
+ else:
+ self.strides.append(arr.strides[i])
+ self.backstrides.append(arr.backstrides[i])
+ self.res_shape = res_shape
+ self.strides = [0] * (len(res_shape) - len(arr.shape)) + self.strides
+ self.backstrides = [0] * (len(res_shape) - len(arr.shape)) +
self.backstrides
+ self._done = False
+
+ @jit.unroll_safe
+ def next(self, shapelen):
+ offset = self.offset
+ indices = [0] * shapelen
+ _done = False
+ for i in range(shapelen):
+ indices[i] = self.indices[i]
+ for i in range(shapelen - 1, -1, -1):
+ if indices[i] < self.res_shape[i] - 1:
+ indices[i] += 1
+ offset += self.strides[i]
+ break
+ else:
+ indices[i] = 0
+ offset -= self.backstrides[i]
+ else:
+ _done = True
+ res = instantiate(BroadcastIterator)
+ res.indices = indices
+ res.offset = offset
+ res._done = _done
+ res.strides = self.strides
+ res.backstrides = self.backstrides
+ res.res_shape = self.res_shape
+ return res
+
+ def done(self):
+ return self._done
+
+ def get_offset(self):
+ return self.offset
+
+class Call2Iterator(BaseIterator):
+ def __init__(self, left, right):
+ self.left = left
+ self.right = right
+
+ def next(self, shapelen):
+ return Call2Iterator(self.left.next(shapelen),
+ self.right.next(shapelen))
+
+ def done(self):
+ if isinstance(self.left, ConstantIterator):
+ return self.right.done()
+ return self.left.done()
+
+ def get_offset(self):
+ if isinstance(self.left, ConstantIterator):
+ return self.right.get_offset()
+ return self.left.get_offset()
+
+class Call1Iterator(BaseIterator):
+ def __init__(self, child):
+ self.child = child
+
+ def next(self, shapelen):
+ return Call1Iterator(self.child.next(shapelen))
+
+ def done(self):
+ return self.child.done()
+
+ def get_offset(self):
+ return self.child.get_offset()
+
+class ConstantIterator(BaseIterator):
+ def next(self, shapelen):
+ return self
+
+ def done(self):
+ return False
+
+ def get_offset(self):
+ return 0
+
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
@@ -198,199 +198,6 @@
n_old_elems_to_use *= old_shape[oldI]
return new_strides
-# Iterators for arrays
-# --------------------
-# all those iterators with the exception of BroadcastIterator iterate over the
-# entire array in C order (the last index changes the fastest). This will
-# yield all elements. Views iterate over indices and look towards strides and
-# backstrides to find the correct position. Notably the offset between
-# x[..., i + 1] and x[..., i] will be strides[-1]. Offset between
-# x[..., k + 1, 0] and x[..., k, i_max] will be backstrides[-2] etc.
-
-# BroadcastIterator works like that, but for indexes that don't change source
-# in the original array, strides[i] == backstrides[i] == 0
-
-class BaseIterator(object):
- def next(self, shapelen):
- raise NotImplementedError
-
- def done(self):
- raise NotImplementedError
-
- def get_offset(self):
- raise NotImplementedError
-
-class ArrayIterator(BaseIterator):
- def __init__(self, size):
- self.offset = 0
- self.size = size
-
- def next(self, shapelen):
- arr = instantiate(ArrayIterator)
- arr.size = self.size
- arr.offset = self.offset + 1
- return arr
-
- def done(self):
- return self.offset >= self.size
-
- def get_offset(self):
- return self.offset
-
-class OneDimIterator(BaseIterator):
- def __init__(self, start, step, stop):
- self.offset = start
- self.step = step
- self.size = stop * step + start
-
- def next(self, shapelen):
- arr = instantiate(OneDimIterator)
- arr.size = self.size
- arr.step = self.step
- arr.offset = self.offset + self.step
- return arr
-
- def done(self):
- return self.offset == self.size
-
- def get_offset(self):
- return self.offset
-
-class ViewIterator(BaseIterator):
- def __init__(self, arr):
- self.indices = [0] * len(arr.shape)
- self.offset = arr.start
- self.arr = arr
- self._done = False
-
- @jit.unroll_safe
- def next(self, shapelen):
- offset = self.offset
- indices = [0] * shapelen
- for i in range(shapelen):
- indices[i] = self.indices[i]
- done = False
- for i in range(shapelen - 1, -1, -1):
- if indices[i] < self.arr.shape[i] - 1:
- indices[i] += 1
- offset += self.arr.strides[i]
- break
- else:
- indices[i] = 0
- offset -= self.arr.backstrides[i]
- else:
- done = True
- res = instantiate(ViewIterator)
- res.offset = offset
- res.indices = indices
- res.arr = self.arr
- res._done = done
- return res
-
- def done(self):
- return self._done
-
- def get_offset(self):
- return self.offset
-
-class BroadcastIterator(BaseIterator):
- '''Like a view iterator, but will repeatedly access values
- for all iterations across a res_shape, folding the offset
- using mod() arithmetic
- '''
- def __init__(self, arr, res_shape):
- self.indices = [0] * len(res_shape)
- self.offset = arr.start
- #strides are 0 where original shape==1
- self.strides = []
- self.backstrides = []
- for i in range(len(arr.shape)):
- if arr.shape[i] == 1:
- self.strides.append(0)
- self.backstrides.append(0)
- else:
- self.strides.append(arr.strides[i])
- self.backstrides.append(arr.backstrides[i])
- self.res_shape = res_shape
- self.strides = [0] * (len(res_shape) - len(arr.shape)) + self.strides
- self.backstrides = [0] * (len(res_shape) - len(arr.shape)) +
self.backstrides
- self._done = False
-
- @jit.unroll_safe
- def next(self, shapelen):
- offset = self.offset
- indices = [0] * shapelen
- _done = False
- for i in range(shapelen):
- indices[i] = self.indices[i]
- for i in range(shapelen - 1, -1, -1):
- if indices[i] < self.res_shape[i] - 1:
- indices[i] += 1
- offset += self.strides[i]
- break
- else:
- indices[i] = 0
- offset -= self.backstrides[i]
- else:
- _done = True
- res = instantiate(BroadcastIterator)
- res.indices = indices
- res.offset = offset
- res._done = _done
- res.strides = self.strides
- res.backstrides = self.backstrides
- res.res_shape = self.res_shape
- return res
-
- def done(self):
- return self._done
-
- def get_offset(self):
- return self.offset
-
-class Call2Iterator(BaseIterator):
- def __init__(self, left, right):
- self.left = left
- self.right = right
-
- def next(self, shapelen):
- return Call2Iterator(self.left.next(shapelen),
- self.right.next(shapelen))
-
- def done(self):
- if isinstance(self.left, ConstantIterator):
- return self.right.done()
- return self.left.done()
-
- def get_offset(self):
- if isinstance(self.left, ConstantIterator):
- return self.right.get_offset()
- return self.left.get_offset()
-
-class Call1Iterator(BaseIterator):
- def __init__(self, child):
- self.child = child
-
- def next(self, shapelen):
- return Call1Iterator(self.child.next(shapelen))
-
- def done(self):
- return self.child.done()
-
- def get_offset(self):
- return self.child.get_offset()
-
-class ConstantIterator(BaseIterator):
- def next(self, shapelen):
- return self
-
- def done(self):
- return False
-
- def get_offset(self):
- return 0
-
-
class BaseArray(Wrappable):
_attrs_ = ["invalidates", "signature", "shape", "strides", "backstrides",
"start", 'order']
@@ -1327,6 +1134,7 @@
)
arr = W_NDimArray(size, shape[:], dtype=dtype, order=order)
shapelen = len(shape)
+ iters = arr.signature.create_iterator()
arr_iter = arr.start_iter(arr.shape)
for i in range(len(elems_w)):
w_elem = elems_w[i]
diff --git a/pypy/module/micronumpy/signature.py
b/pypy/module/micronumpy/signature.py
--- a/pypy/module/micronumpy/signature.py
+++ b/pypy/module/micronumpy/signature.py
@@ -1,5 +1,7 @@
from pypy.rlib.objectmodel import r_dict, compute_identity_hash, compute_hash
from pypy.rlib.rarithmetic import intmask
+from pypy.module.micronumpy.interp_iter import ViewIterator, ArrayIterator, \
+ BroadcastIterator, OneDimIterator
# def components_eq(lhs, rhs):
@@ -35,6 +37,9 @@
def hash(self):
return compute_hash(self)
+ def create_iter(self, array, cache):
+ raise NotImplementedError
+
class ViewSignature(Signature):
def __init__(self, child):
self.child = child
@@ -50,10 +55,16 @@
def debug_repr(self):
return 'Slice(%s)' % self.child.debug_repr()
+ def create_iter(self, array, cache):
+ xxxx
+
class ArraySignature(Signature):
def debug_repr(self):
return 'Array'
+ def create_iter(self, array, cache):
+ xxx
+
class ScalarSignature(Signature):
def debug_repr(self):
return 'Scalar'
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit