Are the intriguing and lovely Mandelbrot Set hoops and curls the result of floating point computation inaccuracy?
I have written various Mandelbrot Set implementations, such as a dynamic zoom and playback. Some use fixed point arithmetic, others use the FPU.
I have seen this question which suggests that every bud is a mathematically smooth shape, with smaller buds around.
Are the parades of sea-horse shapes and so on, a side effect of the limitations of computer floating point arithmetic, and not the actual Mandelbrot Set?
Sea horse? added by Spektre:
What I have been trying to say, is that floating point arithmetic, whether fixed point or fixed significance, cannot hold the true result of the iteration steps. The interesting part of the Mandelbrot set is near the boundary, and in this region the iteration coordinates can dither for thousands of iterations in cyclic near-repetitions before eventually "escaping".
My question is: does the arithmetic fail in such a fashion as to cause the patterns? As far as I have been able to understand, the perfect Mandelbrot set is actually smoothly shaped buds arranged around other buds, ad infinitum. Commenters have said that the better the arithmetic, the better the famous seahorse etc. shapes are, and that can be seen when a poor implementation produces a blurry image. But it only strengthens my question: the more precise the arithmetic, the more precisely and regularly the arithmetic fails until, as the coordinates change, there is a discontinuity and it progresses to failure in a slightly different way.
Anyway, here is a C function which iterates one point using the x87 FPU. The code isn't recent, and there is scope to improve it by taking advantage of the difference between squares, which is still on my ancient "to-do" list.
int MAXRAD = 4;
int K_LIMIT = 5000;
double REAL8, IMAG8;
int iterate (void)
// calculate Mandelbrot iterations of REAL8, IMAG8
// return iterations
{
int iters;
__asm {
FILD DWORD PTR MAXRAD ;MAX R^2
FLD QWORD PTR IMAG8 ;INIT Y VALUE
FLD QWORD PTR REAL8 ;INIT X VALUE
FLD ST(1) ;WORKING Y = IMAG
FLD ST(1) ;WORKING X = REAL
MOV ECX,DWORD PTR K_LIMIT
MOV BX,0100h ;MASK FOR C0 FLAG
ALIGN 4
MLOOPB: ;ITERATE ST0 ST1 ST2 ST3 ST4 ST5 ST6 ST7
; X Y REAL IMAG 4.0
FLD ST(0) ;PUSH X X X Y REAL IMAG 4.0
FMUL ST(1),ST ;X * X X X^2 Y REAL IMAG 4.0
FMUL ST,ST(2) ;X * Y XY X^2 Y REAL IMAG 4.0
FADD ST,ST(0) ;2 * XY 2XY X^2 Y REAL IMAG 4.0
FADD ST,ST(4) ;2XY+IMAG Y' X^2 Y REAL IMAG 4.0
FXCH ST(2) ;Y', Y Y X^2 Y' REAL IMAG 4.0
FMUL ST,ST(0) ;Y * Y Y^2 X^2 Y' REAL IMAG 4.0
FLD ST(0) ;PUSH Y^2 Y^2 Y^2 X^2 Y' REAL IMAG 4.0
FADD ST,ST(2) ;Y^2 + X^2 R^2 Y^2 X^2 Y' REAL IMAG 4.0
FCOMP ST(6) ;TEST & POP Y^2 X^2 Y' REAL IMAG 4.0
FNSTSW AX ;STATUS
FSUB ;X^2 - Y^2 ... Y' REAL IMAG 4.0
FADD ST,ST(2) ;X' X' Y' REAL IMAG 4.0
TEST AX,BX ;CHECK C0
LOOPNZ MLOOPB ;LOOP IF (ITERS > 0) and (RADIUS^2 < 4)
FNINIT ;INIT COPROCESSOR TO CLEAR STACK
MOV EAX,DWORD PTR K_LIMIT
SUB EAX,ECX ;DONE, LOOP WAS COUNTED DOWNWARD
MOV DWORD PTR iters,EAX
}
return iters;
}
Note that there are no memory load/store operations within the iteration loop.
I also asked the question on StackExchange Mathematics here.
The curlicues and seahorse shapes and buds and all the other amazing things you see in the Mandelbrot Set are for real, and are not a result of computation rounding. In fact, the more significant figures in your computations - the less rounding errors - the more intricate the calculated shapes become. Personal warning: coding of the Mandelbrot Set can become addictive!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With