deques.nim 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2012 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Implementation of a `deque`:idx: (double-ended queue).
  10. ## The underlying implementation uses a ``seq``.
  11. ##
  12. ## None of the procs that get an individual value from the deque can be used
  13. ## on an empty deque.
  14. ## If compiled with `boundChecks` option, those procs will raise an `IndexError`
  15. ## on such access. This should not be relied upon, as `-d:release` will
  16. ## disable those checks and may return garbage or crash the program.
  17. ##
  18. ## As such, a check to see if the deque is empty is needed before any
  19. ## access, unless your program logic guarantees it indirectly.
  20. ##
  21. ## .. code-block:: Nim
  22. ## proc foo(a, b: Positive) = # assume random positive values for `a` and `b`
  23. ## var deq = initDeque[int]() # initializes the object
  24. ## for i in 1 ..< a: deq.addLast i # populates the deque
  25. ##
  26. ## if b < deq.len: # checking before indexed access
  27. ## echo "The element at index position ", b, " is ", deq[b]
  28. ##
  29. ## # The following two lines don't need any checking on access due to the
  30. ## # logic of the program, but that would not be the case if `a` could be 0.
  31. ## assert deq.peekFirst == 1
  32. ## assert deq.peekLast == a
  33. ##
  34. ## while deq.len > 0: # checking if the deque is empty
  35. ## echo deq.popLast()
  36. ##
  37. ## Note: For inter thread communication use
  38. ## a `Channel <channels.html>`_ instead.
  39. import math, typetraits
  40. type
  41. Deque*[T] = object
  42. ## A double-ended queue backed with a ringed seq buffer.
  43. data: seq[T]
  44. head, tail, count, mask: int
  45. proc initDeque*[T](initialSize: int = 4): Deque[T] =
  46. ## Create a new deque.
  47. ## Optionally, the initial capacity can be reserved via `initialSize` as a
  48. ## performance optimization. The length of a newly created deque will still
  49. ## be 0.
  50. ##
  51. ## `initialSize` needs to be a power of two. If you need to accept runtime
  52. ## values for this you could use the ``nextPowerOfTwo`` proc from the
  53. ## `math <math.html>`_ module.
  54. assert isPowerOfTwo(initialSize)
  55. result.mask = initialSize-1
  56. newSeq(result.data, initialSize)
  57. proc len*[T](deq: Deque[T]): int {.inline.} =
  58. ## Return the number of elements of `deq`.
  59. result = deq.count
  60. template emptyCheck(deq) =
  61. # Bounds check for the regular deque access.
  62. when compileOption("boundChecks"):
  63. if unlikely(deq.count < 1):
  64. raise newException(IndexError, "Empty deque.")
  65. template xBoundsCheck(deq, i) =
  66. # Bounds check for the array like accesses.
  67. when compileOption("boundChecks"): # d:release should disable this.
  68. if unlikely(i >= deq.count): # x < deq.low is taken care by the Natural parameter
  69. raise newException(IndexError,
  70. "Out of bounds: " & $i & " > " & $(deq.count - 1))
  71. proc `[]`*[T](deq: Deque[T], i: Natural) : T {.inline.} =
  72. ## Access the i-th element of `deq` by order from first to last.
  73. ## deq[0] is the first, deq[^1] is the last.
  74. xBoundsCheck(deq, i)
  75. return deq.data[(deq.head + i) and deq.mask]
  76. proc `[]`*[T](deq: var Deque[T], i: Natural): var T {.inline.} =
  77. ## Access the i-th element of `deq` and returns a mutable
  78. ## reference to it.
  79. xBoundsCheck(deq, i)
  80. return deq.data[(deq.head + i) and deq.mask]
  81. proc `[]=`* [T] (deq: var Deque[T], i: Natural, val : T) {.inline.} =
  82. ## Change the i-th element of `deq`.
  83. xBoundsCheck(deq, i)
  84. deq.data[(deq.head + i) and deq.mask] = val
  85. iterator items*[T](deq: Deque[T]): T =
  86. ## Yield every element of `deq`.
  87. var i = deq.head
  88. for c in 0 ..< deq.count:
  89. yield deq.data[i]
  90. i = (i + 1) and deq.mask
  91. iterator mitems*[T](deq: var Deque[T]): var T =
  92. ## Yield every element of `deq`.
  93. var i = deq.head
  94. for c in 0 ..< deq.count:
  95. yield deq.data[i]
  96. i = (i + 1) and deq.mask
  97. iterator pairs*[T](deq: Deque[T]): tuple[key: int, val: T] =
  98. ## Yield every (position, value) of `deq`.
  99. var i = deq.head
  100. for c in 0 ..< deq.count:
  101. yield (c, deq.data[i])
  102. i = (i + 1) and deq.mask
  103. proc contains*[T](deq: Deque[T], item: T): bool {.inline.} =
  104. ## Return true if `item` is in `deq` or false if not found. Usually used
  105. ## via the ``in`` operator. It is the equivalent of ``deq.find(item) >= 0``.
  106. ##
  107. ## .. code-block:: Nim
  108. ## if x in q:
  109. ## assert q.contains x
  110. for e in deq:
  111. if e == item: return true
  112. return false
  113. proc expandIfNeeded[T](deq: var Deque[T]) =
  114. var cap = deq.mask + 1
  115. if unlikely(deq.count >= cap):
  116. var n = newSeq[T](cap * 2)
  117. for i, x in pairs(deq): # don't use copyMem because the GC and because it's slower.
  118. shallowCopy(n[i], x)
  119. shallowCopy(deq.data, n)
  120. deq.mask = cap * 2 - 1
  121. deq.tail = deq.count
  122. deq.head = 0
  123. proc addFirst*[T](deq: var Deque[T], item: T) =
  124. ## Add an `item` to the beginning of the `deq`.
  125. expandIfNeeded(deq)
  126. inc deq.count
  127. deq.head = (deq.head - 1) and deq.mask
  128. deq.data[deq.head] = item
  129. proc addLast*[T](deq: var Deque[T], item: T) =
  130. ## Add an `item` to the end of the `deq`.
  131. expandIfNeeded(deq)
  132. inc deq.count
  133. deq.data[deq.tail] = item
  134. deq.tail = (deq.tail + 1) and deq.mask
  135. proc peekFirst*[T](deq: Deque[T]): T {.inline.}=
  136. ## Returns the first element of `deq`, but does not remove it from the deque.
  137. emptyCheck(deq)
  138. result = deq.data[deq.head]
  139. proc peekLast*[T](deq: Deque[T]): T {.inline.} =
  140. ## Returns the last element of `deq`, but does not remove it from the deque.
  141. emptyCheck(deq)
  142. result = deq.data[(deq.tail - 1) and deq.mask]
  143. template destroy(x: untyped) =
  144. reset(x)
  145. proc popFirst*[T](deq: var Deque[T]): T {.inline, discardable.} =
  146. ## Remove and returns the first element of the `deq`.
  147. emptyCheck(deq)
  148. dec deq.count
  149. result = deq.data[deq.head]
  150. destroy(deq.data[deq.head])
  151. deq.head = (deq.head + 1) and deq.mask
  152. proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} =
  153. ## Remove and returns the last element of the `deq`.
  154. emptyCheck(deq)
  155. dec deq.count
  156. deq.tail = (deq.tail - 1) and deq.mask
  157. result = deq.data[deq.tail]
  158. destroy(deq.data[deq.tail])
  159. proc clear*[T](deq: var Deque[T]) {.inline.} =
  160. ## Resets the deque so that it is empty.
  161. for el in mitems(deq): destroy(el)
  162. deq.count = 0
  163. deq.tail = deq.head
  164. proc shrink*[T](deq: var Deque[T], fromFirst = 0, fromLast = 0) =
  165. ## Remove `fromFirst` elements from the front of the deque and
  166. ## `fromLast` elements from the back. If the supplied number of
  167. ## elements exceeds the total number of elements in the deque,
  168. ## the deque will remain empty.
  169. ##
  170. ## Any user defined destructors
  171. if fromFirst + fromLast > deq.count:
  172. clear(deq)
  173. return
  174. for i in 0 ..< fromFirst:
  175. destroy(deq.data[deq.head])
  176. deq.head = (deq.head + 1) and deq.mask
  177. for i in 0 ..< fromLast:
  178. destroy(deq.data[deq.tail])
  179. deq.tail = (deq.tail - 1) and deq.mask
  180. dec deq.count, fromFirst + fromLast
  181. proc `$`*[T](deq: Deque[T]): string =
  182. ## Turn a deque into its string representation.
  183. result = "["
  184. for x in deq:
  185. if result.len > 1: result.add(", ")
  186. result.addQuoted(x)
  187. result.add("]")
  188. when isMainModule:
  189. var deq = initDeque[int](1)
  190. deq.addLast(4)
  191. deq.addFirst(9)
  192. deq.addFirst(123)
  193. var first = deq.popFirst()
  194. deq.addLast(56)
  195. assert(deq.peekLast() == 56)
  196. deq.addLast(6)
  197. assert(deq.peekLast() == 6)
  198. var second = deq.popFirst()
  199. deq.addLast(789)
  200. assert(deq.peekLast() == 789)
  201. assert first == 123
  202. assert second == 9
  203. assert($deq == "[4, 56, 6, 789]")
  204. assert deq[0] == deq.peekFirst and deq.peekFirst == 4
  205. #assert deq[^1] == deq.peekLast and deq.peekLast == 789
  206. deq[0] = 42
  207. deq[deq.len - 1] = 7
  208. assert 6 in deq and 789 notin deq
  209. assert deq.find(6) >= 0
  210. assert deq.find(789) < 0
  211. block:
  212. var d = initDeque[int](1)
  213. d.addLast 7
  214. d.addLast 8
  215. d.addLast 10
  216. d.addFirst 5
  217. d.addFirst 2
  218. d.addFirst 1
  219. d.addLast 20
  220. d.shrink(fromLast = 2)
  221. doAssert($d == "[1, 2, 5, 7, 8]")
  222. d.shrink(2, 1)
  223. doAssert($d == "[5, 7]")
  224. d.shrink(2, 2)
  225. doAssert d.len == 0
  226. for i in -2 .. 10:
  227. if i in deq:
  228. assert deq.contains(i) and deq.find(i) >= 0
  229. else:
  230. assert(not deq.contains(i) and deq.find(i) < 0)
  231. when compileOption("boundChecks"):
  232. try:
  233. echo deq[99]
  234. assert false
  235. except IndexError:
  236. discard
  237. try:
  238. assert deq.len == 4
  239. for i in 0 ..< 5: deq.popFirst()
  240. assert false
  241. except IndexError:
  242. discard
  243. # grabs some types of resize error.
  244. deq = initDeque[int]()
  245. for i in 1 .. 4: deq.addLast i
  246. deq.popFirst()
  247. deq.popLast()
  248. for i in 5 .. 8: deq.addFirst i
  249. assert $deq == "[8, 7, 6, 5, 2, 3]"
  250. # Similar to proc from the documentation example
  251. proc foo(a, b: Positive) = # assume random positive values for `a` and `b`.
  252. var deq = initDeque[int]()
  253. assert deq.len == 0
  254. for i in 1 .. a: deq.addLast i
  255. if b < deq.len: # checking before indexed access.
  256. assert deq[b] == b + 1
  257. # The following two lines don't need any checking on access due to the logic
  258. # of the program, but that would not be the case if `a` could be 0.
  259. assert deq.peekFirst == 1
  260. assert deq.peekLast == a
  261. while deq.len > 0: # checking if the deque is empty
  262. assert deq.popFirst() > 0
  263. #foo(0,0)
  264. foo(8,5)
  265. foo(10,9)
  266. foo(1,1)
  267. foo(2,1)
  268. foo(1,5)
  269. foo(3,2)