@@ -1270,6 +1270,43 @@ public ref TEntry AddOrGetEntryRef(K key, out bool found)
12701270 return ref _entries . AddKeyAndGetEntryRef ( key , 0 ) ; // add the new key to the entries with the 0 index in the entries
12711271 }
12721272
1273+ /*
1274+ Insertion step by step:
1275+
1276+ 1. Initially the map is empty. Its capacity mask is 7:
1277+
1278+ Index: 0 1 2 3 4 5 6 7
1279+ Hash: [0] [0] [0] [0] [0] [0] [0] [0]
1280+
1281+ 2. Insert that key A with the hash 13, which is 0b0011_0101. 13 & 7 Mask = 5, so the index is 5.
1282+
1283+ Index: 0 1 2 3 4 5 6 7
1284+ Hash: [0] [0] [0] [0] [0] [13] [0] [0]
1285+ Probe: 1A
1286+
1287+ 3. Insert that key B with the hash 5, which is 0b0000_1011. 5 & 7 Mask = 5, so the index is again 5.
1288+
1289+ Index: 0 1 2 3 4 5 6 7
1290+ Hash: [0] [0] [0] [0] [0] [13] [5] [0]
1291+ Probe 1A 2B
1292+
1293+ 4. Insert that key C with the hash 7, which is 0b0010_0101. 7 & 7 Mask = 7, so the index is 7.
1294+
1295+ Index: 0 1 2 3 4 5 6 7
1296+ Hash: [0] [0] [0] [0] [0] [13] [5] [7]
1297+ Probe: 1A 2B 1C
1298+
1299+ 5. Insert that key D with the hash 21, which is 0b0101_0101. 21 & 7 Mask = 5, so the index is again again 5.
1300+
1301+ Index: 0 1 2 3 4 5 6 7
1302+ Hash: [7] [0] [0] [0] [0] [13] [5] [21]
1303+ Probe: 2C 1A 2B 3D
1304+ // todo: @perf @wip just an idea
1305+ 5 (with padding):
1306+ Index: 0 1 2 3 4 5 6 7 | 8 9 10 11
1307+ Hash: [7] [0] [0] [0] [0] [13] [5] [21]| [7] [0] [0] [0]
1308+ Probe: 2C 1A 2B 3D | 2C
1309+ */
12731310 [ UnscopedRef ]
12741311 private ref TEntry AddSureAbsentDefaultAndGetRefInEntries ( K key )
12751312 {
@@ -1405,13 +1442,53 @@ internal ref TEntry TryGetRefInEntries(K key, out bool found)
14051442 return ref RefTools < TEntry > . GetNullRef ( ) ;
14061443 }
14071444
1408- /// <summary>Lookups for the stored entry by key. Returns the ref to the found entry or the null ref</summary>
1445+ // todo: @wip
1446+ [ UnscopedRef ]
1447+ [ MethodImpl ( ( MethodImplOptions ) 256 ) ]
1448+ internal ref TEntry TryGetRefInEntries2 ( K key , out bool found )
1449+ {
1450+ var hash = default ( TEq ) . GetHashCode ( key ) ;
1451+
1452+ var indexMask = ( 1 << _capacityBitShift ) - 1 ;
1453+ var hashMiddleMask = HashAndIndexMask & ~ indexMask ;
1454+ var hashMiddle = hash & hashMiddleMask ;
1455+ var hashIndex = hash & indexMask ;
1456+
1457+ #if NET7_0_OR_GREATER
1458+ ref var hashesAndIndexes = ref MemoryMarshal . GetArrayDataReference ( _packedHashesAndIndexes ) ;
1459+ #else
1460+ var hashesAndIndexes = _packedHashesAndIndexes ;
1461+ #endif
1462+
1463+ var h = hashesAndIndexes . GetSurePresentItem ( hashIndex ) ;
1464+
1465+ // 1. Skip over hashes with the bigger and equal probes. The hashes with bigger probes overlapping from the earlier ideal positions
1466+ var probes = 1 ;
1467+
1468+ while ( ( h >>> ProbeCountShift ) >= probes )
1469+ {
1470+ // 2. For the equal probes check for equality the hash middle part, then check the entry
1471+ if ( ( ( h >>> ProbeCountShift ) == probes ) & ( ( h & hashMiddleMask ) == hashMiddle ) )
1472+ {
1473+ ref var e = ref GetSurePresentEntryRef ( h & indexMask ) ;
1474+ if ( found = default ( TEq ) . Equals ( e . Key , key ) )
1475+ return ref e ;
1476+ }
1477+
1478+ h = hashesAndIndexes . GetSurePresentItem ( ++ hashIndex & indexMask ) ;
1479+ ++ probes ;
1480+ }
1481+
1482+ found = false ;
1483+ return ref RefTools < TEntry > . GetNullRef ( ) ;
1484+ }
1485+
1486+ /// <summary>Lookup for the stored entry by key. Returns the ref to the found entry or the null ref</summary>
14091487 [ UnscopedRef ]
14101488 public ref TEntry TryGetEntryRef ( K key , out bool found )
14111489 {
14121490 if ( _count > StackEntries . Capacity )
14131491 return ref TryGetRefInEntries ( key , out found ) ;
1414-
14151492 return ref StackEntries . TryGetEntryRef ( ref _stackHashes , _count , key , out found ,
14161493 default ( TEq ) , default ( TStackCap ) , default ( Use < TEntry > ) ) ;
14171494 }
0 commit comments