[Mono-dev] Optimising code breaks maths

Alan McGovern alan.mcgovern at gmail.com
Sun Jan 28 06:41:35 EST 2007


Hi,

While NUniting for Mono.XNA i came across a problem i have no real idea how
to fix. The problem appears when i compile in "Release" mode with
optimisations enabled. For example, when i coded a method which calculates
the 8 corners of a cube when given the 6 sides of the cube, i get completely
different answers as my result when i compile in release as opposed to
debug.

What i assume is happening is that the math routines are being optimised,
which is resulting in the floating point multiplications and divisions being
moved around thus making the calculation more inaccurate. From my NUnit
tests debug mode gives me a result of ~0.19 whereas Release mode would give
a result of 0.125. That's a 30% difference!

Does anyone have any advice on how to code the methods to reduce the impact
of the optimiser? Or should i just disable optimisations altogether,
although I'd assume that wouldn't be advisable for performance reasons.

For example, this is what is currently in SVN:

        *private* *static* Vector3 IntersectionPoint(*ref* Plane a,
*ref* Plane b, *ref* Plane c)
        {
            Vector3 v1, v2, v3;
            *float* f = -Vector3.Dot(a.Normal, Vector3.Cross(b.Normal,
c.Normal));

            v1 = (a.D * Vector3.Cross(b.Normal, c.Normal)) / f;
            v2 = (b.D * Vector3.Cross(c.Normal, a.Normal)) / f;
            v3 = (c.D * Vector3.Cross(a.Normal, b.Normal)) / f;

            Vector3 vec = *new* Vector3(v1.X + v2.X + v3.X, v1.Y +
v2.Y + v3.Y, v1.Z + v2.Z + v3.Z);
            *return* vec;
        }

If i change to the following (mathmatically identical form) i end up
with a different (more accurate) answer:

        *private* *static* Vector3 IntersectionPoint(*ref* Plane a,
*ref* Plane b, *ref* Plane c)
        {
            Vector3 v1, v2, v3;
            *float* f = -1 / Vector3.Dot(a.Normal,
Vector3.Cross(b.Normal, c.Normal));

            v1 = (a.D * Vector3.Cross(b.Normal, c.Normal));
            v2 = (b.D * Vector3.Cross(c.Normal, a.Normal));
            v3 = (c.D * Vector3.Cross(a.Normal, b.Normal));

            Vector3 vec = *new* Vector3(v1.X + v2.X + v3.X, v1.Y +
v2.Y + v3.Y, v1.Z + v2.Z + v3.Z);
            *return* vec / f;
        }

However the results of both methods change depending on whether i'm in
debug or release mode, which just isn't good.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-devel-list/attachments/20070128/2eab7ee7/attachment.html 


More information about the Mono-devel-list mailing list