Today I have had a look at the BASIC program that has been presented in this article. I was looking for some ways of speeding it up a bit, as drawing the fractal requires a lot of time.
First of all, I have been looking for a way to compute the points a bit faster. After reading this webpage (paragraph “Further Optimization”), I realized that the iterative process could be coded in a simpler way. In facts, the iterations can be coded as follows (please refer to the Freebasic code of the previous article):
for k = 1 to 250 r_squared = real_part * real_part i_squared = im_part * im_part if (r_squared + i_squared) > 4 then is_mandelbrot = 0: goto escape im_part = 2 * real_part* im_part + im0 real_part = r_squared - i_squared + real0 next k
This way, each iteration is faster and the code is easier to understand. This time, r_squared and i_squared are actually the squares of the complex part and imaginary part of the complex number.
The Mandelbrot set condition is now tested before the computation of the imaginary part and of the real part of Zn+1. This doesn’t change anything and every colour matches the ones of the image created by the previous version of the program. The only thing to fix is the number of iterations when the iterations loop is exited. Since the Mandelbrot set condition is tested before evaluating Zn+1, the number of iterations on loop exiting must be reduced by one. Otherwise, colours will be off.
Another improvement deals with precalculating some values. I0 and R0 can be precalculated at the beginning of the program, right before Mandelbrot points computation. An array has been set up containing the values of I0 (evaluated for any Y), and the values of R0 (evaluated for any X). Afterwards, those values can be retrieved by looking for array elements, which is faster than computing them each time. Still, as each I0 or R0 value is used more times by the program, the element retrieved from the array is assigned to a variable before each iteration. This way, while doing the computations, the BASIC interpreter must only access a simple variable and not an array element, which is slower.
As this fractal image enjoys symmetry, a mirror plotting can be coded. This way, we get a dramatic speed improvement. So, after one point has been calculated, it is just possible to plot two points at a time. Symmetry is along the X axis (or, better, the real axis), so the first point in the top left corner of the screen must be copied to the bottom left corner of the screen, and so on.
The following improved BASIC program just shows off all of these concepts.
Since we have 25 characters rows on the screen, and 25 is an odd number, I had to take out one row. This way, the remaining 24 rows can be splitted into 12 computed rows and 12 mirrored rows. Hiding the missing row seemed to be easy, but some problems did arise during image interlacing (after the fractal image has been drawn, you may press space to interlace the image). As the first row of computed points is now one character far from the upper border, during image interlacing a graphics artifact did show off. Some points of the image were interlacing with a part of the first empty character row. The fix was quite easy. I had to emulate the missing border by using 7 expanded sprites. Those have the same colour as the border, so they cannot be seen.