Commits

Ben Bass committed c9dcf2a

split out into multiple files

Comments (0)

Files changed (5)

 	g++ make_ppm.cc -o make_ppm
   
 brotmap: brotmap.cc brotmap.h
-	g++ brotmap.cc -Werror -O3 -o brotmap -lc -lpthread
+	g++ brotmap.cc worker.cc evaluate.cc -Werror -O3 -o brotmap -lc -lpthread
 	
 clean:
 	rm -f brotmap make_ppm out.ppm out_image
 // brotmap - Ben Bass 2010-2012
 
 #include <cstdio>
-#include <math.h>  // for NAN. Not in the C++ library...
 #include <cstddef>
 #include <cstdlib>
 #include "brotmap.h"
 #include <unistd.h>
 #include <sys/mman.h>
 
-#include <pthread.h>
-
 #ifndef _POSIX_MAPPED_FILES
 #error "no mapped file support"
 #endif
 #define ftruncate ftruncate64
 #endif
 
-long mpoint(pinfo* p);
 
 long inside_points = 0;
 
 // these are the dimensions of the fractal we are plotting.
-const FLOAT MIN_X = -2.0;
-const FLOAT MAX_X = 1.0;
-const FLOAT MIN_Y = -1.5;
-const FLOAT MAX_Y = 1.5;
-const FLOAT BAILOUT = 4.0;
+FLOAT MIN_X = -2.0;
+FLOAT MAX_X = 1.0;
+FLOAT MIN_Y = -1.5;
+FLOAT MAX_Y = 1.5;
 
 int BINARY_DIGITS = 10;
 
-// mpoint(real, image, ...) -> 1 if mset else 0
-inline long mpoint(FLOAT r,
-                  FLOAT i,
-                  pinfo* p,
-                  int old_max_iter=0)
-{
-    if (isnan(p->x)) {
-        // we've already processed this entry -
-        // and it's not part of the Mset
-        return 0;
-    }
-    FLOAT x2, y2;
-    FLOAT x = p->x;
-    FLOAT y = p->y;
-    int k = MAX_ITER;
-
-#ifdef CARDIOID_OPT
-    // based on 'Optimizations' section in wikipedia
-    // http://en.wikipedia.org/wiki/Mandelbrot_set#Optimizations
-    double roff = (r-0.25);
-    double isq = i*i;
-    double dist = roff*roff + isq;
-    if (dist * (dist + roff) < 0.25*isq)
-    {
-        return 1;
-    }
-
-    roff = r+1.0;
-    if (roff*roff + isq < 1.0/16.0)
-    {
-        return 1;
-    }
-#endif
-    // this is the core 'inner loop'.
-    // It should be fast, which is why it doesn't
-    // have lots of whitespace in it ;)
-    //
-    // of course this is massively parallelizable
-    do {
-        x2 = x*x;
-        y2 = y*y;
-        if ((x2+y2) >= BAILOUT) break;
-        y = 2.0*x*y+i;
-        x = x2-y2+r;
-    } while (--k);
-
-    if (!k)
-    {
-        // we ran out of iterations. Up to MAX_ITER,
-        // this point seems to be part of the mset.
-        // Store current values of x and y so we can
-        // carry on later.
-        p->x = x;
-        p->y = y;
-        return 1;
-    }
-    else
-    {
-        // this is definitely not part of the mset
-        // (rounding errors excepted). We want to store
-        // that fact, together with an iteration count
-        // and the magnitude of the calculation at that
-        // point (so we can do smooth renderings)
-        p->x = NAN;
-        p->itercount = (old_max_iter + (MAX_ITER - k));
-        return 0;
-    }
-}
-
 pinfo* FPTR_START;
 FLOAT STEP_SIZE;
-pthread_mutex_t acc_lock;
 
-void* worker_start(void* arg)
-{
-    int t_num = *reinterpret_cast<int*>(arg);
-    FLOAT t_start = t_num*STEP_SIZE;
-
-    long local_inside = 0;
-
-    // get the number of points to skip per row
-    ptrdiff_t row_skip = (MAX_X-MIN_X)/STEP_SIZE;
-    // get starting point in the mmapped file - t_num rows in
-    pinfo* local_fptr = FPTR_START+(row_skip*t_num);
-
-    for (FLOAT y=MIN_Y + t_start; y<MAX_Y; y+=(NUM_THREADS*STEP_SIZE))
-    {
-        for (FLOAT x=MIN_X; x<MAX_X; x+=STEP_SIZE)
-        {
-            pinfo* p=local_fptr++;
-            local_inside += mpoint(x, y, p, MAX_ITER);
-        }
-        // skip ahead the relevant number of lines
-        local_fptr += (row_skip * (NUM_THREADS-1));
-    }
-    pthread_mutex_lock(&acc_lock);
-    inside_points += local_inside;
-    pthread_mutex_unlock(&acc_lock);
-}
 
 int main(int argc, char* argv[])
 {
     printf("mapped file %d at %p %llu bytes\n", fd, fptr, mapsize);
     printf("Current MAX_ITER: %d\n", fheader->max_iter);
 
-    pthread_t t_handle[NUM_THREADS];
-    int t_num[NUM_THREADS];
-
-    // setup global read-only vars //BADBADBAD (but could be worse)
-    FPTR_START = fptr;
-    STEP_SIZE = step;
-
-    printf("Using %d threads\n", NUM_THREADS);
-
-    pthread_mutex_init(&acc_lock, NULL);
-    for (int nt=0; nt < NUM_THREADS; nt++)
-    {
-        t_num[nt] = nt;
-        pthread_create(&t_handle[nt],
-                NULL, worker_start, reinterpret_cast<void*>(&t_num[nt]));
-    }
-    for (int nt=0; nt < NUM_THREADS; nt++)
-    {
-        pthread_join(t_handle[nt], NULL);
-    }
+    worker_run(fptr, step);
 
     fheader->max_iter += MAX_ITER;
     fheader->binary_digits = BINARY_DIGITS;
     int max_iter;
 };
 
+long mpoint(FLOAT r,
+            FLOAT i,
+            pinfo* p,
+            int old_max_iter=0);
+void* worker_start(void* arg);
+void worker_run(pinfo* fptr, const FLOAT step);
 
 #endif
+#include "brotmap.h"
+#include <math.h>  // for NAN. Not in the C++ library...
+
+const FLOAT BAILOUT = 4.0;
+
+// mpoint(real, image, ...) -> 1 if mset else 0
+long mpoint(FLOAT r,
+            FLOAT i,
+            pinfo* p,
+            int old_max_iter)
+{
+    if (isnan(p->x)) {
+        // we've already processed this entry -
+        // and it's not part of the Mset
+        return 0;
+    }
+    FLOAT x2, y2;
+    FLOAT x = p->x;
+    FLOAT y = p->y;
+    int k = MAX_ITER;
+
+#ifdef CARDIOID_OPT
+    // based on 'Optimizations' section in wikipedia
+    // http://en.wikipedia.org/wiki/Mandelbrot_set#Optimizations
+    double roff = (r-0.25);
+    double isq = i*i;
+    double dist = roff*roff + isq;
+    if (dist * (dist + roff) < 0.25*isq)
+    {
+        return 1;
+    }
+
+    roff = r+1.0;
+    if (roff*roff + isq < 1.0/16.0)
+    {
+        return 1;
+    }
+#endif
+    // this is the core 'inner loop'.
+    // It should be fast, which is why it doesn't
+    // have lots of whitespace in it ;)
+    //
+    // of course this is massively parallelizable
+    do {
+        x2 = x*x;
+        y2 = y*y;
+        if ((x2+y2) >= BAILOUT) break;
+        y = 2.0*x*y+i;
+        x = x2-y2+r;
+    } while (--k);
+
+    if (!k)
+    {
+        // we ran out of iterations. Up to MAX_ITER,
+        // this point seems to be part of the mset.
+        // Store current values of x and y so we can
+        // carry on later.
+        p->x = x;
+        p->y = y;
+        return 1;
+    }
+    else
+    {
+        // this is definitely not part of the mset
+        // (rounding errors excepted). We want to store
+        // that fact, together with an iteration count
+        // and the magnitude of the calculation at that
+        // point (so we can do smooth renderings)
+        p->x = NAN;
+        p->itercount = (old_max_iter + (MAX_ITER - k));
+        return 0;
+    }
+}
+#include "brotmap.h"
+#include <iostream>
+#include <stddef.h>
+#include <pthread.h>
+
+extern int MIN_X, MIN_Y, MAX_X, MAX_Y;
+extern float STEP_SIZE;
+extern pinfo* FPTR_START;
+extern unsigned long inside_points;
+
+pthread_mutex_t acc_lock;
+
+void* worker_start(void* arg)
+{
+    int t_num = *reinterpret_cast<int*>(arg);
+    FLOAT t_start = t_num*STEP_SIZE;
+
+    long local_inside = 0;
+
+    // get the number of points to skip per row
+    ptrdiff_t row_skip = (MAX_X-MIN_X)/STEP_SIZE;
+    // get starting point in the mmapped file - t_num rows in
+    pinfo* local_fptr = FPTR_START+(row_skip*t_num);
+
+    for (FLOAT y=MIN_Y + t_start; y<MAX_Y; y+=(NUM_THREADS*STEP_SIZE))
+    {
+        for (FLOAT x=MIN_X; x<MAX_X; x+=STEP_SIZE)
+        {
+            pinfo* p=local_fptr++;
+            local_inside += mpoint(x, y, p, MAX_ITER);
+        }
+        // skip ahead the relevant number of lines
+        local_fptr += (row_skip * (NUM_THREADS-1));
+    }
+    pthread_mutex_lock(&acc_lock);
+    inside_points += local_inside;
+    pthread_mutex_unlock(&acc_lock);
+}
+
+void worker_run(pinfo* fptr, const FLOAT step) {
+    pthread_t t_handle[NUM_THREADS];
+    int t_num[NUM_THREADS];
+
+    // setup global read-only vars //BADBADBAD (but could be worse)
+    FPTR_START = fptr;
+    STEP_SIZE = step;
+
+    std::cout << "Using " << NUM_THREADS << " threads" << std::endl;
+
+    pthread_mutex_init(&acc_lock, NULL);
+    for (int nt=0; nt < NUM_THREADS; nt++)
+    {
+        t_num[nt] = nt;
+        pthread_create(&t_handle[nt],
+                NULL, worker_start, reinterpret_cast<void*>(&t_num[nt]));
+    }
+    for (int nt=0; nt < NUM_THREADS; nt++)
+    {
+        pthread_join(t_handle[nt], NULL);
+    }
+};