.NET Portable library missing BitConverter.DoubleToInt64Bits, replacement very slow
Asked Answered
P

2

6

I am developing a portable class library in C# and I want to bit convert a double to a long. The most straightforward solution to this issue would be to use the BitConverter.DoubleToInt64Bits method, but unfortunately this method is not available in the Portable Library subset of the .NET class library.

As an alternative I have come up with the following "two-pass" bit conversion:

var result = BitConverter.ToInt64(BitConverter.GetBytes(x), 0);

My tests show that this expression consistently produces the same result as DoubleToInt64Bits. However, my benchmark tests also show that this alternative formulation is approximately four times slower than DoubleToInt64Bits when implemented in a full .NET Framework application.

Using only the Portable Library subset, is it possible to implement a replacement of DoubleToInt64Bits that is quicker than my formulation above?

Peneus answered 9/5, 2012 at 13:26 Comment(0)
F
5

How about using a union?

[StructLayout(LayoutKind.Explicit)]
public struct DoubleLongUnion
{
    [FieldOffset(0)]
    public double Double;

    [FieldOffset(0)]
    public long Long;
}

public static long DoubleToInt64Bits(double value)
{
    var union = new DoubleLongUnion {Double = value};
    return union.Long;
}
Favata answered 9/5, 2012 at 15:39 Comment(3)
Great, what a clever solution, many thanks Omer! Your solution is slower than the full framework DoubleToInt64Bits method, but more than twice as fast as my "two-pass" solution. For a while I was a little bit worried that this would not work in a portable library, since there is no indication on MSDN that the Portable Library subset supports the FieldOffset attribute. However, the implementation works so it only seems to be an oversight in the MSDN documentation.Peneus
An additional benefit with your solution is that I can easily add a ulong ULong field to the Union struct, and analogously implement a DoubleToUInt64Bits method returning a ulong value. This flexibility is much appreciated :-)Peneus
BTW, a potential speed boost might be to declare the union instance as a static field, outside of the method, and only change its value in the method. Then you won't have to allocate the stack space every time you call the method. However the downside is that it will not be thread-safe anymore.Favata
S
3

If you're able to flag your assembly as unsafe then you could just lift the DoubleToInt64Bits implementation into your own library:

public static unsafe long DoubleToInt64Bits(double value)
{
    return *(((long*) &value));
}
Smitten answered 9/5, 2012 at 14:33 Comment(2)
Thanks for the suggestion! I made a quick benchmark test of your method, and it seems to be about as fast as the DoubleToInt64Bits method. Unfortunately, since it is a portable library(potentially aimed also for Silverlight, WP7 and Metro applications), unsafe is not an option.Peneus
Of course, your method is bound to be as fast as DoubleToInt64Bits. I read your answer too quickly the first time and missed the part that this is the way DoubleToInt64Bits is implemented :-) Sorry for my confusion.Peneus

© 2022 - 2024 — McMap. All rights reserved.