From 561a683230dce671c7cbfc166ffa79cc5a46b8b5 Mon Sep 17 00:00:00 2001 From: Sander van den Bosch Date: Mon, 31 Mar 2025 16:33:48 +0200 Subject: [PATCH] Added .hash() functions for vectors (#2043) * Added .hash() functions for vectors * Update test to a non-zero sized vector * Changed vector hash functions to hash the underlying bytes in a char slice, the same approch is used for arrays * Added test for hashed * Updated formatting to be consistant with C3 code style * Formatting, use "self" --------- Co-authored-by: Christoffer Lerno --- lib/std/core/builtin.c3 | 63 ++++++++++++++++++++++----- test/unit/stdlib/core/builtintests.c3 | 63 ++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 12 deletions(-) diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index c2267dad3..98db25e27 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -431,22 +431,63 @@ macro @generic_hash(value) return h; } -macro uint int.hash(int i) => @generic_hash(i); -macro uint uint.hash(uint i) => @generic_hash(i); -macro uint short.hash(short s) => @generic_hash(s); -macro uint ushort.hash(ushort s) => @generic_hash(s); -macro uint char.hash(char c) => @generic_hash(c); -macro uint ichar.hash(ichar c) => @generic_hash(c); -macro uint long.hash(long i) => @generic_hash(i); -macro uint ulong.hash(ulong i) => @generic_hash(i); -macro uint int128.hash(int128 i) => @generic_hash(i); -macro uint uint128.hash(uint128 i) => @generic_hash(i); -macro uint bool.hash(bool b) => @generic_hash(b); + +macro uint int128.hash(self) => @generic_hash(self); +macro uint uint128.hash(self) => @generic_hash(self); +macro uint long.hash(self) => @generic_hash(self); +macro uint ulong.hash(self) => @generic_hash(self); +macro uint int.hash(self) => @generic_hash(self); +macro uint uint.hash(self) => @generic_hash(self); +macro uint short.hash(self) => @generic_hash(self); +macro uint ushort.hash(self) => @generic_hash(self); +macro uint ichar.hash(self) => @generic_hash(self); +macro uint char.hash(self) => @generic_hash(self); +macro uint bool.hash(self) => @generic_hash(self); + +macro uint int128[*].hash(&self) => hash_array(self); +macro uint uint128[*].hash(&self) => hash_array(self); +macro uint long[*].hash(&self) => hash_array(self); +macro uint ulong[*].hash(&self) => hash_array(self); +macro uint int[*].hash(&self) => hash_array(self); +macro uint uint[*].hash(&self) => hash_array(self); +macro uint short[*].hash(&self) => hash_array(self); +macro uint ushort[*].hash(&self) => hash_array(self); +macro uint char[*].hash(&self) => hash_array(self); +macro uint ichar[*].hash(&self) => hash_array(self); +macro uint bool[*].hash(&self) => hash_array(self); + +macro uint int128[<*>].hash(self) => hash_vec(self); +macro uint uint128[<*>].hash(self) => hash_vec(self); +macro uint long[<*>].hash(self) => hash_vec(self); +macro uint ulong[<*>].hash(self) => hash_vec(self); +macro uint int[<*>].hash(self) => hash_vec(self); +macro uint uint[<*>].hash(self) => hash_vec(self); +macro uint short[<*>].hash(self) => hash_vec(self); +macro uint ushort[<*>].hash(self) => hash_vec(self); +macro uint char[<*>].hash(self) => hash_vec(self); +macro uint ichar[<*>].hash(self) => hash_vec(self); +macro uint bool[<*>].hash(self) => hash_vec(self); + macro uint typeid.hash(typeid t) => @generic_hash(((ulong)(uptr)t)); macro uint String.hash(String c) => (uint)fnv32a::hash(c); macro uint char[].hash(char[] c) => (uint)fnv32a::hash(c); macro uint void*.hash(void* ptr) => @generic_hash(((ulong)(uptr)ptr)); +<* + @require @typekind(array_ptr) == POINTER &&& @typekind(*array_ptr) == ARRAY +*> +macro uint hash_array(array_ptr) @local +{ + return (uint)fnv32a::hash(((char*)array_ptr)[:$sizeof(*array_ptr)]); +} + +<* + @require @typekind(vec) == VECTOR +*> +macro uint hash_vec(vec) @local +{ + return (uint)fnv32a::hash(((char*)&&vec)[:$sizeof(vec.len * $typeof(vec).inner.sizeof)]); +} const MAX_FRAMEADDRESS = 128; <* diff --git a/test/unit/stdlib/core/builtintests.c3 b/test/unit/stdlib/core/builtintests.c3 index 24e553be3..a0fc7800b 100644 --- a/test/unit/stdlib/core/builtintests.c3 +++ b/test/unit/stdlib/core/builtintests.c3 @@ -63,17 +63,78 @@ fn void test_prefetch() fn void test_hash() { (char){}.hash(); + (char[<100>]){}.hash(); + (char[100]){}.hash(); (ichar){}.hash(); + (ichar[<100>]){}.hash(); + (ichar[100]){}.hash(); (short){}.hash(); + (short[<100>]){}.hash(); + (short[100]){}.hash(); (ushort){}.hash(); + (ushort[<100>]){}.hash(); + (ushort[100]){}.hash(); (int){}.hash(); + (int[<100>]){}.hash(); + (int[100]){}.hash(); (uint){}.hash(); + (uint[<100>]){}.hash(); + (uint[100]){}.hash(); (long){}.hash(); + (long[<100>]){}.hash(); + (long[100]){}.hash(); (ulong){}.hash(); + (ulong[<100>]){}.hash(); + (ulong[100]){}.hash(); (int128){}.hash(); + (int128[<100>]){}.hash(); + (int128[100]){}.hash(); (uint128){}.hash(); + (uint128[<100>]){}.hash(); + (uint128[100]){}.hash(); + (bool){}.hash(); + (bool[<100>]){}.hash(); + (bool[100]){}.hash(); String x = "abc"; char[] y = "abc"; assert(x.hash() == y.hash()); assert(int.typeid.hash()); -} \ No newline at end of file +} + +fn void test_hash_repeat() +{ + assert((char){}.hash() == (char){}.hash()); + assert((char[<100>]){}.hash() == (char[<100>]){}.hash()); + assert((char[100]){}.hash() == (char[100]){}.hash()); + assert((ichar){}.hash() == (ichar){}.hash()); + assert((ichar[<100>]){}.hash() == (ichar[<100>]){}.hash()); + assert((ichar[100]){}.hash() == (ichar[100]){}.hash()); + assert((short){}.hash() == (short){}.hash()); + assert((short[<100>]){}.hash() == (short[<100>]){}.hash()); + assert((short[100]){}.hash() == (short[100]){}.hash()); + assert((ushort){}.hash() == (ushort){}.hash()); + assert((ushort[<100>]){}.hash() == (ushort[<100>]){}.hash()); + assert((ushort[100]){}.hash() == (ushort[100]){}.hash()); + assert((int){}.hash() == (int){}.hash()); + assert((int[<100>]){}.hash() == (int[<100>]){}.hash()); + assert((int[100]){}.hash() == (int[100]){}.hash()); + assert((uint){}.hash() == (uint){}.hash()); + assert((uint[<100>]){}.hash() == (uint[<100>]){}.hash()); + assert((uint[100]){}.hash() == (uint[100]){}.hash()); + assert((long){}.hash() == (long){}.hash()); + assert((long[<100>]){}.hash() == (long[<100>]){}.hash()); + assert((long[100]){}.hash() == (long[100]){}.hash()); + assert((ulong){}.hash() == (ulong){}.hash()); + assert((ulong[<100>]){}.hash() == (ulong[<100>]){}.hash()); + assert((ulong[100]){}.hash() == (ulong[100]){}.hash()); + assert((int128){}.hash() == (int128){}.hash()); + assert((int128[<100>]){}.hash() == (int128[<100>]){}.hash()); + assert((int128[100]){}.hash() == (int128[100]){}.hash()); + assert((uint128){}.hash() == (uint128){}.hash()); + assert((uint128[<100>]){}.hash() == (uint128[<100>]){}.hash()); + assert((uint128[100]){}.hash() == (uint128[100]){}.hash()); + assert((bool){}.hash() == (bool){}.hash()); + assert((bool[<100>]){}.hash() == (bool[<100>]){}.hash()); + assert((bool[100]){}.hash() == (bool[100]){}.hash()); + assert(int.typeid.hash() == int.typeid.hash()); +}