Edit: I think the suggestion in the answer of kuroi neko is also a very good idea if you do not care about "incremental" computation, but have a fixed number of iterations.
You should use
vector<point_t>
instead ofvector<point_t*>
.A
vector<point_t*>
is a list of pointers topoint_t
. Each point is stored at some random location in the memory. If you iterate over the points, the pattern in which memory is accessed looks completely random. You will get a lot of cache misses.On the opposite
vector<point_t>
uses continuous memory to store the points. Thus the next point is stored directly after the current point. This allows efficient caching.You should not call
erase(it);
in your inner loop.Each call to
erase
has to move all elements after the one you remove. This has O(n) runtime. For example, you could add a flag topoint_t
to indicate that it should not be processed any longer. It may be even faster to remove all the "inactive" points after each iteration.It is probably not a good idea to draw individual pixels using
cairo_rectangle
. I would suggest you create an image and store the color for each pixel. Then draw the whole image with one draw call.
Your code could look like this:
for(unsigned int i = 0; i < iterations; i++){
double r,g,b;
r = (double)i+1 / (double)iterations;
g = 0;
b = 0;
for(vector<point_t>::iterator it=points->begin(); it!=points->end(); ++it) {
point_t& p = *it;
if(!p.active) {
continue;
}
p.Z = (p.Z * p.Z) + p.C;
if(abs(p.Z) > 2.0) {
cairo_set_source_rgba(cr, r, g, b, 1);
cairo_rectangle (cr, p.x, p.y, 1, 1);
cairo_fill (cr);
p.active = false;
}
}
// perhaps remove all points where p.active = false
}
If you can not change point_t
, you can use an additional vector<char>
to store if a point has become "inactive".