Author: Ronan Lamy <[email protected]>
Branch: indexing
Changeset: r78582:79db5bdf0df2
Date: 2015-07-17 16:03 +0100
http://bitbucket.org/pypy/pypy/changeset/79db5bdf0df2/
Log: Delay computation of slice length (required to implement ellipses)
diff --git a/pypy/module/micronumpy/concrete.py
b/pypy/module/micronumpy/concrete.py
--- a/pypy/module/micronumpy/concrete.py
+++ b/pypy/module/micronumpy/concrete.py
@@ -222,16 +222,16 @@
if space.isinstance_w(w_idx, space.w_slice):
if len(self.get_shape()) == 0:
raise oefmt(space.w_ValueError, "cannot slice a 0-d array")
- return [SliceChunk(w_idx, space, self.get_shape()[0])]
+ return [SliceChunk(w_idx)]
elif space.isinstance_w(w_idx, space.w_int):
- return [IntegerChunk(w_idx, space, self.get_shape()[0])]
+ return [IntegerChunk(w_idx)]
elif isinstance(w_idx, W_NDimArray) and w_idx.is_scalar():
w_idx = w_idx.get_scalar_value().item(space)
if not space.isinstance_w(w_idx, space.w_int) and \
not space.isinstance_w(w_idx, space.w_bool):
raise OperationError(space.w_IndexError, space.wrap(
"arrays used as indices must be of integer (or boolean)
type"))
- return [IntegerChunk(w_idx, space, self.get_shape()[0])]
+ return [IntegerChunk(w_idx)]
elif space.is_w(w_idx, space.w_None):
return [NewAxisChunk()]
result = []
@@ -249,10 +249,10 @@
elif space.is_w(w_item, space.w_None):
result.append(NewAxisChunk())
elif space.isinstance_w(w_item, space.w_slice):
- result.append(SliceChunk(w_item, space, self.get_shape()[i]))
+ result.append(SliceChunk(w_item))
i += 1
else:
- result.append(IntegerChunk(w_item, space, self.get_shape()[i]))
+ result.append(IntegerChunk(w_item))
i += 1
return result
diff --git a/pypy/module/micronumpy/strides.py
b/pypy/module/micronumpy/strides.py
--- a/pypy/module/micronumpy/strides.py
+++ b/pypy/module/micronumpy/strides.py
@@ -11,7 +11,7 @@
class Chunk(BaseChunk):
- axis_step = 1
+ input_dim = 1
def __init__(self, start, stop, step, lgt):
self.start = start
@@ -19,22 +19,45 @@
self.step = step
self.lgt = lgt
+ @property
+ def out_dim(self):
+ if self.step == 0:
+ return 0
+ else:
+ return 1
+
+ def compute(self, space, base_length, base_stride):
+ stride = base_stride * self.step
+ backstride = base_stride * max(0, self.lgt - 1) * self.step
+ return self.start, self.lgt, stride, backstride
+
def __repr__(self):
return 'Chunk(%d, %d, %d, %d)' % (self.start, self.stop, self.step,
self.lgt)
-class IntegerChunk(Chunk):
- def __init__(self, w_idx, space, base_length):
+class IntegerChunk(BaseChunk):
+ input_dim = 1
+ out_dim = 0
+ def __init__(self, w_idx):
self.w_idx = w_idx
- args = space.decode_index4(w_idx, base_length)
- Chunk.__init__(self, *args)
+ def compute(self, space, base_length, base_stride):
+ start, _, _, _ = space.decode_index4(self.w_idx, base_length)
+ return start, 0, 0, 0
-class SliceChunk(Chunk):
- def __init__(self, w_slice, space, base_length):
+
+class SliceChunk(BaseChunk):
+ input_dim = 1
+ out_dim = 1
+
+ def __init__(self, w_slice):
self.w_slice = w_slice
- args = space.decode_index4(w_slice, base_length)
- Chunk.__init__(self, *args)
+
+ def compute(self, space, base_length, base_stride):
+ start, stop, step, length = space.decode_index4(self.w_slice,
base_length)
+ stride = base_stride * step
+ backstride = base_stride * max(0, length - 1) * step
+ return start, length, stride, backstride
class NewAxisChunk(Chunk):
@@ -42,11 +65,15 @@
stop = 1
step = 1
lgt = 1
- axis_step = 0
+ input_dim = 0
+ out_dim = 1
def __init__(self):
pass
+ def compute(self, space, base_length, base_stride):
+ return 0, 1, 0, 0
+
class EllipsisChunk(BaseChunk):
def __init__(self):
pass
@@ -54,10 +81,9 @@
def new_view(space, w_arr, chunks):
arr = w_arr.implementation
- shape = _extend_shape(arr.shape, chunks)
- r = calculate_slice_strides(arr.shape, arr.start, arr.get_strides(),
+ r = calculate_slice_strides(space, arr.shape, arr.start, arr.get_strides(),
arr.get_backstrides(), chunks)
- _, start, strides, backstrides = r
+ shape, start, strides, backstrides = r
return W_NDimArray.new_slice(space, start, strides[:], backstrides[:],
shape[:], arr, w_arr)
@@ -66,7 +92,7 @@
shape = []
i = -1
for i, c in enumerate_chunks(chunks):
- if c.step != 0:
+ if c.out_dim > 0:
shape.append(c.lgt)
s = i + 1
assert s >= 0
@@ -93,35 +119,40 @@
result = []
i = -1
for chunk in chunks:
- i += chunk.axis_step
+ i += chunk.input_dim
result.append((i, chunk))
return result
[email protected]_inside_iff(lambda shape, start, strides, backstrides, chunks:
[email protected]_inside_iff(lambda space, shape, start, strides, backstrides, chunks:
jit.isconstant(len(chunks)))
-def calculate_slice_strides(shape, start, strides, backstrides, chunks):
+def calculate_slice_strides(space, shape, start, strides, backstrides, chunks):
size = 0
for chunk in chunks:
- if chunk.step != 0:
- size += 1
+ size += chunk.out_dim
rstrides = [0] * size
rbackstrides = [0] * size
rstart = start
rshape = [0] * size
- i = -1
- j = 0
- for i, chunk in enumerate_chunks(chunks):
+ i = -1 # index of the current dimension in the input array
+ j = 0 # index of the current dimension in the result view
+ for chunk in chunks:
+ i += chunk.input_dim
+ if isinstance(chunk, NewAxisChunk):
+ rshape[j] = 1
+ j += 1
+ continue
try:
s_i = strides[i]
except IndexError:
continue
- if chunk.step != 0:
- rstrides[j] = s_i * chunk.step
- rbackstrides[j] = s_i * max(0, chunk.lgt - 1) * chunk.step
- rshape[j] = chunk.lgt
- j += 1
- rstart += s_i * chunk.start
+ start, length, stride, backstride = chunk.compute(space, shape[i],
strides[i])
+ if chunk.out_dim == 1:
+ rstrides[j] = stride
+ rbackstrides[j] = backstride
+ rshape[j] = length
+ j += chunk.out_dim
+ rstart += s_i * start
# add a reminder
s = i + 1
assert s >= 0
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit