時計回り/反時計回りの独立性に関する目的のプロパティを備えた非常に高速な(計算する)ハッシュの場合、ポイントの明確に定義された順序を見つけることに依存したくないでしょう。
これにより、ハッシュ結合操作が通勤する操作に制限されます。したがって、結合操作中は、方向に依存しないすべてのデータを分離しておく必要があります。
簡単な解決策は次のとおりです。
結合関数int->int->intが結合法則であると仮定すると、次のいずれかで始まります。
public static int combine(int h, int x)
{
return h * 31 + x;
}
public static int combine(int h, int x)
{
return h ^ x;
}
次に、次のことを実行できます。
public override int GetHashCode()
{
int x = 0;
int y = 0;
uint h = 0;
foreach (var point p in polgon)
{
x = combine(x, p.X);
y = combine(y, p.Y);
h++;
}
// simplified, unrolled Murmur2 hash for end stage
const uint m = 0x5bd1e995;
const int r = 24;
uint h = count;
uint k = ReinterpretInt32ToUInt32(x);
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
k = ReinterpretInt32ToUInt32(y);
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
// avalanche
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return ReinterpretUInt32ToInt32(h);
}
上記のコードを簡単にするためにこれに依存する
public unsafe uint ReinterpretInt32ToUInt32(int i)
{
return *((uint*) (void*) &i);
}
public unsafe int ReinterpretUInt32ToInt32(uint u)
{
return *((int*) (void*) &u);
}
これは、衝突回避の観点からは最良のハッシュではありませんが、計算が非常に高速である必要があり、ニーズに十分に対応できる場合があります。