setimpl.nim 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2019 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # An `include` file for the different hash set implementations.
  10. template maxHash(t): untyped = high(t.data)
  11. template dataLen(t): untyped = len(t.data)
  12. include hashcommon
  13. template initImpl(s: typed, size: int) =
  14. let correctSize = slotsNeeded(size)
  15. when s is OrderedSet:
  16. s.first = -1
  17. s.last = -1
  18. s.counter = 0
  19. newSeq(s.data, correctSize)
  20. template rawInsertImpl() {.dirty.} =
  21. if data.len == 0:
  22. initImpl(s, defaultInitialSize)
  23. data[h].key = key
  24. data[h].hcode = hc
  25. proc rawInsert[A](s: var HashSet[A], data: var KeyValuePairSeq[A], key: A,
  26. hc: Hash, h: Hash) =
  27. rawInsertImpl()
  28. proc enlarge[A](s: var HashSet[A]) =
  29. var n: KeyValuePairSeq[A]
  30. newSeq(n, len(s.data) * growthFactor)
  31. swap(s.data, n) # n is now old seq
  32. for i in countup(0, high(n)):
  33. if isFilled(n[i].hcode):
  34. var j = -1 - rawGetKnownHC(s, n[i].key, n[i].hcode)
  35. rawInsert(s, s.data, n[i].key, n[i].hcode, j)
  36. template inclImpl() {.dirty.} =
  37. if s.data.len == 0:
  38. initImpl(s, defaultInitialSize)
  39. var hc: Hash
  40. var index = rawGet(s, key, hc)
  41. if index < 0:
  42. if mustRehash(s):
  43. enlarge(s)
  44. index = rawGetKnownHC(s, key, hc)
  45. rawInsert(s, s.data, key, hc, -1 - index)
  46. inc(s.counter)
  47. template containsOrInclImpl() {.dirty.} =
  48. if s.data.len == 0:
  49. initImpl(s, defaultInitialSize)
  50. var hc: Hash
  51. var index = rawGet(s, key, hc)
  52. if index >= 0:
  53. result = true
  54. else:
  55. result = false
  56. if mustRehash(s):
  57. enlarge(s)
  58. index = rawGetKnownHC(s, key, hc)
  59. rawInsert(s, s.data, key, hc, -1 - index)
  60. inc(s.counter)
  61. template doWhile(a, b) =
  62. while true:
  63. b
  64. if not a: break
  65. proc exclImpl[A](s: var HashSet[A], key: A): bool {.inline.} =
  66. var hc: Hash
  67. var i = rawGet(s, key, hc)
  68. var msk = high(s.data)
  69. result = true
  70. if i >= 0:
  71. result = false
  72. dec(s.counter)
  73. while true: # KnuthV3 Algo6.4R adapted for i=i+1 instead of i=i-1
  74. var j = i # The correctness of this depends on (h+1) in nextTry,
  75. var r = j # though may be adaptable to other simple sequences.
  76. s.data[i].hcode = 0 # mark current EMPTY
  77. {.push warning[UnsafeDefault]:off.}
  78. reset(s.data[i].key)
  79. {.pop.}
  80. doWhile((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)):
  81. i = (i + 1) and msk # increment mod table size
  82. if isEmpty(s.data[i].hcode): # end of collision cluster; So all done
  83. return
  84. r = s.data[i].hcode and msk # "home" location of key@i
  85. s.data[j] = move(s.data[i]) # data[i] will be marked EMPTY next loop
  86. template dollarImpl() {.dirty.} =
  87. result = "{"
  88. for key in items(s):
  89. if result.len > 1: result.add(", ")
  90. result.addQuoted(key)
  91. result.add("}")
  92. # --------------------------- OrderedSet ------------------------------
  93. proc rawGet[A](t: OrderedSet[A], key: A, hc: var Hash): int {.inline.} =
  94. rawGetImpl()
  95. proc rawInsert[A](s: var OrderedSet[A], data: var OrderedKeyValuePairSeq[A],
  96. key: A, hc: Hash, h: Hash) =
  97. rawInsertImpl()
  98. data[h].next = -1
  99. if s.first < 0: s.first = h
  100. if s.last >= 0: data[s.last].next = h
  101. s.last = h
  102. proc enlarge[A](s: var OrderedSet[A]) =
  103. var n: OrderedKeyValuePairSeq[A]
  104. newSeq(n, len(s.data) * growthFactor)
  105. var h = s.first
  106. s.first = -1
  107. s.last = -1
  108. swap(s.data, n)
  109. while h >= 0:
  110. var nxt = n[h].next
  111. if isFilled(n[h].hcode):
  112. var j = -1 - rawGetKnownHC(s, n[h].key, n[h].hcode)
  113. rawInsert(s, s.data, n[h].key, n[h].hcode, j)
  114. h = nxt
  115. proc exclImpl[A](s: var OrderedSet[A], key: A): bool {.inline.} =
  116. if len(s.data) == 0:
  117. return true
  118. var n: OrderedKeyValuePairSeq[A]
  119. newSeq(n, len(s.data))
  120. var h = s.first
  121. s.first = -1
  122. s.last = -1
  123. swap(s.data, n)
  124. let hc = genHash(key)
  125. result = true
  126. while h >= 0:
  127. var nxt = n[h].next
  128. if isFilled(n[h].hcode):
  129. if n[h].hcode == hc and n[h].key == key:
  130. dec s.counter
  131. result = false
  132. else:
  133. var j = -1 - rawGetKnownHC(s, n[h].key, n[h].hcode)
  134. rawInsert(s, s.data, n[h].key, n[h].hcode, j)
  135. h = nxt