Skip to content

Instantly share code, notes, and snippets.

@geniuszxy
Last active February 13, 2022 13:24
Show Gist options
  • Save geniuszxy/35bd647d9a118fa862d014d0df107ce6 to your computer and use it in GitHub Desktop.
Save geniuszxy/35bd647d9a118fa862d014d0df107ce6 to your computer and use it in GitHub Desktop.
Get Primes
#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
}
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