chronosifter's picture

Clever trick, curious on how safe it is for platform neutrality

Having had to do a lot of NextPowerOfTwo calls in a proof of concept I found the performance to be abysmal using the traditional methods. So I resorted to the IEEE specification that C# relies upon and came up with the following:

[StructLayout(LayoutKind.Explicit)]
struct IntFloatUnion
{
    [FieldOffset(0)]
    public float Float;
    [FieldOffset(0)]
    public int Int;
 
    public int Sign { get { return +1 | (Int >> 31); } }
    public int Exponent { get { return ((Int >> 23) & 0xFF) - 127; } }
 
    public IntFloatUnion(float f)
    {
        Int = 0;
        Float = f;
    }
}

And a similar structure for double precision.

Then the following function:

public static float NextPowerOfTwo(float n)
{
    IntFloatUnion union = new IntFloatUnion(n);
    if (union.Sign < 0) throw new ArgumentOutOfRangeException("n", "Must be positive.");
    int exp = union.Exponent;
    if (union.Float - exp > 0) exp++;
    return (float)(1 << exp);
}

Since this relies upon the bit structure of a float (and double in that case), I'm curious whether or not this sort of thing would be safe to use across multiple platforms without additional work to correct for platform differences?


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Robmaister's picture

You might encounter some endianness issues, but other than that it should work just fine.

Inertia's picture

When I did research regarding the half-precision float type, it turned out that endianness is not really anything to worry about when you use .Net/Mono (little-endian everywhere). Just add some line:
if(NextPow(7)!=8 throw...
and just use it until that throw pops ;)