summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorNycto <James@RoundEights.com>2015-04-24 08:18:24 -0700
committerNycto <James@RoundEights.com>2015-04-24 08:25:58 -0700
commit4f88238761e91192aab9da734c132268a4608284 (patch)
treec625949f35a68e55edaac4bb61c70faa649eeced
parent6ca38472a13840906d6f113eb92c11a25db49224 (diff)
downloadNim-4f88238761e91192aab9da734c132268a4608284.tar.gz
Fix floats in tuples in HashSets
Previously, the added tests would fail to compile with
errors complaining that 'hash(float)' didn't exist
-rw-r--r--lib/pure/hashes.nim66
-rw-r--r--tests/collections/tsets.nim48
2 files changed, 71 insertions, 43 deletions
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index a16342d44..2ce8ac796 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -37,29 +37,29 @@
 ##    h = h !& hash(x.bar)
 ##    result = !$h
 
-import 
+import
   strutils
 
-type 
-  THash* = int ## a hash value; hash tables using these values should 
+type
+  THash* = int ## a hash value; hash tables using these values should
                ## always have a size of a power of two and can use the ``and``
                ## operator instead of ``mod`` for truncation of the hash value.
 
-proc `!&`*(h: THash, val: int): THash {.inline.} = 
+proc `!&`*(h: THash, val: int): THash {.inline.} =
   ## mixes a hash value `h` with `val` to produce a new hash value. This is
   ## only needed if you need to implement a hash proc for a new datatype.
   result = h +% val
   result = result +% result shl 10
   result = result xor (result shr 6)
 
-proc `!$`*(h: THash): THash {.inline.} = 
+proc `!$`*(h: THash): THash {.inline.} =
   ## finishes the computation of the hash value. This is
   ## only needed if you need to implement a hash proc for a new datatype.
   result = h +% h shl 3
   result = result xor (result shr 11)
   result = result +% result shl 15
 
-proc hashData*(data: pointer, size: int): THash = 
+proc hashData*(data: pointer, size: int): THash =
   ## hashes an array of bytes of size `size`
   var h: THash = 0
   when defined(js):
@@ -69,7 +69,7 @@ proc hashData*(data: pointer, size: int): THash =
     var p = cast[cstring](data)
   var i = 0
   var s = size
-  while s > 0: 
+  while s > 0:
     h = h !& ord(p[i])
     inc(i)
     dec(s)
@@ -78,7 +78,7 @@ proc hashData*(data: pointer, size: int): THash =
 when defined(js):
   var objectID = 0
 
-proc hash*(x: pointer): THash {.inline.} = 
+proc hash*(x: pointer): THash {.inline.} =
   ## efficient hashing of pointers
   when defined(js):
     asm """
@@ -93,7 +93,7 @@ proc hash*(x: pointer): THash {.inline.} =
     """
   else:
     result = (cast[THash](x)) shr 3 # skip the alignment
-  
+
 when not defined(booting):
   proc hash*[T: proc](x: T): THash {.inline.} =
     ## efficient hashing of proc vars; closures are supported too.
@@ -101,58 +101,65 @@ when not defined(booting):
       result = hash(rawProc(x)) !& hash(rawEnv(x))
     else:
       result = hash(pointer(x))
-  
-proc hash*(x: int): THash {.inline.} = 
+
+proc hash*(x: int): THash {.inline.} =
   ## efficient hashing of integers
   result = x
 
-proc hash*(x: int64): THash {.inline.} = 
+proc hash*(x: int64): THash {.inline.} =
   ## efficient hashing of integers
   result = toU32(x)
 
-proc hash*(x: char): THash {.inline.} = 
+proc hash*(x: char): THash {.inline.} =
   ## efficient hashing of characters
   result = ord(x)
 
-proc hash*(x: string): THash = 
+proc hash*(x: string): THash =
   ## efficient hashing of strings
   var h: THash = 0
-  for i in 0..x.len-1: 
+  for i in 0..x.len-1:
     h = h !& ord(x[i])
   result = !$h
-  
-proc hashIgnoreStyle*(x: string): THash = 
+
+proc hashIgnoreStyle*(x: string): THash =
   ## efficient hashing of strings; style is ignored
   var h: THash = 0
-  for i in 0..x.len-1: 
+  for i in 0..x.len-1:
     var c = x[i]
-    if c == '_': 
+    if c == '_':
       continue                # skip _
-    if c in {'A'..'Z'}: 
+    if c in {'A'..'Z'}:
       c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
     h = h !& ord(c)
   result = !$h
 
-proc hashIgnoreCase*(x: string): THash = 
+proc hashIgnoreCase*(x: string): THash =
   ## efficient hashing of strings; case is ignored
   var h: THash = 0
-  for i in 0..x.len-1: 
+  for i in 0..x.len-1:
     var c = x[i]
-    if c in {'A'..'Z'}: 
+    if c in {'A'..'Z'}:
       c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
     h = h !& ord(c)
   result = !$h
-  
-proc hash*[T: tuple](x: T): THash = 
-  ## efficient hashing of tuples.
-  for f in fields(x):
-    result = result !& hash(f)
-  result = !$result
 
 proc hash*(x: float): THash {.inline.} =
   var y = x + 1.0
   result = cast[ptr THash](addr(y))[]
 
+
+# Forward declarations before methods that hash containers. This allows
+# containers to contain other containers
+proc hash*[A](x: openArray[A]): THash
+proc hash*[A](x: set[A]): THash
+
+
+proc hash*[T: tuple](x: T): THash =
+  ## efficient hashing of tuples.
+  for f in fields(x):
+    result = result !& hash(f)
+  result = !$result
+
 proc hash*[A](x: openArray[A]): THash =
   for it in items(x): result = result !& hash(it)
   result = !$result
@@ -160,3 +167,4 @@ proc hash*[A](x: openArray[A]): THash =
 proc hash*[A](x: set[A]): THash =
   for it in items(x): result = result !& hash(it)
   result = !$result
+
diff --git a/tests/collections/tsets.nim b/tests/collections/tsets.nim
index 656c5b3f2..a5bbe8dbd 100644
--- a/tests/collections/tsets.nim
+++ b/tests/collections/tsets.nim
@@ -1,17 +1,37 @@
-discard """
-  output: '''true
-true'''
-"""
-
 import sets
-var
-  a = initSet[int]()
-  b = initSet[int]()
-  c = initSet[string]()
 
-for i in 0..5: a.incl(i)
-for i in 1..6: b.incl(i)
-for i in 0..5: c.incl($i)
+block setEquality:
+  var
+    a = initSet[int]()
+    b = initSet[int]()
+    c = initSet[string]()
+
+  for i in 0..5: a.incl(i)
+  for i in 1..6: b.incl(i)
+  for i in 0..5: c.incl($i)
+
+  doAssert map(a, proc(x: int): int = x + 1) == b
+  doAssert map(a, proc(x: int): string = $x) == c
+
+
+block setsContainingTuples:
+  var set = initSet[tuple[i: int, i64: int64, f: float]]()
+  set.incl( (i: 123, i64: 123'i64, f: 3.14) )
+  doAssert set.contains( (i: 123, i64: 123'i64, f: 3.14) )
+  doAssert( not set.contains( (i: 456, i64: 789'i64, f: 2.78) ) )
+
+
+block setWithTuplesWithSeqs:
+  var s = initSet[tuple[s: seq[int]]]()
+  s.incl( (s: @[1, 2, 3]) )
+  doAssert s.contains( (s: @[1, 2, 3]) )
+  doAssert( not s.contains((s: @[4, 5, 6])) )
+
+
+block setWithSequences:
+  var s = initSet[seq[int]]()
+  s.incl( @[1, 2, 3] )
+  doAssert s.contains(@[1, 2, 3])
+  doAssert( not s.contains(@[4, 5, 6]) )
+
 
-echo map(a, proc(x: int): int = x + 1) == b
-echo map(a, proc(x: int): string = $x) == c