big rename

This commit is contained in:
Araq 2014-08-27 23:42:51 +02:00
commit 11b6958755
98 changed files with 2491 additions and 2341 deletions

View file

@ -1,8 +1,40 @@
#nimrod c -t:-march=i686 --cpu:amd64 --threads:on -d:release lockfreehash.nim
import baseutils, unsigned, math, hashes
import unsigned, math, hashes
#------------------------------------------------------------------------------
## Memory Utility Functions
proc newHeap*[T](): ptr T =
result = cast[ptr T](alloc0(sizeof(T)))
proc copyNew*[T](x: var T): ptr T =
var
size = sizeof(T)
mem = alloc(size)
copyMem(mem, x.addr, size)
return cast[ptr T](mem)
proc copyTo*[T](val: var T, dest: int) =
copyMem(pointer(dest), val.addr, sizeof(T))
proc allocType*[T](): pointer = alloc(sizeof(T))
proc newShared*[T](): ptr T =
result = cast[ptr T](allocShared0(sizeof(T)))
proc copyShared*[T](x: var T): ptr T =
var
size = sizeof(T)
mem = allocShared(size)
copyMem(mem, x.addr, size)
return cast[ptr T](mem)
#------------------------------------------------------------------------------
## Pointer arithmetic
proc `+`*(p: pointer, i: int): pointer {.inline.} =
cast[pointer](cast[int](p) + i)
const
minTableSize = 8
@ -194,7 +226,7 @@ proc copySlot[K,V](idx: int, oldTbl: var PConcTable[K,V], newTbl: var PConcTable
#Prevent new values from appearing in the old table by priming
oldVal = atomic_load_n(oldTbl[idx].value.addr, ATOMIC_RELAXED)
while not isPrime(oldVal):
var box = if oldVal == NULL or isTomb(oldVal) : oldVal.setTomb.setPrime
var box = if oldVal == 0 or isTomb(oldVal) : oldVal.setTomb.setPrime
else: oldVal.setPrime
if atomic_compare_exchange_n(oldTbl[idx].value.addr, oldVal.addr,
box, false, ATOMIC_RELAXED, ATOMIC_RELAXED):
@ -209,8 +241,8 @@ proc copySlot[K,V](idx: int, oldTbl: var PConcTable[K,V], newTbl: var PConcTable
return false
if isTomb(oldVal):
echo("oldVal is Tomb!!!, should not happen")
if pop(oldVal) != NULL:
result = setVal(newTbl, pop(oldKey), pop(oldVal), NULL, true) == NULL
if pop(oldVal) != 0:
result = setVal(newTbl, pop(oldKey), pop(oldVal), 0, true) == 0
if result:
#echo("Copied a Slot! idx= " & $idx & " key= " & $oldKey & " val= " & $oldVal)
else:
@ -323,7 +355,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
idx = idx and (table.len - 1)
#echo("try set idx = " & $idx & "for" & $key)
var
probedKey = NULL
probedKey = 0
openKey = atomic_compare_exchange_n(table[idx].key.addr, probedKey.addr,
key, false, ATOMIC_RELAXED, ATOMIC_RELAXED)
if openKey:
@ -339,7 +371,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
if keyEQ[K](probedKey, key):
#echo("we found the matching slot")
break # We found a matching slot
if (not(expVal != NULL and match)) and (probes >= reProbeLimit or key.isTomb):
if (not(expVal != 0 and match)) and (probes >= reProbeLimit or key.isTomb):
if key.isTomb: echo("Key is Tombstone")
#if probes >= reProbeLimit: echo("Too much probing " & $probes)
#echo("try to resize")
@ -361,7 +393,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
return oldVal
nextTable = atomic_load_n(table.next.addr, ATOMIC_SEQ_CST)
if nextTable == nil and
((oldVal == NULL and
((oldVal == 0 and
(probes >= reProbeLimit or table.used / table.len > 0.8)) or
(isPrime(oldVal))):
if table.used / table.len > 0.8: echo("resize because usage ratio = " &
@ -380,12 +412,12 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int,
if atomic_compare_exchange_n(table[idx].value.addr, oldVal.addr,
val, false, ATOMIC_RELEASE, ATOMIC_RELAXED):
#echo("val set at table " & $cast[int](table))
if expVal != NULL:
if (oldVal == NULL or isTomb(oldVal)) and not isTomb(val):
if expVal != 0:
if (oldVal == 0 or isTomb(oldVal)) and not isTomb(val):
discard atomic_add_fetch(table.active.addr, 1, ATOMIC_RELAXED)
elif not (oldVal == NULL or isTomb(oldVal)) and isTomb(val):
elif not (oldVal == 0 or isTomb(oldVal)) and isTomb(val):
discard atomic_add_fetch(table.active.addr, -1, ATOMIC_RELAXED)
if oldVal == NULL and expVal != NULL:
if oldVal == 0 and expVal != 0:
return setTomb(oldVal)
else: return oldVal
if isPrime(oldVal):
@ -415,7 +447,7 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int =
if not isPrime(val):
if isTomb(val):
#echo("val was tomb but not prime")
return NULL
return 0
else:
#echo("-GotIt- idx = ", idx, " key = ", key, " val ", val )
return val
@ -427,7 +459,7 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int =
if probes >= reProbeLimit*4 or key.isTomb:
if newTable == nil:
#echo("too many probes and no new table ", key, " ", idx )
return NULL
return 0
else:
newTable = helpCopy(table)
return getVal(newTable, key)
@ -437,10 +469,10 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int =
#------------------------------------------------------------------------------
#proc set*(table: var PConcTable[TRaw,TRaw], key: TRaw, val: TRaw) =
# discard setVal(table, pack(key), pack(key), NULL, false)
# discard setVal(table, pack(key), pack(key), 0, false)
#proc set*[V](table: var PConcTable[TRaw,V], key: TRaw, val: ptr V) =
# discard setVal(table, pack(key), cast[int](val), NULL, false)
# discard setVal(table, pack(key), cast[int](val), 0, false)
proc set*[K,V](table: var PConcTable[K,V], key: var K, val: var V) =
when not (K is TRaw):
@ -451,10 +483,10 @@ proc set*[K,V](table: var PConcTable[K,V], key: var K, val: var V) =
var newVal = cast[int](copyShared(val))
else:
var newVal = pack(val)
var oldPtr = pop(setVal(table, newKey, newVal, NULL, false))
var oldPtr = pop(setVal(table, newKey, newVal, 0, false))
#echo("oldPtr = ", cast[int](oldPtr), " newPtr = ", cast[int](newPtr))
when not (V is TRaw):
if newVal != oldPtr and oldPtr != NULL:
if newVal != oldPtr and oldPtr != 0:
deallocShared(cast[ptr V](oldPtr))
@ -573,10 +605,3 @@ when isMainModule:
# echo(i, " = ", hashInt(i) and 8191)
deleteConcTable(table)

View file

@ -1,41 +0,0 @@
#------------------------------------------------------------------------------
## Useful Constants
const NULL* = 0
#------------------------------------------------------------------------------
## Memory Utility Functions
proc newHeap*[T](): ptr T =
result = cast[ptr T](alloc0(sizeof(T)))
proc copyNew*[T](x: var T): ptr T =
var
size = sizeof(T)
mem = alloc(size)
copyMem(mem, x.addr, size)
return cast[ptr T](mem)
proc copyTo*[T](val: var T, dest: int) =
copyMem(pointer(dest), val.addr, sizeof(T))
proc allocType*[T](): pointer = alloc(sizeof(T))
proc newShared*[T](): ptr T =
result = cast[ptr T](allocShared0(sizeof(T)))
proc copyShared*[T](x: var T): ptr T =
var
size = sizeof(T)
mem = allocShared(size)
copyMem(mem, x.addr, size)
return cast[ptr T](mem)
#------------------------------------------------------------------------------
## Pointer arithmetic
proc `+`*(p: pointer, i: int): pointer {.inline.} =
cast[pointer](cast[int](p) + i)

View file

@ -1,6 +1,6 @@
#
#
# Nimrod's Runtime Library
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
@ -12,30 +12,32 @@
## by Adam Langley.
type
TNode[T] = object {.pure, final, acyclic.}
NodeObj[T] = object {.pure, final, acyclic.}
byte: int ## byte index of the difference
otherbits: char
case isLeaf: bool
of false: child: array[0..1, ref TNode[T]]
of false: child: array[0..1, ref NodeObj[T]]
of true:
key: string
when T isnot void:
val: T
PNode[T] = ref TNode[T]
TCritBitTree*[T] = object {.
Node[T] = ref NodeObj[T]
CritBitTree*[T] = object {.
pure, final.} ## The crit bit tree can either be used
## as a mapping from strings to
## some type ``T`` or as a set of
## strings if ``T`` is void.
root: PNode[T]
root: Node[T]
count: int
proc len*[T](c: TCritBitTree[T]): int =
{.deprecated: [TCritBitTree: CritBitTree].}
proc len*[T](c: CritBitTree[T]): int =
## returns the number of elements in `c` in O(1).
result = c.count
proc rawGet[T](c: TCritBitTree[T], key: string): PNode[T] =
proc rawGet[T](c: CritBitTree[T], key: string): Node[T] =
var it = c.root
while it != nil:
if not it.isLeaf:
@ -45,15 +47,15 @@ proc rawGet[T](c: TCritBitTree[T], key: string): PNode[T] =
else:
return if it.key == key: it else: nil
proc contains*[T](c: TCritBitTree[T], key: string): bool {.inline.} =
proc contains*[T](c: CritBitTree[T], key: string): bool {.inline.} =
## returns true iff `c` contains the given `key`.
result = rawGet(c, key) != nil
proc hasKey*[T](c: TCritBitTree[T], key: string): bool {.inline.} =
proc hasKey*[T](c: CritBitTree[T], key: string): bool {.inline.} =
## alias for `contains`.
result = rawGet(c, key) != nil
proc rawInsert[T](c: var TCritBitTree[T], key: string): PNode[T] =
proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] =
if c.root == nil:
new c.root
c.root.isleaf = true
@ -84,7 +86,7 @@ proc rawInsert[T](c: var TCritBitTree[T], key: string): PNode[T] =
let ch = it.key[newByte]
let dir = (1 + (ord(ch) or newOtherBits)) shr 8
var inner: PNode[T]
var inner: Node[T]
new inner
new result
result.isLeaf = true
@ -106,7 +108,7 @@ proc rawInsert[T](c: var TCritBitTree[T], key: string): PNode[T] =
wherep[] = inner
inc c.count
proc containsOrIncl*[T](c: var TCritBitTree[T], key: string, val: T): bool =
proc containsOrIncl*[T](c: var CritBitTree[T], key: string, val: T): bool =
## returns true iff `c` contains the given `key`. If the key does not exist
## ``c[key] = val`` is performed.
let oldCount = c.count
@ -115,23 +117,23 @@ proc containsOrIncl*[T](c: var TCritBitTree[T], key: string, val: T): bool =
when T isnot void:
if not result: n.val = val
proc containsOrIncl*(c: var TCritBitTree[void], key: string): bool =
proc containsOrIncl*(c: var CritBitTree[void], key: string): bool =
## returns true iff `c` contains the given `key`. If the key does not exist
## it is inserted into `c`.
let oldCount = c.count
var n = rawInsert(c, key)
result = c.count == oldCount
proc incl*(c: var TCritBitTree[void], key: string) =
proc incl*(c: var CritBitTree[void], key: string) =
## includes `key` in `c`.
discard rawInsert(c, key)
proc `[]=`*[T](c: var TCritBitTree[T], key: string, val: T) =
proc `[]=`*[T](c: var CritBitTree[T], key: string, val: T) =
## puts a (key, value)-pair into `t`.
var n = rawInsert(c, key)
n.val = val
proc `[]`*[T](c: TCritBitTree[T], key: string): T {.inline.} =
proc `[]`*[T](c: CritBitTree[T], key: string): T {.inline.} =
## retrieves the value at ``c[key]``. If `key` is not in `t`,
## default empty value for the type `B` is returned
## and no exception is raised. One can check with ``hasKey`` whether the key
@ -139,22 +141,22 @@ proc `[]`*[T](c: TCritBitTree[T], key: string): T {.inline.} =
let n = rawGet(c, key)
if n != nil: result = n.val
proc mget*[T](c: var TCritBitTree[T], key: string): var T {.inline.} =
proc mget*[T](c: var CritBitTree[T], key: string): var T {.inline.} =
## retrieves the value at ``c[key]``. The value can be modified.
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
## If `key` is not in `t`, the ``KeyError`` exception is raised.
let n = rawGet(c, key)
if n != nil: result = n.val
else: raise newException(EInvalidKey, "key not found: " & $key)
else: raise newException(KeyError, "key not found: " & $key)
proc excl*[T](c: var TCritBitTree[T], key: string) =
proc excl*[T](c: var CritBitTree[T], key: string) =
## removes `key` (and its associated value) from the set `c`.
## If the `key` does not exist, nothing happens.
var p = c.root
var wherep = addr(c.root)
var whereq: ptr PNode = nil
var whereq: ptr Node[T] = nil
if p == nil: return
var dir = 0
var q: PNode
var q: Node[T]
while not p.isLeaf:
whereq = wherep
q = p
@ -170,7 +172,7 @@ proc excl*[T](c: var TCritBitTree[T], key: string) =
whereq[] = q.child[1 - dir]
dec c.count
iterator leaves[T](n: PNode[T]): PNode[T] =
iterator leaves[T](n: Node[T]): Node[T] =
if n != nil:
# XXX actually we could compute the necessary stack size in advance:
# it's rougly log2(c.count).
@ -183,33 +185,33 @@ iterator leaves[T](n: PNode[T]): PNode[T] =
assert(it != nil)
yield it
iterator keys*[T](c: TCritBitTree[T]): string =
iterator keys*[T](c: CritBitTree[T]): string =
## yields all keys in lexicographical order.
for x in leaves(c.root): yield x.key
iterator values*[T](c: TCritBitTree[T]): T =
iterator values*[T](c: CritBitTree[T]): T =
## yields all values of `c` in the lexicographical order of the
## corresponding keys.
for x in leaves(c.root): yield x.val
iterator mvalues*[T](c: var TCritBitTree[T]): var T =
iterator mvalues*[T](c: var CritBitTree[T]): var T =
## yields all values of `c` in the lexicographical order of the
## corresponding keys. The values can be modified.
for x in leaves(c.root): yield x.val
iterator items*[T](c: TCritBitTree[T]): string =
iterator items*[T](c: CritBitTree[T]): string =
## yields all keys in lexicographical order.
for x in leaves(c.root): yield x.key
iterator pairs*[T](c: TCritBitTree[T]): tuple[key: string, val: T] =
iterator pairs*[T](c: CritBitTree[T]): tuple[key: string, val: T] =
## yields all (key, value)-pairs of `c`.
for x in leaves(c.root): yield (x.key, x.val)
iterator mpairs*[T](c: var TCritBitTree[T]): tuple[key: string, val: var T] =
iterator mpairs*[T](c: var CritBitTree[T]): tuple[key: string, val: var T] =
## yields all (key, value)-pairs of `c`. The yielded values can be modified.
for x in leaves(c.root): yield (x.key, x.val)
proc allprefixedAux[T](c: TCritBitTree[T], key: string): PNode[T] =
proc allprefixedAux[T](c: CritBitTree[T], key: string): Node[T] =
var p = c.root
var top = p
if p != nil:
@ -223,42 +225,42 @@ proc allprefixedAux[T](c: TCritBitTree[T], key: string): PNode[T] =
if p.key[i] != key[i]: return
result = top
iterator itemsWithPrefix*[T](c: TCritBitTree[T], prefix: string): string =
iterator itemsWithPrefix*[T](c: CritBitTree[T], prefix: string): string =
## yields all keys starting with `prefix`.
let top = allprefixedAux(c, prefix)
for x in leaves(top): yield x.key
iterator keysWithPrefix*[T](c: TCritBitTree[T], prefix: string): string =
iterator keysWithPrefix*[T](c: CritBitTree[T], prefix: string): string =
## yields all keys starting with `prefix`.
let top = allprefixedAux(c, prefix)
for x in leaves(top): yield x.key
iterator valuesWithPrefix*[T](c: TCritBitTree[T], prefix: string): T =
iterator valuesWithPrefix*[T](c: CritBitTree[T], prefix: string): T =
## yields all values of `c` starting with `prefix` of the
## corresponding keys.
let top = allprefixedAux(c, prefix)
for x in leaves(top): yield x.val
iterator mvaluesWithPrefix*[T](c: var TCritBitTree[T], prefix: string): var T =
iterator mvaluesWithPrefix*[T](c: var CritBitTree[T], prefix: string): var T =
## yields all values of `c` starting with `prefix` of the
## corresponding keys. The values can be modified.
let top = allprefixedAux(c, prefix)
for x in leaves(top): yield x.val
iterator pairsWithPrefix*[T](c: TCritBitTree[T],
iterator pairsWithPrefix*[T](c: CritBitTree[T],
prefix: string): tuple[key: string, val: T] =
## yields all (key, value)-pairs of `c` starting with `prefix`.
let top = allprefixedAux(c, prefix)
for x in leaves(top): yield (x.key, x.val)
iterator mpairsWithPrefix*[T](c: var TCritBitTree[T],
iterator mpairsWithPrefix*[T](c: var CritBitTree[T],
prefix: string): tuple[key: string, val: var T] =
## yields all (key, value)-pairs of `c` starting with `prefix`.
## The yielded values can be modified.
let top = allprefixedAux(c, prefix)
for x in leaves(top): yield (x.key, x.val)
proc `$`*[T](c: TCritBitTree[T]): string =
proc `$`*[T](c: CritBitTree[T]): string =
## turns `c` into a string representation. Example outputs:
## ``{keyA: value, keyB: value}``, ``{:}``
## If `T` is void the outputs look like:
@ -285,7 +287,7 @@ proc `$`*[T](c: TCritBitTree[T]): string =
result.add("}")
when isMainModule:
var r: TCritBitTree[void]
var r: CritBitTree[void]
r.incl "abc"
r.incl "xyz"
r.incl "def"

View file

@ -1,6 +1,6 @@
#
#
# Nimrod's Runtime Library
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
@ -9,7 +9,7 @@
## The ``intsets`` module implements an efficient int set implemented as a
## sparse bit set.
## **Note**: Since Nimrod currently does not allow the assignment operator to
## **Note**: Since Nim currently does not allow the assignment operator to
## be overloaded, ``=`` for int sets performs some rather meaningless shallow
## copy; use ``assign`` to get a deep copy.
@ -17,7 +17,7 @@ import
os, hashes, math
type
TBitScalar = int
BitScalar = int
const
InitIntSetSize = 8 # must be a power of two!
@ -25,8 +25,8 @@ const
BitsPerTrunk = 1 shl TrunkShift # needs to be a power of 2 and
# divisible by 64
TrunkMask = BitsPerTrunk - 1
IntsPerTrunk = BitsPerTrunk div (sizeof(TBitScalar) * 8)
IntShift = 5 + ord(sizeof(TBitScalar) == 8) # 5 or 6, depending on int width
IntsPerTrunk = BitsPerTrunk div (sizeof(BitScalar) * 8)
IntShift = 5 + ord(sizeof(BitScalar) == 8) # 5 or 6, depending on int width
IntMask = 1 shl IntShift - 1
type
@ -34,15 +34,16 @@ type
TTrunk {.final.} = object
next: PTrunk # all nodes are connected with this pointer
key: int # start address at bit 0
bits: array[0..IntsPerTrunk - 1, TBitScalar] # a bit vector
bits: array[0..IntsPerTrunk - 1, BitScalar] # a bit vector
TTrunkSeq = seq[PTrunk]
TIntSet* {.final.} = object ## an efficient set of 'int' implemented as a
## sparse bit set
IntSet* = object ## an efficient set of 'int' implemented as a sparse bit set
counter, max: int
head: PTrunk
data: TTrunkSeq
{.deprecated: [TIntSet: IntSet].}
proc mustRehash(length, counter: int): bool {.inline.} =
assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4)

View file

@ -1,6 +1,6 @@
#
#
# Nimrod's Runtime Library
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
@ -15,52 +15,58 @@ when not defined(nimhygiene):
{.pragma: dirty.}
type
TDoublyLinkedNode* {.pure,
final.}[T] = object ## a node a doubly linked list consists of
next*, prev*: ref TDoublyLinkedNode[T]
DoublyLinkedNodeObj*[T] = object ## a node a doubly linked list consists of
next*, prev*: ref DoublyLinkedNodeObj[T]
value*: T
PDoublyLinkedNode*[T] = ref TDoublyLinkedNode[T]
DoublyLinkedNode*[T] = ref DoublyLinkedNodeObj[T]
TSinglyLinkedNode* {.pure,
final.}[T] = object ## a node a singly linked list consists of
next*: ref TSinglyLinkedNode[T]
SinglyLinkedNodeObj*[T] = object ## a node a singly linked list consists of
next*: ref SinglyLinkedNodeObj[T]
value*: T
PSinglyLinkedNode*[T] = ref TSinglyLinkedNode[T]
SinglyLinkedNode*[T] = ref SinglyLinkedNodeObj[T]
TSinglyLinkedList* {.pure, final.}[T] = object ## a singly linked list
head*, tail*: PSinglyLinkedNode[T]
SinglyLinkedList*[T] = object ## a singly linked list
head*, tail*: SinglyLinkedNode[T]
TDoublyLinkedList* {.pure, final.}[T] = object ## a doubly linked list
head*, tail*: PDoublyLinkedNode[T]
DoublyLinkedList*[T] = object ## a doubly linked list
head*, tail*: DoublyLinkedNode[T]
TSinglyLinkedRing* {.pure, final.}[T] = object ## a singly linked ring
head*: PSinglyLinkedNode[T]
SinglyLinkedRing*[T] = object ## a singly linked ring
head*: SinglyLinkedNode[T]
TDoublyLinkedRing* {.pure, final.}[T] = object ## a doubly linked ring
head*: PDoublyLinkedNode[T]
DoublyLinkedRing*[T] = object ## a doubly linked ring
head*: DoublyLinkedNode[T]
proc initSinglyLinkedList*[T](): TSinglyLinkedList[T] =
{.deprecated: [TDoublyLinkedNode: DoublyLinkedNodeObj,
PDoublyLinkedNode: DoublyLinkedNode,
TSinglyLinkedNode: SinglyLinkedNodeObj,
PSinglyLinkedNode: SinglyLinkedNode,
TDoublyLinkedList: DoublyLinkedList,
TSinglyLinkedRing: SinglyLinkedRing,
TDoublyLinkedRing: DoublyLinkedRing].}
proc initSinglyLinkedList*[T](): SinglyLinkedList[T] =
## creates a new singly linked list that is empty.
discard
proc initDoublyLinkedList*[T](): TDoublyLinkedList[T] =
proc initDoublyLinkedList*[T](): DoublyLinkedList[T] =
## creates a new doubly linked list that is empty.
discard
proc initSinglyLinkedRing*[T](): TSinglyLinkedRing[T] =
proc initSinglyLinkedRing*[T](): SinglyLinkedRing[T] =
## creates a new singly linked ring that is empty.
discard
proc initDoublyLinkedRing*[T](): TDoublyLinkedRing[T] =
proc initDoublyLinkedRing*[T](): DoublyLinkedRing[T] =
## creates a new doubly linked ring that is empty.
discard
proc newDoublyLinkedNode*[T](value: T): PDoublyLinkedNode[T] =
proc newDoublyLinkedNode*[T](value: T): DoublyLinkedNode[T] =
## creates a new doubly linked node with the given `value`.
new(result)
result.value = value
proc newSinglyLinkedNode*[T](value: T): PSinglyLinkedNode[T] =
proc newSinglyLinkedNode*[T](value: T): SinglyLinkedNode[T] =
## creates a new singly linked node with the given `value`.
new(result)
result.value = value
@ -99,38 +105,38 @@ template findImpl() {.dirty.} =
for x in nodes(L):
if x.value == value: return x
iterator items*[T](L: TDoublyLinkedList[T]): T =
iterator items*[T](L: DoublyLinkedList[T]): T =
## yields every value of `L`.
itemsListImpl()
iterator items*[T](L: TSinglyLinkedList[T]): T =
iterator items*[T](L: SinglyLinkedList[T]): T =
## yields every value of `L`.
itemsListImpl()
iterator items*[T](L: TSinglyLinkedRing[T]): T =
iterator items*[T](L: SinglyLinkedRing[T]): T =
## yields every value of `L`.
itemsRingImpl()
iterator items*[T](L: TDoublyLinkedRing[T]): T =
iterator items*[T](L: DoublyLinkedRing[T]): T =
## yields every value of `L`.
itemsRingImpl()
iterator nodes*[T](L: TSinglyLinkedList[T]): PSinglyLinkedNode[T] =
iterator nodes*[T](L: SinglyLinkedList[T]): SinglyLinkedNode[T] =
## iterates over every node of `x`. Removing the current node from the
## list during traversal is supported.
nodesListImpl()
iterator nodes*[T](L: TDoublyLinkedList[T]): PDoublyLinkedNode[T] =
iterator nodes*[T](L: DoublyLinkedList[T]): DoublyLinkedNode[T] =
## iterates over every node of `x`. Removing the current node from the
## list during traversal is supported.
nodesListImpl()
iterator nodes*[T](L: TSinglyLinkedRing[T]): PSinglyLinkedNode[T] =
iterator nodes*[T](L: SinglyLinkedRing[T]): SinglyLinkedNode[T] =
## iterates over every node of `x`. Removing the current node from the
## list during traversal is supported.
nodesRingImpl()
iterator nodes*[T](L: TDoublyLinkedRing[T]): PDoublyLinkedNode[T] =
iterator nodes*[T](L: DoublyLinkedRing[T]): DoublyLinkedNode[T] =
## iterates over every node of `x`. Removing the current node from the
## list during traversal is supported.
nodesRingImpl()
@ -142,33 +148,33 @@ template dollarImpl() {.dirty.} =
result.add($x.value)
result.add("]")
proc `$`*[T](L: TSinglyLinkedList[T]): string =
proc `$`*[T](L: SinglyLinkedList[T]): string =
## turns a list into its string representation.
dollarImpl()
proc `$`*[T](L: TDoublyLinkedList[T]): string =
proc `$`*[T](L: DoublyLinkedList[T]): string =
## turns a list into its string representation.
dollarImpl()
proc `$`*[T](L: TSinglyLinkedRing[T]): string =
proc `$`*[T](L: SinglyLinkedRing[T]): string =
## turns a list into its string representation.
dollarImpl()
proc `$`*[T](L: TDoublyLinkedRing[T]): string =
proc `$`*[T](L: DoublyLinkedRing[T]): string =
## turns a list into its string representation.
dollarImpl()
proc find*[T](L: TSinglyLinkedList[T], value: T): PSinglyLinkedNode[T] =
proc find*[T](L: SinglyLinkedList[T], value: T): SinglyLinkedNode[T] =
## searches in the list for a value. Returns nil if the value does not
## exist.
findImpl()
proc find*[T](L: TDoublyLinkedList[T], value: T): PDoublyLinkedNode[T] =
proc find*[T](L: DoublyLinkedList[T], value: T): DoublyLinkedNode[T] =
## searches in the list for a value. Returns nil if the value does not
## exist.
findImpl()
proc find*[T](L: TSinglyLinkedRing[T], value: T): PSinglyLinkedNode[T] =
proc find*[T](L: SinglyLinkedRing[T], value: T): SinglyLinkedNode[T] =
## searches in the list for a value. Returns nil if the value does not
## exist.
findImpl()
@ -300,5 +306,3 @@ proc remove*[T](L: var TDoublyLinkedRing[T], n: PDoublyLinkedNode[T]) =
L.head = nil
else:
L.head = L.head.prev

View file

@ -1,6 +1,6 @@
#
#
# Nimrod's Runtime Library
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
@ -12,13 +12,15 @@
import math
type
TQueue* {.pure, final.}[T] = object ## a queue
Queue*[T] = object ## a queue
data: seq[T]
rd, wr, count, mask: int
{.deprecated: [TQueue: Queue].}
proc initQueue*[T](initialSize=4): TQueue[T] =
## creates a new queue. `initialSize` needs to be a power of 2.
assert IsPowerOfTwo(initialSize)
assert isPowerOfTwo(initialSize)
result.mask = initialSize-1
newSeq(result.data, initialSize)

View file

@ -1,6 +1,6 @@
#
#
# Nimrod's Runtime Library
# Nim's Runtime Library
# (c) Copyright 2011 Alex Mitchell
#
# See the file "copying.txt", included in this
@ -31,7 +31,7 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] =
##
## Example:
##
## .. code-block:: nimrod
## .. code-block::
## let
## s1 = @[1, 2, 3]
## s2 = @[4, 5]
@ -50,7 +50,7 @@ proc concat*[T](seqs: varargs[seq[T]]): seq[T] =
proc deduplicate*[T](seq1: seq[T]): seq[T] =
## Returns a new sequence without duplicates.
##
## .. code-block:: nimrod
## .. code-block::
## let
## dup1 = @[1, 1, 3, 4, 2, 2, 8, 1, 4]
## dup2 = @["a", "a", "c", "d", "d"]
@ -69,7 +69,7 @@ proc zip*[S, T](seq1: seq[S], seq2: seq[T]): seq[tuple[a: S, b: T]] =
## fields `a` and `b`. If one sequence is shorter, the remaining items in the
## longer sequence are discarded. Example:
##
## .. code-block:: nimrod
## .. code-block::
## let
## short = @[1, 2, 3]
## long = @[6, 5, 4, 3, 2, 1]
@ -104,7 +104,7 @@ proc distribute*[T](s: seq[T], num: int, spread = true): seq[seq[T]] =
##
## Example:
##
## .. code-block:: nimrod
## .. code-block::
## let numbers = @[1, 2, 3, 4, 5, 6, 7]
## assert numbers.distribute(3) == @[@[1, 2, 3], @[4, 5], @[6, 7]]
## assert numbers.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]]
@ -155,7 +155,7 @@ iterator filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): T =
##
## Example:
##
## .. code-block:: nimrod
## .. code-block::
## let numbers = @[1, 4, 5, 8, 9, 7, 4]
## for n in filter(numbers, proc (x: int): bool = x mod 2 == 0):
## echo($n)
@ -169,7 +169,7 @@ proc filter*[T](seq1: seq[T], pred: proc(item: T): bool {.closure.}): seq[T] =
##
## Example:
##
## .. code-block:: nimrod
## .. code-block::
## let
## colors = @["red", "yellow", "black"]
## f1 = filter(colors, proc(x: string): bool = x.len < 6)
@ -184,7 +184,7 @@ proc keepIf*[T](seq1: var seq[T], pred: proc(item: T): bool {.closure.}) =
##
## Example:
##
## .. code-block:: nimrod
## .. code-block::
## var floats = @[13.0, 12.5, 5.8, 2.0, 6.1, 9.9, 10.1]
## keepIf(floats, proc(x: float): bool = x > 10)
## assert floats == @[13.0, 12.5, 10.1]
@ -202,7 +202,7 @@ proc delete*[T](s: var seq[T], first=0, last=0) =
##
## Example:
##
##.. code-block:: nimrod
##.. code-block::
## let outcome = @[1,1,1,1,1,1,1,1]
## var dest = @[1,1,1,2,2,2,2,2,2,1,1,1,1,1]
## dest.delete(3, 8)
@ -223,7 +223,7 @@ proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) =
##
## Example:
##
##.. code-block:: nimrod
##.. code-block::
## var dest = @[1,1,1,1,1,1,1,1]
## let
## src = @[2,2,2,2,2,2]
@ -254,7 +254,7 @@ template filterIt*(seq1, pred: expr): expr {.immediate.} =
## the ``it`` variable for testing, like: ``filterIt("abcxyz", it == 'x')``.
## Example:
##
## .. code-block:: nimrod
## .. code-block::
## let
## temperatures = @[-272.15, -2.0, 24.5, 44.31, 99.9, -113.44]
## acceptable = filterIt(temperatures, it < 50 and it > -10)
@ -273,7 +273,7 @@ template keepItIf*(varSeq, pred: expr) =
## the ``it`` variable for testing, like: ``keepItIf("abcxyz", it == 'x')``.
## Example:
##
## .. code-block:: nimrod
## .. code-block::
## var candidates = @["foo", "bar", "baz", "foobar"]
## keepItIf(candidates, it.len == 3 and it[0] == 'b')
## assert candidates == @["bar", "baz"]
@ -292,7 +292,7 @@ template toSeq*(iter: expr): expr {.immediate.} =
##
## Example:
##
## .. code-block:: nimrod
## .. code-block::
## let
## numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
## odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
@ -318,18 +318,18 @@ template foldl*(sequence, operation: expr): expr =
## the sequence of numbers 1, 2 and 3 will be parenthesized as (((1) - 2) -
## 3). Example:
##
## .. code-block:: nimrod
## .. code-block::
## let
## numbers = @[5, 9, 11]
## addition = foldl(numbers, a + b)
## substraction = foldl(numbers, a - b)
## multiplication = foldl(numbers, a * b)
## words = @["nim", "rod", "is", "cool"]
## words = @["nim", "is", "cool"]
## concatenation = foldl(words, a & b)
## assert addition == 25, "Addition is (((5)+9)+11)"
## assert substraction == -15, "Substraction is (((5)-9)-11)"
## assert multiplication == 495, "Multiplication is (((5)*9)*11)"
## assert concatenation == "nimrodiscool"
## assert concatenation == "nimiscool"
assert sequence.len > 0, "Can't fold empty sequences"
var result {.gensym.}: type(sequence[0])
result = sequence[0]
@ -354,18 +354,18 @@ template foldr*(sequence, operation: expr): expr =
## the sequence of numbers 1, 2 and 3 will be parenthesized as (1 - (2 -
## (3))). Example:
##
## .. code-block:: nimrod
## .. code-block::
## let
## numbers = @[5, 9, 11]
## addition = foldr(numbers, a + b)
## substraction = foldr(numbers, a - b)
## multiplication = foldr(numbers, a * b)
## words = @["nim", "rod", "is", "cool"]
## words = @["nim", "is", "cool"]
## concatenation = foldr(words, a & b)
## assert addition == 25, "Addition is (5+(9+(11)))"
## assert substraction == 7, "Substraction is (5-(9-(11)))"
## assert multiplication == 495, "Multiplication is (5*(9*(11)))"
## assert concatenation == "nimrodiscool"
## assert concatenation == "nimiscool"
assert sequence.len > 0, "Can't fold empty sequences"
var result {.gensym.}: type(sequence[0])
result = sequence[sequence.len - 1]
@ -384,7 +384,7 @@ template mapIt*(seq1, typ, pred: expr): expr =
## since the new returned sequence can have a different type than the
## original. Example:
##
## .. code-block:: nimrod
## .. code-block::
## let
## nums = @[1, 2, 3, 4]
## strings = nums.mapIt(string, $(4 * it))
@ -401,7 +401,7 @@ template mapIt*(varSeq, pred: expr) =
## expression. The expression has to return the same type as the sequence you
## are mutating. Example:
##
## .. code-block:: nimrod
## .. code-block::
## var nums = @[1, 2, 3, 4]
## nums.mapIt(it * 3)
## assert nums[0] + nums[3] == 15
@ -412,7 +412,7 @@ template mapIt*(varSeq, pred: expr) =
template newSeqWith*(len: int, init: expr): expr =
## creates a new sequence, calling `init` to initialize each value. Example:
##
## .. code-block:: nimrod
## .. code-block::
## var seq2D = newSeqWith(20, newSeq[bool](10))
## seq2D[0][0] = true
## seq2D[1][0] = true
@ -503,12 +503,12 @@ when isMainModule:
addition = foldl(numbers, a + b)
substraction = foldl(numbers, a - b)
multiplication = foldl(numbers, a * b)
words = @["nim", "rod", "is", "cool"]
words = @["nim", "is", "cool"]
concatenation = foldl(words, a & b)
assert addition == 25, "Addition is (((5)+9)+11)"
assert substraction == -15, "Substraction is (((5)-9)-11)"
assert multiplication == 495, "Multiplication is (((5)*9)*11)"
assert concatenation == "nimrodiscool"
assert concatenation == "nimiscool"
block: # foldr tests
let
@ -516,12 +516,12 @@ when isMainModule:
addition = foldr(numbers, a + b)
substraction = foldr(numbers, a - b)
multiplication = foldr(numbers, a * b)
words = @["nim", "rod", "is", "cool"]
words = @["nim", "is", "cool"]
concatenation = foldr(words, a & b)
assert addition == 25, "Addition is (5+(9+(11)))"
assert substraction == 7, "Substraction is (5-(9-(11)))"
assert multiplication == 495, "Multiplication is (5*(9*(11)))"
assert concatenation == "nimrodiscool"
assert concatenation == "nimiscool"
block: # delete tests
let outcome = @[1,1,1,1,1,1,1,1]

View file

@ -1,6 +1,6 @@
#
#
# Nimrod's Runtime Library
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
@ -24,17 +24,19 @@ when not defined(nimhygiene):
{.pragma: dirty.}
type
TSlotEnum = enum seEmpty, seFilled, seDeleted
TKeyValuePair[A] = tuple[slot: TSlotEnum, key: A]
TKeyValuePairSeq[A] = seq[TKeyValuePair[A]]
TSet* {.final, myShallow.}[A] = object ## \
SlotEnum = enum seEmpty, seFilled, seDeleted
KeyValuePair[A] = tuple[slot: SlotEnum, key: A]
KeyValuePairSeq[A] = seq[KeyValuePair[A]]
HashSet* {.myShallow.}[A] = object ## \
## A generic hash set.
##
## Use `init() <#init,TSet[A],int>`_ or `initSet[type]() <#initSet>`_
## Use `init() <#init,HashSet[A],int>`_ or `initSet[type]() <#initSet>`_
## before calling other procs on it.
data: TKeyValuePairSeq[A]
data: KeyValuePairSeq[A]
counter: int
{.deprecated: [TSet: HashSet].}
proc isValid*[A](s: TSet[A]): bool =
## Returns `true` if the set has been initialized with `initSet <#initSet>`_.
##
@ -43,7 +45,7 @@ proc isValid*[A](s: TSet[A]): bool =
## your own procs to verify that sets passed to your procs are correctly
## initialized. Example:
##
## .. code-block :: nimrod
## .. code-block ::
## proc savePreferences(options: TSet[string]) =
## assert options.isValid, "Pass an initialized set!"
## # Do stuff here, may crash in release builds!
@ -490,19 +492,20 @@ proc map*[A, B](data: TSet[A], op: proc (x: A): B {.closure.}): TSet[B] =
# ------------------------------ ordered set ------------------------------
type
TOrderedKeyValuePair[A] = tuple[
slot: TSlotEnum, next: int, key: A]
TOrderedKeyValuePairSeq[A] = seq[TOrderedKeyValuePair[A]]
TOrderedSet* {.
final, myShallow.}[A] = object ## \
OrderedKeyValuePair[A] = tuple[
slot: SlotEnum, next: int, key: A]
OrderedKeyValuePairSeq[A] = seq[OrderedKeyValuePair[A]]
OrderedSet* {.myShallow.}[A] = object ## \
## A generic hash set that remembers insertion order.
##
## Use `init() <#init,TOrderedSet[A],int>`_ or `initOrderedSet[type]()
## Use `init() <#init,OrderedSet[A],int>`_ or `initOrderedSet[type]()
## <#initOrderedSet>`_ before calling other procs on it.
data: TOrderedKeyValuePairSeq[A]
counter, first, last: int
proc isValid*[A](s: TOrderedSet[A]): bool =
{.deprecated: [TOrderedSet: OrderedSet].}
proc isValid*[A](s: OrderedSet[A]): bool =
## Returns `true` if the ordered set has been initialized with `initSet
## <#initOrderedSet>`_.
##
@ -511,13 +514,13 @@ proc isValid*[A](s: TOrderedSet[A]): bool =
## in your own procs to verify that ordered sets passed to your procs are
## correctly initialized. Example:
##
## .. code-block :: nimrod
## .. code-block::
## proc saveTarotCards(cards: TOrderedSet[int]) =
## assert cards.isValid, "Pass an initialized set!"
## # Do stuff here, may crash in release builds!
result = not s.data.isNil
proc len*[A](s: TOrderedSet[A]): int {.inline.} =
proc len*[A](s: OrderedSet[A]): int {.inline.} =
## Returns the number of keys in `s`.
##
## Due to an implementation detail you can call this proc on variables which
@ -734,14 +737,14 @@ proc `==`*[A](s, t: TOrderedSet[A]): bool =
proc testModule() =
## Internal micro test to validate docstrings and such.
block isValidTest:
var options: TSet[string]
var options: HashSet[string]
proc savePreferences(options: TSet[string]) =
assert options.isValid, "Pass an initialized set!"
options = initSet[string]()
options.savePreferences
block lenTest:
var values: TSet[int]
var values: HashSet[int]
assert(not values.isValid)
assert values.len == 0
assert values.card == 0
@ -835,14 +838,14 @@ proc testModule() =
assert b == toSet(["1", "2", "3"])
block isValidTest:
var cards: TOrderedSet[string]
var cards: OrderedSet[string]
proc saveTarotCards(cards: TOrderedSet[string]) =
assert cards.isValid, "Pass an initialized set!"
cards = initOrderedSet[string]()
cards.saveTarotCards
block lenTest:
var values: TOrderedSet[int]
var values: OrderedSet[int]
assert(not values.isValid)
assert values.len == 0
assert values.card == 0
@ -879,7 +882,7 @@ proc testModule() =
assert(a == b) # https://github.com/Araq/Nimrod/issues/1413
block initBlocks:
var a: TOrderedSet[int]
var a: OrderedSet[int]
a.init(4)
a.incl(2)
a.init

View file

@ -1,6 +1,6 @@
#
#
# Nimrod's Runtime Library
# Nim's Runtime Library
# (c) Copyright 2013 Andreas Rumpf
#
# See the file "copying.txt", included in this
@ -28,7 +28,7 @@
## you add such a proc for your custom type everything will work. See this
## example:
##
## .. code-block:: nimrod
## .. code-block::
## type
## Person = object
## firstName, lastName: string
@ -61,13 +61,15 @@ import
{.pragma: myShallow.}
type
TSlotEnum = enum seEmpty, seFilled, seDeleted
TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
TTable* {.final, myShallow.}[A, B] = object ## generic hash table
data: TKeyValuePairSeq[A, B]
SlotEnum = enum seEmpty, seFilled, seDeleted
KeyValuePair[A, B] = tuple[slot: SlotEnum, key: A, val: B]
KeyValuePairSeq[A, B] = seq[KeyValuePair[A, B]]
Table* {.myShallow.}[A, B] = object ## generic hash table
data: KeyValuePairSeq[A, B]
counter: int
PTable*[A,B] = ref TTable[A, B]
TableRef*[A,B] = ref Table[A, B]
{.deprecated: [TTable: Table, PTable: TableRef].}
when not defined(nimhygiene):
{.pragma: dirty.}
@ -158,12 +160,12 @@ proc hasKey*[A, B](t: TTable[A, B], key: A): bool =
## returns true iff `key` is in the table `t`.
result = rawGet(t, key) >= 0
proc rawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B],
proc rawInsert[A, B](t: var TTable[A, B], data: var KeyValuePairSeq[A, B],
key: A, val: B) =
rawInsertImpl()
proc enlarge[A, B](t: var TTable[A, B]) =
var n: TKeyValuePairSeq[A, B]
var n: KeyValuePairSeq[A, B]
newSeq(n, len(t.data) * growthFactor)
for i in countup(0, high(t.data)):
if t.data[i].slot == seFilled: rawInsert(t, n, t.data[i].key, t.data[i].val)
@ -347,14 +349,16 @@ proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): PTable[C, B] =
# ------------------------------ ordered table ------------------------------
type
TOrderedKeyValuePair[A, B] = tuple[
slot: TSlotEnum, next: int, key: A, val: B]
TOrderedKeyValuePairSeq[A, B] = seq[TOrderedKeyValuePair[A, B]]
TOrderedTable* {.
final, myShallow.}[A, B] = object ## table that remembers insertion order
data: TOrderedKeyValuePairSeq[A, B]
OrderedKeyValuePair[A, B] = tuple[
slot: SlotEnum, next: int, key: A, val: B]
OrderedKeyValuePairSeq[A, B] = seq[OrderedKeyValuePair[A, B]]
OrderedTable* {.
myShallow.}[A, B] = object ## table that remembers insertion order
data: OrderedKeyValuePairSeq[A, B]
counter, first, last: int
POrderedTable*[A, B] = ref TOrderedTable[A, B]
OrderedTableRef*[A, B] = ref OrderedTable[A, B]
{.deprecated: [TOrderedTable: OrderedTable, POrderedTable: OrderedTableRef].}
proc len*[A, B](t: TOrderedTable[A, B]): int {.inline.} =
## returns the number of keys in `t`.
@ -608,11 +612,13 @@ proc sort*[A, B](t: POrderedTable[A, B],
# ------------------------------ count tables -------------------------------
type
TCountTable* {.final, myShallow.}[
CountTable* {.myShallow.}[
A] = object ## table that counts the number of each key
data: seq[tuple[key: A, val: int]]
counter: int
PCountTable*[A] = ref TCountTable[A]
CountTableRef*[A] = ref CountTable[A]
{.deprecated: [TCountTable: CountTable, PCountTable: CountTableRef].}
proc len*[A](t: TCountTable[A]): int =
## returns the number of keys in `t`.