-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
@tannergooding, @pgovind
What do you guys think of the idea of adding the following TryMultiply methods to System.UInt64 or System.Math? They return null if the multiplication would overflow:
namespace System
{
public struct UInt64 // Alternatively System.Math
{
public static unsafe UInt64? TryMultiply(UInt64 a, UInt64 b)
{
unchecked {
if (System.Runtime.Intrinsics.X86.Bmi2.X64.IsSupported)
{
uint64 low;
if (System.Runtime.Intrinsics.X86.Bmi2.X64.MultiplyNoFlags(a, b, &low) == 0)
return low;
return null;
}
if (b == 0 || a <= (UInt64.MaxValue / b)) return a * b;
return null;
}
}
// And for System.UInt32.TryMultiply or System.Math.TryMultiply(UInt32, UInt32):
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static UInt32? TryMultiply(UInt32 a, UInt32 b)
{
unchecked {
UInt64 product64 = (UInt64)a * b;
UInt32 product32 = (UInt32)product64;
if (product32 == product64) return product32;
return null;
}
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static UInt64? TryAdd(UInt64 a, UInt64 b)
{
UInt64 result = unchecked(a + b);
return (result >= a) ? result : default(UInt64?);
}
}
}These methods intentionally do not use checked(a * b) because they're intended for scenarios where the high cost of throwing exceptions is unacceptable.
Maybe you know, and could answer, the question of whether my TryMultiply implementations above are the best-possible implementations. Because of gaps in my knowledge of Intel processors, I'm unsure whether the above are the best implementations. I wonder whether or not it would be beneficial to add a few more intrinsics/methods to System.Runtime.Intrinsics.X86 in order to gain the ability to read the carry and/or overflow flags -- if necessary. I don't know enough CPU detail to say whether or not the x86-64 carry and/or overflow flags should be used, versus whether the above implementations are already the best overall. Maybe someone with detailed CPU knowledge could answer this question.
In any event, regardless of whether the above implementations are the best-possible, they're already at least good implementations that could be added to NETFW 5.x immediately, and later further optimized if necessary.
See also issue #13026 where @RobertBouillon suggests new CIL instructions. Although I like his idea, it's far more work than the alternative of TryMultiply etc methods such as the above. The above TryMultiply etc methods could provide the desired functionality very soon, unlike the complexity and politics of creating new CIL instructions.