private static ImmutableDictionary <TKey, TValue> From(TKey key, TValue value, uint hash, int shift, TKey key2, TValue value2) { if (hash == (uint)key2.GetHashCode() && key.Equals(key2)) { // TODO lift hash and key equlity (update) to above layer var newValues = new ValueNode1 <TKey, TValue>(key, value); return(new BitMapNode <TKey, TValue, ValueNode1 <TKey, TValue> >(0, new ImmutableDictionary <TKey, TValue> [0], 1U << (int)((hash >> shift) & Mask), newValues)); } else if (hash == (uint)key2.GetHashCode()) { // TODO handle collisions, at what shift level? throw new NotImplementedException(); } else { var bit1 = 1U << (int)(((uint)key2.GetHashCode() >> shift) & Mask); var bit2 = 1U << (int)((hash >> shift) & Mask); if (bit1 < bit2) { var newValues = new ValueNode2 <TKey, TValue>(key2, value2, key, value); return(new BitMapNode <TKey, TValue, ValueNode2 <TKey, TValue> >(0, new ImmutableDictionary <TKey, TValue> [0], bit1 | bit2, newValues)); } else if (bit1 > bit2) { var newValues = new ValueNode2 <TKey, TValue>(key, value, key2, value2); return(new BitMapNode <TKey, TValue, ValueNode2 <TKey, TValue> >(0, new ImmutableDictionary <TKey, TValue> [0], bit1 | bit2, newValues)); } else { var newNodes = BitMapNode <TKey, TValue, TValues> .From(key, value, hash, shift + Shift, key2, value2); return(new BitMapNode <TKey, TValue, ValueNode0 <TKey, TValue> >(bit1, new [] { newNodes }, 0, new ValueNode0 <TKey, TValue>())); } } }
internal override ImmutableDictionary <TKey, TValue> Add(TKey key, TValue value, uint hash, int shift) { var bit = 1U << (int)((hash >> shift) & Mask); if ((_bitmapNodes & bit) != 0) { var newNodes = new ImmutableDictionary <TKey, TValue> [_nodes.Length]; Array.Copy(_nodes, newNodes, _nodes.Length); var index = Popcnt.PopCount(_bitmapNodes & (bit - 1)); newNodes[index] = _nodes[index].Add(key, value, hash, shift + Shift); return(new BitMapNode <TKey, TValue, TValues>(_bitmapNodes, newNodes, _bitmapValues, _values)); } else if ((_bitmapValues & bit) != 0) { // TODO collisions and same value var newNodes = new ImmutableDictionary <TKey, TValue> [_nodes.Length + 1]; var index = Popcnt.PopCount(_bitmapNodes & (bit - 1)); Array.Copy(_nodes, newNodes, index); Array.Copy(_nodes, index, newNodes, index + 1, _nodes.Length - index); var indexValues = Popcnt.PopCount(_bitmapValues & (bit - 1)); var key2 = _values.GetKey(indexValues); var value2 = _values.GetValue(indexValues); newNodes[index] = BitMapNode <TKey, TValue, TValues> .From(key, value, hash, shift + Shift, key2, value2); return(_values.Shrink(_bitmapNodes | bit, newNodes, _bitmapValues ^ bit, (uint)indexValues)); } else { var index = (uint)Popcnt.PopCount(_bitmapValues & (bit - 1)); return(_values.Add(key, value, _bitmapNodes, _nodes, _bitmapValues | bit, index)); } }