Last active
February 13, 2022 13:24
-
-
Save geniuszxy/35bd647d9a118fa862d014d0df107ce6 to your computer and use it in GitHub Desktop.
Get Primes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define PROFILE | |
//#define OUTPUT | |
//#define USE_BITS | |
//#define SHIFT | |
using System; | |
using System.Diagnostics; | |
using System.Runtime.CompilerServices; | |
class Program | |
{ | |
static void Main() | |
{ | |
GetPrimes(int.MaxValue, p => Console.WriteLine(p)); | |
} | |
/// <summary> | |
/// Get primes from 2 to MAX | |
/// </summary> | |
public static void GetPrimes(int MAX, Action<int> output) | |
{ | |
int MAX_TEST_IDX = GetIndex((int)Math.Sqrt(MAX)); //max integer index to test | |
#if PROFILE | |
var sw = Stopwatch.StartNew(); | |
#endif | |
//count of odds in the range | |
//all evens except '2' are not prime, so we exclude them from the beginning | |
//'1' is also include so that 'GetNumber' replaces '+1' with '|1' | |
var vts = new Vectors(GetIndex(MAX) + 1); | |
#if OUTPUT | |
output(2); | |
#endif | |
//loop through all numbers we want to test | |
//'i' is the index in 'vts' | |
//'b' is the real odd, so it adds 2 after each loop | |
for (int i = 1, b = GetNumber(i); i <= MAX_TEST_IDX; i++, b += 2) | |
{ | |
//for convenience, '0' means the index of the odd is regarded as a prime | |
//if the odd is composite, it means the odd is sieved in previous loops | |
//so all the multiples of this number are already sieved too. | |
if (vts[i] != 0) | |
continue; | |
#if OUTPUT | |
output(b); | |
#endif | |
//now we start sieving the multiple of 'b' | |
//it is in reverse order, 'j' is the maximum multiple index | |
//'c' is the maximum product | |
int j = GetIndex(MAX / b); | |
#if SHIFT | |
int c = GetNumber(j) * b; | |
//'b2' is used to decrease 'c' after each loop | |
//since there are only odds to test, the decreasement should be multiply by 2 | |
int b2 = b << 1; | |
for (; j > i; j--) | |
{ | |
if (vts[j] == 0) | |
vts.Set(c >> 1); | |
c -= b2; | |
} | |
//finally sieving 'b*b' | |
vts.Set(c >> 1); | |
#else | |
int c = (GetNumber(j) * b) >> 1; | |
for (; j > i; j--) | |
{ | |
if (vts[j] == 0) | |
vts.Set(c); | |
c -= b; | |
} | |
//finally sieving 'b*b' | |
vts.Set(c); | |
#endif | |
} | |
#if OUTPUT | |
for (int i = MAX_TEST_IDX + 1; i < nums.Length; i++) | |
if (nums[i] > 0) | |
output(nums[i]); | |
#endif | |
#if PROFILE | |
sw.Stop(); | |
Console.WriteLine(sw.Elapsed); | |
#endif | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
static int GetIndex(int odd) | |
{ | |
var i = odd >> 1; | |
return (odd & 1) == 0 ? i - 1 : i; //if input value is an even, minus the index by 1 | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
static int GetNumber(int index) | |
{ | |
return (index << 1) | 1; //index * 2 + 1 | |
} | |
#if USE_BITS | |
struct Vectors | |
{ | |
private ulong[] _vs; | |
public Vectors(int count) | |
{ | |
var c = count >> 5; | |
if ((count & 63) != 0) | |
c++; | |
_vs = new ulong[c]; | |
} | |
//If the bit is set to 1 | |
public ulong this[int index] | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
get => _vs[index >> 5] & (1UL << (index & 63)); | |
} | |
//Set the bit to 1 | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public void Set(int index) | |
{ | |
_vs[index >> 5] |= 1UL << (index & 63); | |
} | |
} | |
#else | |
struct Vectors | |
{ | |
internal byte[] _vs; | |
public Vectors(int count) | |
{ | |
_vs = new byte[count]; | |
} | |
//If the bit is set to 1 | |
public byte this[int index] | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
get => _vs[index]; | |
} | |
//Set the bit to 1 | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public void Set(int index) | |
{ | |
_vs[index] = 1; | |
} | |
} | |
#endif | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private void Output() | |
{ | |
var k = 2; | |
uint lp = 6; | |
int primeL = 3; | |
Console.WriteLine(3); | |
do | |
{ | |
for (; k < _vs.Length; ++k) | |
{ | |
if (_vs[k] != 0) | |
continue; | |
var prime = GetNumber(k); | |
int d = prime - (int)lp; | |
if (d >= 0) | |
{ | |
if (d == 0) | |
lp = (uint)prime; | |
else | |
{ | |
int e = (int)lp - primeL; | |
lp = (uint)(e < d ? primeL : prime); | |
} | |
Console.WriteLine(lp); | |
break; | |
} | |
primeL = prime; | |
} | |
if (lp <= 1024) | |
lp *= 2; | |
else if (lp <= 262144) | |
lp = (uint)(lp * 1.5); | |
else if (lp <= 134217728) | |
lp = (uint)(lp * 1.2); | |
else | |
lp = (uint)(lp * 1.1); | |
} | |
while (lp < int.MaxValue); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment