Refine GPU residue prime tables
This commit is contained in:
1 parent
88d0c9c271
commit
34cc0b0fdd
5 files changed
+209
-99
No files matched your search
@@ -1,80 +1,113 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PerfectNumbers.Core;
|
||||
|
||||
public static class PrimesGenerator
|
||||
{
|
||||
private static uint[]? _primes;
|
||||
private static ulong[]? _primesPow2;
|
||||
public static readonly uint[] SmallPrimes;
|
||||
public static readonly ulong[] SmallPrimesPow2;
|
||||
public static readonly uint[] SmallPrimesLastOne;
|
||||
public static readonly ulong[] SmallPrimesPow2LastOne;
|
||||
public static readonly uint[] SmallPrimesLastSeven;
|
||||
public static readonly ulong[] SmallPrimesPow2LastSeven;
|
||||
|
||||
public static readonly uint[] SmallPrimes = BuildSmallPrimesInternal();
|
||||
public static readonly ulong[] SmallPrimesPow2 = BuildSmallPrimesPow2Internal();
|
||||
static PrimesGenerator()
|
||||
{
|
||||
BuildSmallPrimes(
|
||||
out SmallPrimes,
|
||||
out SmallPrimesPow2,
|
||||
out SmallPrimesLastOne,
|
||||
out SmallPrimesPow2LastOne,
|
||||
out SmallPrimesLastSeven,
|
||||
out SmallPrimesPow2LastSeven);
|
||||
}
|
||||
|
||||
private static void BuildSmallPrimes(
|
||||
out uint[] all,
|
||||
out ulong[] allPow2,
|
||||
out uint[] lastOne,
|
||||
out ulong[] lastOnePow2,
|
||||
out uint[] lastSeven,
|
||||
out ulong[] lastSevenPow2)
|
||||
{
|
||||
uint target = PerfectNumberConstants.PrimesLimit;
|
||||
int targetInt = checked((int)target);
|
||||
all = new uint[targetInt];
|
||||
allPow2 = new ulong[targetInt];
|
||||
lastOne = new uint[targetInt];
|
||||
lastOnePow2 = new ulong[targetInt];
|
||||
lastSeven = new uint[targetInt];
|
||||
lastSevenPow2 = new ulong[targetInt];
|
||||
|
||||
private static uint[] BuildSmallPrimesInternal()
|
||||
{
|
||||
if (_primes == null)
|
||||
{
|
||||
BuildSmallPrimes();
|
||||
}
|
||||
List<uint> primes = new(targetInt * 4 / 3 + 16);
|
||||
uint candidate = 2U;
|
||||
int allCount = 0;
|
||||
int lastOneCount = 0;
|
||||
int lastSevenCount = 0;
|
||||
|
||||
return _primes!;
|
||||
}
|
||||
while (allCount < targetInt || lastOneCount < targetInt || lastSevenCount < targetInt)
|
||||
{
|
||||
bool isPrime = true;
|
||||
int primesCount = primes.Count;
|
||||
for (int i = 0; i < primesCount; i++)
|
||||
{
|
||||
uint p = primes[i];
|
||||
if (p * p > candidate)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
private static ulong[] BuildSmallPrimesPow2Internal()
|
||||
{
|
||||
if (_primesPow2 == null)
|
||||
{
|
||||
BuildSmallPrimes();
|
||||
}
|
||||
if (candidate % p == 0U)
|
||||
{
|
||||
isPrime = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _primesPow2!;
|
||||
}
|
||||
if (isPrime)
|
||||
{
|
||||
primes.Add(candidate);
|
||||
if (allCount < targetInt)
|
||||
{
|
||||
all[allCount] = candidate;
|
||||
allPow2[allCount] = checked((ulong)candidate * candidate);
|
||||
allCount++;
|
||||
}
|
||||
|
||||
private static void BuildSmallPrimes()
|
||||
{
|
||||
uint limit = PerfectNumberConstants.PrimesLimit;
|
||||
var primes = new uint[limit];
|
||||
primes[0] = 2;
|
||||
var primesPow2 = new ulong[limit];
|
||||
primesPow2[0] = 4;
|
||||
if (candidate != 2U)
|
||||
{
|
||||
if (lastOneCount < targetInt && IsAllowedForLastOne(candidate))
|
||||
{
|
||||
lastOne[lastOneCount] = candidate;
|
||||
lastOnePow2[lastOneCount] = checked((ulong)candidate * candidate);
|
||||
lastOneCount++;
|
||||
}
|
||||
|
||||
int j;
|
||||
uint i = 3, p, sqrt;
|
||||
bool isPrime;
|
||||
int primeIndex = 1;
|
||||
if (lastSevenCount < targetInt && IsAllowedForLastSeven(candidate))
|
||||
{
|
||||
lastSeven[lastSevenCount] = candidate;
|
||||
lastSevenPow2[lastSevenCount] = checked((ulong)candidate * candidate);
|
||||
lastSevenCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; i <= limit; i += 2)
|
||||
{
|
||||
isPrime = true;
|
||||
sqrt = (uint)Math.Sqrt(i);
|
||||
for (j = 0; j < primeIndex; j++)
|
||||
{
|
||||
p = primes[j];
|
||||
if (p > sqrt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
candidate = candidate == 2U ? 3U : candidate + 2U;
|
||||
}
|
||||
}
|
||||
|
||||
if (i % p == 0UL)
|
||||
{
|
||||
isPrime = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsAllowedForLastOne(uint prime)
|
||||
{
|
||||
uint mod10 = prime % 10U;
|
||||
return mod10 == 1U || mod10 == 3U || mod10 == 9U || prime == 7U || prime == 11U;
|
||||
}
|
||||
|
||||
if (isPrime)
|
||||
{
|
||||
primes[primeIndex] = i;
|
||||
primesPow2[primeIndex] = checked((ulong)i * i);
|
||||
primeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
Array.Resize(ref primes, primeIndex);
|
||||
Array.Resize(ref primesPow2, primeIndex);
|
||||
|
||||
_primes = primes;
|
||||
_primesPow2 = primesPow2;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsAllowedForLastSeven(uint prime)
|
||||
{
|
||||
uint mod10 = prime % 10U;
|
||||
return mod10 == 3U || mod10 == 7U || mod10 == 9U || prime == 11U;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user