CSC 220

Introduction

First Steps

Control

Functions

Arrays

Containers

Classes

Trivial Class

Point Class

Point Driver

Polynomial Class

Poly Imple

Poly Driver

Poly Ptr

Primgen Algorithm

Primgen Code

Templates

Memory Management

Exceptions

Class Inheritance

Multi-File Programs

Other Things

/*
* This program generates prime numbers fairly quickly using a sieve.
* It prints prime numbers until the first of
* o You get tired and kill it.
* o It runs out of memory and crashes.
* o The integers start to overflow, in which case you have a computer
* with a whole lot of memory.
*/
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
/*
* Prime eliminator. It is essentially a pair of numbers, the first prime
* and the second a multiple of the first. The program keeps a collection
* of these in a heap to eliminate candidate primes.
*/
class Eliminator
{
public:
// Create at a prime, ready to eliminate the first multiple thereof.
Eliminator(int p)
{
base = p;
target = 2*p;
}
// See what number is eliminated next.
int eliminates()
{
return target;
}
// Advance to the next elimination.
void advance()
{
target += base;
}
// Compare Eliminators according to their eliminated value.
bool operator<(const Eliminator &e) const
{
return target > e.target; // Note: Inverted sense
}
bool operator==(const Eliminator &e) const
{
return target == e.target;
}
void print()
{
cout << "(" << base << ", " << target << ")";
}
private:
// The base is a prime number, and the target is the next multiple
// which it has not yet eliminated.
int base, target;
};
// This is a collection of Eliminators organized as a heap, so the next largest
// one can be found quickly.
class EliminatorCollection
{
public:
// What does the heap eliminate just now?
int eliminates()
{
return heap.front().eliminates();
}
// Insert a new prime eliminator into the collection.
void insert(int i)
{
heap.push_back(Eliminator(i));
push_heap(heap.begin(), heap.end());
}
// Move on to the next elimination target.
void advance()
{
// Get the current eliminee.
int you_die = eliminates();
// Get rid of all the nodes which eliminate this same number.
vector<Eliminator>::iterator heap_end = heap.end();
while(heap_end != heap.begin() &&
heap.front().eliminates() == you_die) {
pop_heap(heap.begin(), heap_end);
--heap_end;
heap_end->advance();
}
// Return them, now advanced, to the heap.
do {
++heap_end;
push_heap(heap.begin(), heap_end);
}
while(heap_end != heap.end());
}
// Get 'em out.
void dump()
{
vector<Eliminator>::iterator scan = heap.begin();
while(scan != heap.end()) {
scan->print();
cout << endl;
++scan;
}
}
private:
// This holds the heap data structure.
vector<Eliminator> heap;
};
/*
* Output with appropriate line breaking.
*/
void outprime(int n)
{
static int outlen = 0; // Output line width.
// Get the string for n.
ostringstream os;
os << n;
string strint = os.str();
// Do any needed wrap.
if(outlen + strint.length() + 1 > 75) {
cout << endl;
outlen = 0;
} else {
cout << " ";
outlen++;
}
cout << strint;
outlen += strint.length();
}
/*
* Generate primes until you get tired of it (or run out of
* ints). This uses a form of the seive method which
* eliminates non-prime candidate primes by checking if they are a
* multiple of any previous prime found. This is done efficiently by
* keeping the set of multiples of previously-found primes in a heap.
* A heap is a data structure which can quickly find the smallest
* number it contains.
*/
main()
{
outprime(2);
EliminatorCollection ec;
ec.insert(2);
for(int m=3; 1; m++)
{
if(m == ec.eliminates())
ec.advance();
else {
//cout << m << endl;
outprime(m);
ec.insert(m);
}
}
cout << endl;
}