Skip to content

Commit 3a85376

Browse files
committed
Now passes setitem tests for negative steps
1 parent 9e0cc93 commit 3a85376

2 files changed

Lines changed: 18 additions & 13 deletions

File tree

src/blosc2/ndarray.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,11 +1588,11 @@ def get_fselection_numpy(self, key: list | np.ndarray) -> np.ndarray:
15881588
# loop over chunks coming from slices before and after array indices
15891589
for cprior_tuple in product(*cprior_slices):
15901590
out_prior_selection, prior_selection, loc_prior_selection = _get_selection(
1591-
cprior_tuple, prior_tuple, chunks[:begin], shape
1591+
cprior_tuple, prior_tuple, chunks[:begin]
15921592
)
15931593
for cpost_tuple in product(*cpost_slices):
15941594
out_post_selection, post_selection, loc_post_selection = _get_selection(
1595-
cpost_tuple, post_tuple, chunks[end:] if end is not None else [], shape
1595+
cpost_tuple, post_tuple, chunks[end:] if end is not None else []
15961596
)
15971597
locbegin, locend = _get_local_slice(
15981598
prior_selection, post_selection, (chunk_begin, chunk_end)
@@ -1826,7 +1826,7 @@ def updater(sel_idx):
18261826
return value[sel_idx]
18271827

18281828
for c in product(*intersecting_chunks):
1829-
sel_idx, _, sub_idx = _get_selection(c, _slice, chunks, shape, load_full=True)
1829+
sel_idx, _, sub_idx = _get_selection(c, _slice, chunks, load_full=True)
18301830
sel_idx = tuple(s for s, m in zip(sel_idx, mask, strict=True) if not m)
18311831
sub_idx = tuple(s if not m else k.start for s, m, k in zip(sub_idx, mask, key_, strict=True))
18321832
locstart, locstop = (
@@ -4767,7 +4767,7 @@ def slice_to_chunktuple(s, n):
47674767
return tuple(range(start // n, ceiling(stop, n)))
47684768

47694769

4770-
def _get_selection(ctuple, ptuple, chunks, shape, load_full=False):
4770+
def _get_selection(ctuple, ptuple, chunks, load_full=False):
47714771
# we assume that at least one element of chunk intersects with the slice
47724772
# (as a consequence of only looping over intersecting chunks)
47734773
# ptuple is global slice, ctuple is chunk coords (in units of chunks)
@@ -4800,7 +4800,7 @@ def _get_selection(ctuple, ptuple, chunks, shape, load_full=False):
48004800
),
48014801
)
48024802

4803-
# selection relative to coordinates of out (necessarily out_step = +-1)
4803+
# selection relative to coordinates of out (necessarily out_step = 1 as we work through out chunk-by-chunk of self)
48044804
# when added n + 1 elements
48054805
# ps.start = pt.start + step * (n+1) => n = (ps.start - pt.start - sign) // step
48064806
# hence, out_start = n + 1 or shape(out) - 1 - (n + 1) if step < 0
@@ -4811,25 +4811,29 @@ def _get_selection(ctuple, ptuple, chunks, shape, load_full=False):
48114811
for ps, pt in zip(pselection, ptuple, strict=True):
48124812
sign_ = pt.step // builtins.abs(pt.step)
48134813
n = (ps.start - pt.start - sign_) // pt.step
4814-
out_start = n + 1 if sign_ > 0 else shape[i] - (n + 1) - 1
4814+
out_start = n + 1
48154815
# ps.stop always positive except for case where get full array (it is then -1 since desire 0th element)
48164816
out_stop = None if ps.stop == -1 else (ps.stop - pt.start - sign_) // pt.step + 1
48174817
out_pselection += (
48184818
slice(
48194819
out_start,
48204820
out_stop,
4821-
sign_,
4821+
1,
48224822
),
48234823
)
48244824
i += 1
4825-
print(pselection, ptuple, out_pselection)
4825+
48264826
if load_full:
4827+
4828+
def my_checker_f(x): # handle case -1 to get full chunk
4829+
return x if x >= 0 else None
4830+
48274831
loc_selection = tuple(
4828-
slice(s.start - i * csize, s.stop - i * csize, s.step)
4829-
if s.step > 0
4830-
else slice(s.stop - i * csize + 1, s.start - i * csize + 1, -s.step)
4831-
for i, s, csize in zip(ctuple, pselection, chunks, strict=True)
4832-
) # local coords of full chunk (note not reversed for negative steps!)
4832+
slice(s.start - i * csize, my_checker_f(s.stop - i * csize), s.step)
4833+
for i, s, csize in zip(
4834+
ctuple, pselection, chunks, strict=True
4835+
) # if s.step < 0 then we match with out coords no problem
4836+
) # local coords of full chunk
48334837
else:
48344838
loc_selection = tuple(
48354839
slice(0, s.stop - s.start, s.step) if s.step > 0 else slice(s.start - s.stop, None, s.step)

tests/ndarray/test_setitem.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
([12, 13, 14, 15, 16], [5, 5, 5, 5, 5], [2, 2, 2, 2, 2], (slice(1, 3), ..., slice(3, 6)), np.float32),
1919
([12, 13, 14, 15, 16], [5, 5, 5, 5, 5], [2, 2, 2, 2, 2], (slice(1, 9, 2), ..., slice(3, 6)), np.float32),
2020
([12, 13], [5, 5], [2, 2], (slice(11, 2, -1), slice(6, 2, -1)), np.float32),
21+
([25, 13, 22], [5, 5, 3], [2, 2, 1], (slice(17, 2, -3), 0, slice(6, 2, -1)), np.float32),
2122
]
2223

2324

0 commit comments

Comments
 (0)