PrimeTester.IsPrimeCpu will now reuse remainders from previous checks.
This commit is contained in:
1 parent
efb4933935
commit
b3a325521a
1 file changed
+47
-4
@@ -16,6 +16,15 @@ public sealed class PrimeTester
|
|||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
private static PrimeTester? _tester;
|
private static PrimeTester? _tester;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static uint[]? _smallPrimeRemainders;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static ulong _lastTrackedValue;
|
||||||
|
|
||||||
|
[ThreadStatic]
|
||||||
|
private static ulong _lastRemainderLimit;
|
||||||
|
|
||||||
public static PrimeTester Exclusive => _tester ??= new();
|
public static PrimeTester Exclusive => _tester ??= new();
|
||||||
|
|
||||||
public static bool IsPrimeCpu(ulong n)
|
public static bool IsPrimeCpu(ulong n)
|
||||||
@@ -40,25 +49,59 @@ public sealed class PrimeTester
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var remainderStepper = new AscendingDivisorRemainderStepper(n);
|
|
||||||
uint[] smallPrimeDivisors = PrimesGenerator.SmallPrimes;
|
uint[] smallPrimeDivisors = PrimesGenerator.SmallPrimes;
|
||||||
int smallPrimeDivisorsLength = smallPrimeDivisors.Length;
|
int smallPrimeDivisorsLength = smallPrimeDivisors.Length;
|
||||||
|
uint[] remainders = _smallPrimeRemainders ??= new uint[smallPrimeDivisorsLength];
|
||||||
|
if (remainders.Length < smallPrimeDivisorsLength)
|
||||||
|
{
|
||||||
|
remainders = _smallPrimeRemainders = new uint[smallPrimeDivisorsLength];
|
||||||
|
}
|
||||||
|
bool canIncrement = _lastTrackedValue != 0UL && n > _lastTrackedValue;
|
||||||
|
ulong delta = canIncrement ? n - _lastTrackedValue : 0UL;
|
||||||
|
ulong maxDivisor = (ulong)Math.Sqrt(n);
|
||||||
|
if ((UInt128)maxDivisor * maxDivisor < n)
|
||||||
|
{
|
||||||
|
maxDivisor++;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 1; i < smallPrimeDivisorsLength; i++)
|
for (int i = 1; i < smallPrimeDivisorsLength; i++)
|
||||||
{
|
{
|
||||||
uint divisor = smallPrimeDivisors[i];
|
uint divisor = smallPrimeDivisors[i];
|
||||||
|
|
||||||
if (!remainderStepper.ShouldContinue(divisor))
|
if (divisor > maxDivisor)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remainderStepper.Divides(divisor))
|
uint remainder;
|
||||||
|
bool canReuse = canIncrement && divisor <= _lastRemainderLimit;
|
||||||
|
if (!canReuse)
|
||||||
{
|
{
|
||||||
|
remainder = (uint)(n % divisor);
|
||||||
|
remainders[i] = remainder;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint previousRemainder = remainders[i];
|
||||||
|
uint deltaMod = delta >= divisor ? (uint)(delta % divisor) : (uint)delta;
|
||||||
|
remainder = previousRemainder + deltaMod;
|
||||||
|
if (remainder >= divisor)
|
||||||
|
{
|
||||||
|
remainder -= divisor;
|
||||||
|
}
|
||||||
|
remainders[i] = remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remainder == 0UL)
|
||||||
|
{
|
||||||
|
_lastTrackedValue = n;
|
||||||
|
_lastRemainderLimit = maxDivisor;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_lastTrackedValue = n;
|
||||||
|
_lastRemainderLimit = maxDivisor;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,4 +263,4 @@ public sealed class PrimeTester
|
|||||||
|
|
||||||
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
AcceleratorStreamPool.Return(acceleratorIndex, stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user