big rename
This commit is contained in:
parent
15a7bcc89f
commit
11b6958755
98 changed files with 2491 additions and 2341 deletions
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue