------------------------------------------------------------------------------
MC logo
Fast Primes Generator
[^] CSc 220 Home
------------------------------------------------------------------------------
[Introduction] [Boolean and Control] [Functions] [Arrays and Pointers] [Dynamic Arrays] [Array Errors] [Command Array] [Standard Containers] [Structs and Classes] [Automatic Pointer] [Multi-File Programs] [Copying Objects] [Templates] [Inheritance] [Plain C I/O] [Type Odds And Ends] [Plain C Strings] [File I/O]
[Plain Structs] [Point With Struct] [C++ Point Class] [Linked List (Structs)] [Linked List (Classes)] [C++ v. Java Classes I] [Prime Generator Algorithm] [Fast Primes Generator]
primgen.cpp
/*
 * 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;
}