Skip to content

Instantly share code, notes, and snippets.

@panzi
Created November 10, 2013 17:22
Show Gist options
  • Save panzi/7401096 to your computer and use it in GitHub Desktop.
Save panzi/7401096 to your computer and use it in GitHub Desktop.
Usage: visprim <width> <height> <output-filename> [number-of-threads]
CPP = g++
LIB = `Magick++-config --cppflags --cxxflags --ldflags --libs` -lboost_thread-mt
CPPFLAGS = -Wall -O3 `Magick++-config --cppflags --cxxflags`
LDFLAGS = $(LIB) -Wall -O3
BIN = visprim
.PHONY: all zip clean
all: $(BIN)
$(BIN): visprim.cpp
$(CPP) $< -o $@ $(LDFLAGS)
zip: visprim.zip
visprim.zip:
zip -r9 visprim.zip visprim.cpp Makefile
clean:
rm -f $(BIN)
#include <cmath>
#include <iostream>
#include <iomanip>
#include <boost/lexical_cast.hpp>
#include <boost/thread.hpp>
#include <Magick++.h>
using namespace std;
using namespace boost;
using namespace Magick;
void usage(const char * appname) {
cout << "Usage: " << appname << " <width> <height> <output-filename> [number-of-threads]" << endl;
}
bool inline isprime(unsigned int n) {
if (n == 2) {
return true;
}
else if (!(n & 1) || n < 2) {
return false;
}
else {
unsigned int stop = (unsigned int)ceil(sqrt((double)n));
for (unsigned int p = 3; p <= stop; p += 2) {
if (n % p == 0) {
return false;
}
}
return true;
}
}
class Worker {
private:
PixelPacket *const pixel_cache;
const unsigned int begin;
const unsigned int end;
public:
Worker(PixelPacket *pixel_cache, unsigned int begin, unsigned int end) :
pixel_cache(pixel_cache), begin(begin), end(end) {}
void operator () () const {
const ColorRGB red( 1, 0, 0 );
for (unsigned int i = begin; i < end; ++ i) {
if (isprime(i)) {
pixel_cache[i] = red;
}
}
}
};
int main(int argc, char * argv[]) {
if (argc < 4 || argc > 5) {
cerr << "*** illegal number of arguments" << endl;
if (argc < 1) {
usage("visprim");
}
else {
usage(*argv);
}
return 1;
}
unsigned int width;
unsigned int height;
unsigned int threadcount = 1;
const char * filename = argv[3];
try {
width = lexical_cast<unsigned int>(argv[1]);
height = lexical_cast<unsigned int>(argv[2]);
if (argc == 5) {
threadcount = lexical_cast<unsigned int>(argv[4]);
}
}
catch (bad_lexical_cast &) {
cerr << "*** illegal argument" << endl;
usage(*argv);
return 1;
}
if (threadcount == 0) {
cerr << "*** illegal argument" << endl;
usage(*argv);
return 1;
}
Image image( Geometry( width, height ), ColorRGB( 1, 1, 1 ) );
// Ensure that there are no other references to this image
image.modifyImage();
image.type(TrueColorType);
PixelPacket *pixel_cache = image.getPixels(0,0,width,height);
unsigned int n = width * height;
if (threadcount == 1) {
Worker(pixel_cache, 0, n)();
}
else {
thread_group threads;
unsigned int begin = 0;
double segment = ((double)n * (double)n) / (threadcount * 2.0l);
double area = 0;
double x = 0;
for (unsigned int i = 0; i < threadcount - 1; ++ i) {
area += segment;
x = sqrt(2.0l * area);
unsigned int end = (unsigned int) x;
threads.create_thread( Worker(pixel_cache, begin, end) );
begin = end;
}
threads.create_thread( Worker(pixel_cache, begin, n) );
threads.join_all();
}
// Save changes to underlying image
image.syncPixels();
image.write( filename );
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment