Skip to content

Commit

Permalink
Fix order issue with ImmSet and ImmDict hashcodes.
Browse files Browse the repository at this point in the history
  • Loading branch information
oconnor0 committed Oct 8, 2024
1 parent 3c6b129 commit 88fff47
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 7 deletions.
11 changes: 11 additions & 0 deletions Xledger.Collections.Test/TestImmDict.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ public void TestContains() {
}
}

[Fact]
public void TestHashCode() {
var items = Enumerable.Range(-100, 1_000).ToDictionary(i => i.ToString(), i => (i * i).ToString() + "A");
var imm = items.ToImmDict();
var ritems = Enumerable.Range(-100, 1_000).Reverse().ToDictionary(i => i.ToString(), i => (i * i).ToString() + "A");
var two = ritems.ToImmDict();

Assert.Equal(imm.GetHashCode(), two.GetHashCode());
Assert.True(imm == two);
}

[Fact]
public void TestNoOps() {
var imm = ImmDict.Of((7, 6), (5, 4));
Expand Down
2 changes: 1 addition & 1 deletion Xledger.Collections/ImmArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public bool Equals(ImmArray<T> other) {
if (this.data.Length != other.data.Length) {
return false;
}
if (this.hashComputed && other.hashComputed && GetHashCode() != other.GetHashCode()) {
if (this.hashComputed && other.hashComputed && this.hash != other.hash) {
return false;
}

Expand Down
18 changes: 14 additions & 4 deletions Xledger.Collections/ImmDict.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ public bool Equals(ImmDict<K, V> other) {
if (this.data.Count != other.data.Count) {
return false;
}
if (this.hashComputed && other.hashComputed && this.hash != other.hash) {
return false;
}

foreach (var kvp in this.data) {
if (!other.data.TryGetValue(kvp.Key, out var otherValue)
Expand All @@ -88,11 +91,18 @@ public bool Equals(ImmDict<K, V> other) {
public override int GetHashCode() {
if (!this.hashComputed) {
var hashCode = -1487460045;
var hashes = new int[this.data.Count];
var i = 0;
foreach (var kvp in this) {
var next = EqualityComparer<K>.Default.GetHashCode(kvp.Key);
hashCode = hashCode * -1521134295 + next;
next = EqualityComparer<V>.Default.GetHashCode(kvp.Value);
hashCode = hashCode * -1521134295 + next;
var next = 524287;
next = next * -1521134295 + EqualityComparer<K>.Default.GetHashCode(kvp.Key);
next = next * -1521134295 + EqualityComparer<V>.Default.GetHashCode(kvp.Value);
hashes[i] = next;
++i;
}
Array.Sort(hashes);
for (i = 0; i < this.data.Count; ++i) {
hashCode = hashCode * -1521134295 + hashes[i];
}
this.hash = hashCode;
this.hashComputed = true;
Expand Down
13 changes: 11 additions & 2 deletions Xledger.Collections/ImmSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ public bool Equals(ImmSet<T> other) {
if (this.data.Count != other.data.Count) {
return false;
}
if (this.hashComputed && other.hashComputed && this.hash != other.hash) {
return false;
}

return this.data.SetEquals(other.data);
}
Expand All @@ -100,9 +103,15 @@ public IEnumerator<T> GetEnumerator() {
public override int GetHashCode() {
if (!this.hashComputed) {
var hashCode = 358481680;
var hashes = new int[this.data.Count];
var i = 0;
foreach (var item in this) {
var next = EqualityComparer<T>.Default.GetHashCode(item);
hashCode = hashCode * -1521134295 + next;
hashes[i] = EqualityComparer<T>.Default.GetHashCode(item);
++i;
}
Array.Sort(hashes);
for (i = 0; i < this.data.Count; ++i) {
hashCode = hashCode * -1521134295 + hashes[i];
}
this.hash = hashCode;
this.hashComputed = true;
Expand Down

0 comments on commit 88fff47

Please sign in to comment.