[Mono-list] System.Drawing.Drawing2D

Stefan Maierhofer sm@dhm.at
Mon, 27 Aug 2001 13:33:02 +0200


On Monday 27 August 2001 11:43, you wrote:
> you write:
> > > using System.Runtime.InteropServices;
> > >
> > > // in your class
> > >     [StructLayout(LayoutKind.Explicit)]
> > >     internal struct BitConverter {
> > > 	[FieldOffset(0)] public float f;
> > > 	[FieldOffset(0)] public int i;
> > >     }
> > >     public override int GetHashCode()
> > >     {
> > >         BitConverter b;
> > >         // compiler is not smart
> > >         b.i = 0;
> > >         int h=0;
> > >         for(int i=0; i<4; i++) {
> > >             b.f = m[i];
> > >              h ^= m.i;
> > > 	}
> > >         return h;
> > >     }
> >
> > I think your implementation will work fine, so I just added it to
> > the Matrix
> > class and commited to CVS.
> >
> > I made one little adjustment:
> > Your method would return the same hash-code for all translations
> >  and scalings of form (x,y) where x == y, so I use h ^= b.i >> i
> >  instead of h ^= b.i which solves the problem.
>
> mhh, good remark and idea.
> one improvment could again be made, i believe.
> h ^= b.i >>i; each compoent contribute less and less....
>
> why not
> h ^= (b.i >> i) | (b.i << (4-i));
> it is a xor operation combined with a bitwise cycling instead of
> bitwise shifting.

At first I thought that my shifting operation would cancel out small values
i.e.  (3 >> 4) == (7 >> 5)
but this not the case because we are interpreting IEEE single precision
floating point representations as ints. Since IEEE floating point
representation stores the exponent in bits 23-30 (bit 31 is sign, and bits
0-22 mantissa) no problems arise here (since even for small numbers bits will
be set to 1 in the exponent and therefore cannot be "shifted out" (because
maximum shift is 5 bits)
so IMHO it will not matter if some components contribute "less"

example:
Matrix a = new Matrix(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000001f);
Matrix b = new Matrix(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0000001f);

hashcode a: 28062141
hashcode b: 27178492

On the other hand I think your approach (cycling) might distribute hash-codes
even more uniformly than shifting (at the expense of 30 operations in
contrast to 12 operations for h ^= b.i >> i) - a classic trade-off situation

Stefan.