4747 "NumpyDeque" ,
4848]
4949
50+ _PRIORITY_FLAG = {"e" : "equal" , "l" : "left" , "lo" : "leftonly" , "r" : "right" , "ro" : "rightonly" }
5051_MAX_AUTO_BUFFER = 2 ** 11 # Maximum size increase of buffer allowed to include user requested buffer and auto-buffer
5152
5253
@@ -205,6 +206,16 @@ def dtype(self) -> np.dtype:
205206 """Get the data type of the elements stored in the deque."""
206207 return self ._data .dtype
207208
209+ @property
210+ def priority (self ):
211+ """Get the buffer priority of the deque."""
212+ return _PRIORITY_FLAG [self ._priority ]
213+
214+ @property
215+ def buffer_size (self ):
216+ """Get the maximum capacity of the buffer that contains the deque."""
217+ return self ._bcap
218+
208219 @classmethod
209220 def array (
210221 cls ,
@@ -254,7 +265,14 @@ def array(
254265 try :
255266 size = object .size
256267 except (AttributeError , TypeError ): # assume its a scalar
257- return cls (1 , object , dtype , buffer_padding , _force_buffer_size )
268+ if maxsize is not None :
269+ maxsize = max (1 , maxsize )
270+ return cls (maxsize , object , dtype , buffer_padding , _force_buffer_size )
271+
272+ if maxsize is None :
273+ maxsize = size
274+ else :
275+ maxsize = max (size , maxsize )
258276
259277 if dtype is None :
260278 try :
@@ -266,9 +284,9 @@ def array(
266284 dtype = np .array (object [0 ]).dtype
267285
268286 if buffer_padding is None and isinstance (object , NumpyDeque ):
269- buffer_padding = object ._bcap
287+ _force_buffer_size = object ._bcap
270288
271- ob = cls (size , None , dtype , buffer_padding , priority , _force_buffer_size )
289+ ob = cls (maxsize , None , dtype , buffer_padding , priority , _force_buffer_size = _force_buffer_size )
272290 ob ._i = ob ._s
273291 ob ._j = ob ._i + size
274292 ob ._data [ob ._i : ob ._j ] = object
@@ -293,9 +311,29 @@ def put(self, value):
293311 self ._j += 1
294312 self .deque = self ._data [self ._i : self ._j ]
295313
314+ def putleft (self , value ):
315+ """
316+ Add a value to the left end of the deque. If the len(deque) == maxsize,
317+ the right-most value (index=-1) is dropped.
318+
319+ Parameters:
320+ value: The value to be added to the deque.
321+ """
322+
323+ if self ._j - self ._i == self ._qcap :
324+ self ._j -= 1
325+
326+ self ._i -= 1
327+ if self ._i == - 1 :
328+ self ._shift_buffer ()
329+
330+ self ._data [self ._i ] = value
331+
332+ self .deque = self ._data [self ._i : self ._j ]
333+
296334 def putter (self , values ):
297335 """
298- Add multiple values to the deque in an optimized manner.
336+ Add multiple values to the right of the deque in an optimized manner.
299337 This is more efficient than repeatedly calling `put()` for each value.
300338 This is equivalent to:
301339 ```
@@ -317,7 +355,8 @@ def putter(self, values):
317355 return
318356
319357 if dim >= self ._qcap : # overwriting the entire deque move to buffer start
320- self ._i , self ._j = self ._s , self ._i + self ._qcap
358+ self ._i = self ._s
359+ self ._j = self ._i + self ._qcap
321360 self ._data [self ._i : self ._j ] = values [dim - self ._qcap :]
322361 self .deque = self ._data [self ._i : self ._j ]
323362 return
@@ -333,6 +372,62 @@ def putter(self, values):
333372 self ._j += dim
334373 self .deque = self ._data [self ._i : self ._j ]
335374
375+ def putterleft (self , values ):
376+ """
377+ Add multiple values to the left of the deque in an optimized manner.
378+ This is more efficient than repeatedly calling `putleft()` for each value.
379+ This is equivalent to:
380+ ```
381+ for v in values:
382+ self.putleft(v)
383+ ```
384+
385+ Parameters:
386+ values (iterable, array-like or scalar): The values to add to the deque.
387+ """
388+ try :
389+ dim = len (values )
390+ except TypeError : # iterator so need to manually add values
391+ try :
392+ for v in values :
393+ self .putleft (v )
394+ except TypeError : # scalar, so just call regular put
395+ self .putleft (values )
396+ return
397+
398+ if dim >= self ._qcap : # overwriting the entire deque move to buffer start
399+ self ._i = self ._s
400+ self ._j = self ._i + self ._qcap
401+ self ._data [self ._i : self ._j ] = values [::- 1 ][: self ._qcap ]
402+ self .deque = self ._data [self ._i : self ._j ]
403+ return
404+
405+ # if self._j - self._i == self._qcap:
406+ # self._j -= 1
407+
408+ # self._i -= 1
409+ # if self._i == -1:
410+ # self._shift_buffer()
411+
412+ # self._data[self._i] = value
413+
414+ # self.deque = self._data[self._i : self._j]
415+
416+ new_size = self ._j - self ._i + dim
417+ if new_size > self ._qcap :
418+ self ._j -= new_size - self ._qcap
419+
420+ if self ._i - dim < 0 : # shift buffer
421+ s = self ._s + dim
422+ j = s + self ._j - self ._i
423+ self ._data [s :j ] = self ._data [self ._i : self ._j ]
424+ self ._i , self ._j = self ._s , j
425+ else :
426+ self ._i -= dim
427+
428+ self ._data [self ._i : self ._i + dim ] = values [::- 1 ]
429+ self .deque = self ._data [self ._i : self ._j ]
430+
336431 def pop (self ):
337432 """
338433 Remove and return the value from the right end of the deque (index=-1).
@@ -393,7 +488,7 @@ def drop(self, index):
393488
394489 if "o" in self ._priority : # user specified priority for buffer
395490 priority = self ._priority
396- elif (self ._j - self . _s ) <= (self . _s - self ._i ): # index to drop is closer to _j
491+ elif (self ._j - index ) <= (index - self ._i ): # index to drop is closer to _j
397492 priority = "ro"
398493 else :
399494 priority = "lo"
@@ -434,7 +529,7 @@ def copy(self):
434529 Returns:
435530 NumpyDeque: A new instance of NumpyDeque that is a copy of the current deque.
436531 """
437- return NumpyDeque .array (self .deque , self .dtype , self ._bcap , self ._priority )
532+ return NumpyDeque .array (self .deque , None , self .dtype , self ._bcap , self ._priority )
438533
439534 def clear (self ):
440535 """
@@ -470,8 +565,18 @@ def _shift_buffer(self):
470565 """
471566 Internally shift the buffer to accommodate newly added elements and ensure efficient use of buffer space.
472567 """
473- j = self ._s + self ._j - self ._i
474- self ._data [self ._s : j ] = self ._data [self ._i : self ._j ]
568+ if self ._i == - 1 : # putleft shift
569+ s = self ._s + 1 # - self._i
570+ i = 0
571+ j = s + self ._j # - i
572+ elif self ._i >= 0 : # put and putter shift
573+ s = self ._s
574+ i = self ._i
575+ j = self ._s + self ._j - self ._i
576+ else :
577+ raise RuntimeError ("NumpyDeque._shift_buffer encountered an invalid _i index." )
578+
579+ self ._data [s :j ] = self ._data [i : self ._j ]
475580 self ._i , self ._j = self ._s , j
476581
477582 @staticmethod
0 commit comments