Is it possible to write Quake's fast InvSqrt() function in C#?

You should be able to use the StructLayout and FieldOffset attributes to fake a union for plain old data like floats and ints.

[StructLayout(LayoutKind.Explicit, Size=4)]
private struct IntFloat {
    [FieldOffset(0)]
    public float floatValue;

    [FieldOffset(0)]
    public int intValue;

    // redundant assignment to avoid any complaints about uninitialized members
    IntFloat(int x) {
        floatValue = 0;
        intValue = x;
    }

    IntFloat(float x) { 
        intValue = 0;
        floatValue = x;
    }

    public static explicit operator float (IntFloat x) {
        return x.floatValue;
    }

    public static explicit operator int (IntFloat x) { 
        return x.intValue;
    }

    public static explicit operator IntFloat (int i) {
        return new IntFloat(i);
    }
    public static explicit operator IntFloat (float f) { 
        return new IntFloat(f);
    }
}

Then translating InvSqrt is easy.


Use BitConverter if you want to avoid unsafe code.

float InvSqrt(float x)
{
    float xhalf = 0.5f * x;
    int i = BitConverter.SingleToInt32Bits(x);
    i = 0x5f3759df - (i >> 1);
    x = BitConverter.Int32BitsToSingle(i);
    x = x * (1.5f - xhalf * x * x);
    return x;
}

The code above uses new methods introduced in .NET Core 2.0. For .NET Framework, you have to fall back to the following (which performs allocations):

float InvSqrt(float x)
{
    float xhalf = 0.5f * x;
    int i = BitConverter.ToInt32(BitConverter.GetBytes(x), 0);
    i = 0x5f3759df - (i >> 1);
    x = BitConverter.ToSingle(BitConverter.GetBytes(i), 0);
    x = x * (1.5f - xhalf * x * x);
    return x;
}

Otherwise, the C# code is exactly the same as the C code you gave, except that the method needs to be marked as unsafe:

unsafe float InvSqrt(float x) { ... }

Definitely possible in unsafe mode. Note that even though in the Quake 3 source code the constant 0x5f3759df was used, numerical research showed that the constant 0x5f375a86 actually yields better results for Newton Approximations.

Tags:

C#