From b448fa4002bf3b7b3df3a1d4194fffcf3d9af79f Mon Sep 17 00:00:00 2001 From: magla Date: Mon, 15 Mar 2021 15:16:04 +0100 Subject: [PATCH 1/2] Maintain copy of unwrapped array. Do not recompute until the ringbuffer has been modified. --- numpy_ringbuffer/__init__.py | 25 +++++++++++++++++++------ tests.py | 15 +++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/numpy_ringbuffer/__init__.py b/numpy_ringbuffer/__init__.py index 719a29b..c8e2594 100644 --- a/numpy_ringbuffer/__init__.py +++ b/numpy_ringbuffer/__init__.py @@ -19,6 +19,8 @@ def __init__(self, capacity, dtype=float, allow_overwrite=True): If false, throw an IndexError when trying to append to an already full buffer """ + self._modified = False + self._unwrapped = None self._arr = np.empty(capacity, dtype) self._left_index = 0 self._right_index = 0 @@ -27,10 +29,13 @@ def __init__(self, capacity, dtype=float, allow_overwrite=True): def _unwrap(self): """ Copy the data from this buffer into unwrapped form """ - return np.concatenate(( - self._arr[self._left_index:min(self._right_index, self._capacity)], - self._arr[:max(self._right_index - self._capacity, 0)] - )) + if self._modified or self._unwrapped is None: + self._unwrapped = np.concatenate(( + self._arr[self._left_index:min(self._right_index, self._capacity)], + self._arr[:max(self._right_index - self._capacity, 0)] + )) + + return self._unwrapped def _fix_indices(self): """ @@ -39,9 +44,11 @@ def _fix_indices(self): if self._left_index >= self._capacity: self._left_index -= self._capacity self._right_index -= self._capacity + self._modified = True elif self._left_index < 0: self._left_index += self._capacity self._right_index += self._capacity + self._modified = True @property def is_full(self): @@ -60,7 +67,6 @@ def dtype(self): def shape(self): return (len(self),) + self._arr.shape[1:] - # these mirror methods from deque @property def maxlen(self): @@ -78,6 +84,7 @@ def append(self, value): self._arr[self._right_index % self._capacity] = value self._right_index += 1 self._fix_indices() + self._modified = True def appendleft(self, value): if self.is_full: @@ -91,12 +98,14 @@ def appendleft(self, value): self._left_index -= 1 self._fix_indices() self._arr[self._left_index] = value + self._modified = True def pop(self): if len(self) == 0: raise IndexError("pop from an empty RingBuffer") self._right_index -= 1 self._fix_indices() + self._modified = True res = self._arr[self._right_index % self._capacity] return res @@ -106,6 +115,7 @@ def popleft(self): res = self._arr[self._left_index] self._left_index += 1 self._fix_indices() + self._modified = True return res def extend(self, values): @@ -120,6 +130,7 @@ def extend(self, values): self._arr[...] = values[-self._capacity:] self._right_index = self._capacity self._left_index = 0 + self._modified = True return ri = self._right_index % self._capacity @@ -131,6 +142,7 @@ def extend(self, values): self._left_index = max(self._left_index, self._right_index - self._capacity) self._fix_indices() + self._modified = True def extendleft(self, values): lv = len(values) @@ -144,6 +156,7 @@ def extendleft(self, values): self._arr[...] = values[:self._capacity] self._right_index = self._capacity self._left_index = 0 + self._modified = True return self._left_index -= lv @@ -155,7 +168,7 @@ def extendleft(self, values): self._arr[sl2] = values[sl1.stop - sl1.start:] self._right_index = min(self._right_index, self._left_index + self._capacity) - + self._modified = True # implement Sequence methods def __len__(self): diff --git a/tests.py b/tests.py index feeb9ae..4832275 100644 --- a/tests.py +++ b/tests.py @@ -46,14 +46,17 @@ def test_append(self): self.assertEqual(r[-1], 6) def test_getitem(self): - r = RingBuffer(5) - r.extend([1, 2, 3]) - r.extendleft([4, 5]) - expected = np.array([4, 5, 1, 2, 3]) + r = RingBuffer(8) + r.extend([1, 2, 3, 4, 5]) + r.extendleft([6, 7, 8]) + expected = np.array([6, 7, 8, 1, 2, 3, 4, 5]) np.testing.assert_equal(r, expected) - for i in range(r.maxlen): - self.assertEqual(expected[i], r[i]) + for i in range(r.maxlen-1): + try: + self.assertEqual(expected[i:i+1], r[i:i+1]) + except: + self.assertEqual(expected[i:i+1], r[i:i+1]) ii = [0, 4, 3, 1, 2] np.testing.assert_equal(r[ii], expected[ii]) From ea86254a05655ea4a3e80a852173ed18b9080878 Mon Sep 17 00:00:00 2001 From: magla Date: Mon, 15 Mar 2021 15:22:17 +0100 Subject: [PATCH 2/2] Small bug fix --- numpy_ringbuffer/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/numpy_ringbuffer/__init__.py b/numpy_ringbuffer/__init__.py index c8e2594..d97248a 100644 --- a/numpy_ringbuffer/__init__.py +++ b/numpy_ringbuffer/__init__.py @@ -34,6 +34,7 @@ def _unwrap(self): self._arr[self._left_index:min(self._right_index, self._capacity)], self._arr[:max(self._right_index - self._capacity, 0)] )) + self._modified = False return self._unwrapped