提交 ea9bfd21 编写于 作者: A Anton Lapounov 提交者: Jan Kotas

Even faster modulo computation: remove one of the three multiplications. (#406)

上级 4dbc6f16
......@@ -90,21 +90,24 @@ public static int ExpandPrime(int oldSize)
}
#if BIT64
// Returns approximate reciprocal of the divisor: ceil(2**64 / divisor)
public static ulong GetFastModMultiplier(uint divisor)
=> ulong.MaxValue / divisor + 1;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint FastMod(uint value, uint divisor, ulong multiplier)
{
// Using fastmod from Daniel Lemire https://lemire.me/blog/2019/02/08/faster-remainders-when-the-divisor-is-a-constant-beating-compilers-and-libdivide/
// We use modified Daniel Lemire's fastmod algorithm (https://github.com/dotnet/runtime/pull/406),
// which allows to avoid the long multiplication if the divisor is less than 2**31.
Debug.Assert(divisor <= int.MaxValue);
ulong lowbits = multiplier * value;
// 64bit * 64bit => 128bit isn't currently supported by Math https://github.com/dotnet/corefx/issues/41822
// otherwise we'd want this to be (uint)Math.MultiplyHigh(lowbits, divisor)
uint high = (uint)((((ulong)(uint)lowbits * divisor >> 32) + (lowbits >> 32) * divisor) >> 32);
// otherwise we'd want this to be (uint)Math.BigMul(lowbits, divisor, out _)
uint highbits = (uint)((((lowbits >> 32) + 1) * divisor) >> 32);
Debug.Assert(high == value % divisor);
return high;
Debug.Assert(highbits == value % divisor);
return highbits;
}
#endif
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册