class · System

Dictionary<K, V>

public class Dictionary<K : IHashable<K>, V>
Kind
class
Namespace
System
Assembly
System.Core
Access
public
Source file
Dictionary.ant

Type parameters

NameConstraints
KIHashable<K>
Vany type

Inheritance

Base classes
Any Dictionary<K, V>

Constructors

new()
#

Properties

i32 Count { get; }
#

read-only

bool IsEmpty { get; }
#

read-only

i32 Slots { get; }
#

read-only

Methods

Set(K key, V value)
#

Gives key the value value (adding it, or replacing its value).

Get(K key) : V
#

The value of key; a KeyNotFoundError when there is none.

At(K key) : V
#

map[key].

SetAt(K key, V value)
#

map[key] = value.

TryGet(K key, V fallback) : V
#

The value of key, or fallback when there is none.

ContainsKey(K key) : bool
#
Remove(K key) : bool
#

Takes key out; false when it was not there.

Clear()
#
Keys() : List<K>
#

The keys, in the table's order.

Iterator() : DictionaryIterator<K, V>
#

loop (KeyValuePair<K, V> pair in map), in the table's order.

Holds(i32 slot) : bool
#

The slots (for the iterator).

KeyAt(i32 slot) : K
#
ValueAt(i32 slot) : V
#

Private and internal members (12)

K[] keys
#

private

V[] values
#

private

u32[] tags
#

private

Per slot: 0 empty, 2 removed (probing goes on past it), else (odd) the top bits of the key's mixed hash: probing compares them before it looks at a key, and resizing places pairs without hashing their keys again.

i32 count
#

private

i32 used
#

private

i32 bits
#

private

The table has 2^bits slots.

static Tag(u64 hash) : u32
#

private static

A key's tag: the top 32 bits of its hash × 2^64/φ (Fibonacci hashing), made odd.

Home(u32 tag) : i32
#

private

The first slot to look at for a tag (its top bits).

Find(K key) : i32
#

private

The slot holding key, or -1.

Free(u32 tag) : i32
#

private

A slot for a new pair with this tag (empty or removed).

Resize(i32 newBits)
#

private

Rebuilds the table with 2^newBits slots.

Add(K key, V value, u32 tag)
#

private

Adds a pair whose key is not in the table.

Inherited members (5)

Source

Dictionary<K, V> as Antril, decompiled from its Larva HIR.

System.Dictionary.ant
// System.Dictionary — System.Core (decompiled from Larva HIR)

into namespace System
{
	public class Dictionary<K : IHashable<K>, V>
	{
		K[] keys;
		V[] values;

		/// Per slot: 0 empty, 2 removed (probing goes on past it), else (odd) the top bits of the key's mixed hash: probing
		/// compares them before it looks at a key, and resizing places pairs without hashing their keys again.
		u32[] tags;
		i32 count;
		i32 used;

		/// The table has 2^bits slots.
		i32 bits;

		/// A key's tag: the top 32 bits of its hash × 2^64/φ (Fibonacci hashing), made odd.
		static Tag(u64 hash) : u32 => (u32)(hash * 11400714819323198485 >> 32) | 1;

		/// The first slot to look at for a tag (its top bits).
		Home(u32 tag) : i32 => (i32)(tag >> (u32)(32 - bits));

		/// The slot holding `key`, or -1.
		Find(K key) : i32
		{
			u32 tag = Tag(key.Hash());
			i32 mask = tags.Length - 1;
			i32 slot = Home(tag);
			loop (true)
			{
				u32 at = tags[slot];
				if (at == 0)
					return -1;
				if (at == tag && keys[slot].Equals(key))
					return slot;
				slot = slot + 1 & mask;
			}
		}

		/// A slot for a new pair with this tag (empty or removed).
		Free(u32 tag) : i32
		{
			i32 mask = tags.Length - 1;
			i32 slot = Home(tag);
			loop ((tags[slot] & 1) == 1)
				slot = slot + 1 & mask;
			return slot;
		}

		/// Rebuilds the table with 2^newBits slots.
		[NoInline]
		Resize(i32 newBits)
		{
			K[] oldKeys = keys;
			V[] oldValues = values;
			u32[] oldTags = tags;
			bits = newBits;
			i32 size = 1 << newBits;
			keys = new K[size];
			values = new V[size];
			tags = new u32[size];
			used = count;
			loop (i32 i = 0..oldTags.Length)
			{
				u32 tag = oldTags[i];
				if ((tag & 1) == 1)
				{
					i32 slot = Free(tag);
					keys[slot] = oldKeys[i];
					values[slot] = oldValues[i];
					tags[slot] = tag;
				}
			}
		}

		/// Adds a pair whose key is not in the table.
		Add(K key, V value, u32 tag)
		{
			if ((used + 1) * 4 > tags.Length * 3)
				Resize(count * 2 + 2 > tags.Length ? bits + 1 : bits);
			i32 slot = Free(tag);
			if (tags[slot] == 0)
				used++;
			keys[slot] = key;
			values[slot] = value;
			tags[slot] = tag;
			count++;
		}

		public:
			new()
			{
				bits = 3;
				keys = new K[8];
				values = new V[8];
				tags = new u32[8];
			}

			/// Gives `key` the value `value` (adding it, or replacing its value).
			Set(K key, V value)
			{
				i32 slot = Find(key);
				if (slot >= 0)
					values[slot] = value;
				else
					Add(key, value, Tag(key.Hash()));
			}

			/// The value of `key`; a KeyNotFoundError when there is none.
			Get(K key) : V
			{
				i32 slot = Find(key);
				if (slot < 0)
					Fail.KeyNotFound();
				return values[slot];
			}

			/// `map[key]`.
			At(K key) : V => Get(key);

			/// `map[key] = value`.
			SetAt(K key, V value)
			{
				Set(key, value);
			}

			/// The value of `key`, or `fallback` when there is none.
			TryGet(K key, V fallback) : V
			{
				i32 slot = Find(key);
				return slot < 0 ? fallback : values[slot];
			}

			ContainsKey(K key) : bool => Find(key) >= 0;

			/// Takes `key` out; false when it was not there.
			Remove(K key) : bool
			{
				i32 slot = Find(key);
				if (slot < 0)
					return false;
				tags[slot] = 2;
				count--;
				return true;
			}

			Clear()
			{
				loop (i32 i = 0..tags.Length)
					tags[i] = 0;
				count = 0;
				used = 0;
			}

			/// The keys, in the table's order.
			Keys() : List<K>
			{
				List<K> list = new List<K>(count);
				loop (i32 i = 0..tags.Length)
				{
					if ((tags[i] & 1) == 1)
						list.Add(keys[i]);
				}
				return list;
			}

			/// `loop (KeyValuePair<K, V> pair in map)`, in the table's order.
			Iterator() : DictionaryIterator<K, V> => new DictionaryIterator<K, V>(this);

			/// The slots (for the iterator).
			Holds(i32 slot) : bool => (tags[slot] & 1) == 1;

			KeyAt(i32 slot) : K => keys[slot];

			ValueAt(i32 slot) : V => values[slot];

			i32 Count
			{
				get => count;
			}

			bool IsEmpty
			{
				get => count == 0;
			}

			i32 Slots
			{
				get => tags.Length;
			}
	}
}
Esc