From 2b7815f10e6a3c32d93972150ae2b9d79e27043a Mon Sep 17 00:00:00 2001 From: lilinus Date: Thu, 11 Apr 2024 16:49:42 +0200 Subject: [PATCH 1/3] Use BigMul in BigMul --- .../System.Private.CoreLib/src/System/Math.cs | 20 ++++++++++++++----- .../src/System/UInt128.cs | 16 +++++++-------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index e2fe2051ce5c9..d14dce978750f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -208,13 +208,13 @@ static ulong SoftwareFallback(ulong a, ulong b, out ulong low) uint bl = (uint)b; uint bh = (uint)(b >> 32); - ulong mull = ((ulong)al) * bl; - ulong t = ((ulong)ah) * bl + (mull >> 32); - ulong tl = ((ulong)al) * bh + (uint)t; + ulong mull = BigMul(al, bl); + ulong t = BigMul(ah, bl) + (mull >> 32); + ulong tl = BigMul(al, bh) + (uint)t; low = tl << 32 | (uint)mull; - return ((ulong)ah) * bh + (t >> 32) + (tl >> 32); + return BigMul(ah, bh) + (t >> 32) + (tl >> 32); } } @@ -236,13 +236,23 @@ public static long BigMul(long a, long b, out long low) return (long)high - ((a >> 63) & b) - ((b >> 63) & a); } + /// Produces the full product of two unsigned 64-bit numbers. + /// The first number to multiply. + /// The second number to multiply. + /// The full product of the specified numbers. + internal static UInt128 BigMul(ulong a, ulong b) + { + ulong high = BigMul(a, b, out ulong low); + return new UInt128(high, low); + } + /// Produces the full product of two 64-bit numbers. /// The first number to multiply. /// The second number to multiply. /// The full product of the specified numbers. internal static Int128 BigMul(long a, long b) { - long high = Math.BigMul(a, b, out long low); + long high = BigMul(a, b, out long low); return new Int128((ulong)high, (ulong)low); } diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs index ec195239ca983..0ee4c3c800052 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt128.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt128.cs @@ -1396,18 +1396,18 @@ internal static UInt128 BigMul(UInt128 left, UInt128 right, out UInt128 lower) // Basically, it's an optimized version of FOIL method applied to // low and high qwords of each operand - UInt128 al = left._lower; - UInt128 ah = left._upper; + ulong al = left._lower; + ulong ah = left._upper; - UInt128 bl = right._lower; - UInt128 bh = right._upper; + ulong bl = right._lower; + ulong bh = right._upper; - UInt128 mull = al * bl; - UInt128 t = ah * bl + mull._upper; - UInt128 tl = al * bh + t._lower; + UInt128 mull = Math.BigMul(al, bl); + UInt128 t = Math.BigMul(ah, bl) + mull._upper; + UInt128 tl = Math.BigMul(al, bh) + t._lower; lower = new UInt128(tl._lower, mull._lower); - return ah * bh + t._upper + tl._upper; + return Math.BigMul(ah, bh) + t._upper + tl._upper; } // From 331019d915836e51f251e85ca26cfdde1bf0e7e6 Mon Sep 17 00:00:00 2001 From: lilinus Date: Fri, 12 Apr 2024 10:07:05 +0200 Subject: [PATCH 2/3] Reverse usage of BigMul(uint, uint) --- src/libraries/System.Private.CoreLib/src/System/Math.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index d14dce978750f..0f19149869ea1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -208,13 +208,13 @@ static ulong SoftwareFallback(ulong a, ulong b, out ulong low) uint bl = (uint)b; uint bh = (uint)(b >> 32); - ulong mull = BigMul(al, bl); - ulong t = BigMul(ah, bl) + (mull >> 32); - ulong tl = BigMul(al, bh) + (uint)t; + ulong mull = ((ulong)al) * bl; + ulong t = ((ulong)ah) * bl + (mull >> 32); + ulong tl = ((ulong)al) * bh + (uint)t; low = tl << 32 | (uint)mull; - return BigMul(ah, bh) + (t >> 32) + (tl >> 32); + return ((ulong)ah) * bh + (t >> 32) + (tl >> 32); } } From 3f7f3066aa752a14418230ca825665d6d635b353 Mon Sep 17 00:00:00 2001 From: lilinus Date: Wed, 24 Apr 2024 14:06:41 +0200 Subject: [PATCH 3/3] Add aggressive inline to Math.BigMul(ulong, ulong) --- src/libraries/System.Private.CoreLib/src/System/Math.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index 0f19149869ea1..35423008dc317 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -240,6 +240,7 @@ public static long BigMul(long a, long b, out long low) /// The first number to multiply. /// The second number to multiply. /// The full product of the specified numbers. + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static UInt128 BigMul(ulong a, ulong b) { ulong high = BigMul(a, b, out ulong low);