/// <summary>
/// Generates prime number up to a user specified maximum
/// The algorithm used is the Sieve of Eratosthenes.
/// Given an array of integers starting at 2:
/// Find the first uncrossed (eg 3 ) integer, and cross out all its multiples (eg 6,9,12,14)
/// Repeat until there are no more multipes in the array
/// </summary>
class PrimeGenerator
{
public int[] generatePrimes(int maxValue)
{
bool[] crossedOut;
if (maxValue < 2)
return new int[0];
else
{
crossedOut = new bool[maxValue + 1];
uncrossIntegersUpTo(crossedOut);
crossOutMultiples(crossedOut);
return putUncrossedIntegersIntoResult(crossedOut);
}
}
void uncrossIntegersUpTo(bool[] crossedOut)
{
// as bool array starts at 0, and if maxvalue = 10, we need an array of length 11
for (int i = 2; i < crossedOut.Length; i++) // less than as we don't want to reference crossedOut[4] which doesn't exist
crossedOut[i] = false;
}
void crossOutMultiples(bool[] crossedOut)
{
int limit = determineIterationLimit(crossedOut);
for (int i = 2; i <= limit; i++)
if (!crossedOut[i])
crossOutMultiplesOf(crossedOut, i);
}
int determineIterationLimit(bool[] crossedOut)
{
// Every multiple in the array has a prime factor that
// is less than or equal to the square root of the array size,
// which is the largest number we are trying to find primes in.
// So we don't have to cross out numbers
// larger than that square root of the maxnumber, as they will have been crossed out already
double iterationLimit = Math.Sqrt(crossedOut.Length);
return (int) iterationLimit;
}
void crossOutMultiplesOf(bool[] crossedOut, int i)
{
for (int multiple = 2*i; multiple < crossedOut.Length; multiple += i)
crossedOut[multiple] = true;
}
int[] putUncrossedIntegersIntoResult(bool[] crossedOut)
{
int[] result = new int[numberOfUncrossedIntegers(crossedOut)];
for (int j = 0, i = 2; i < crossedOut.Length; i++)
if (!crossedOut[i])
result[j++] = i;
return result;
}
int numberOfUncrossedIntegers(bool[] crossedOut)
{
int count = 0;
for (int i = 2; i < crossedOut.Length; i++)
if (!crossedOut[i])
count++;
return count;
}
}