4

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:

Sea horse?


Edit: following the bounty offered.

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.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • 3
    Can you post a picture of the seahorse shapes on the Mandelbrot Set? – Ṃųỻịgǻňạcểơửṩ Apr 30 '18 at 22:52
  • Following a downvote, to clarify: I don't believe it is possible to generate a Mandelbrot Set image without iterating. Everything I have seen, such as for calculating the distance of a point from the M-Set, always requires iteration. With a limit to the precision of floating point arithmetic, and the large number of iterations, the computation cannot be accurate, so how true a representation is the image generated? This is particularly so in the neighbourhood of the M-Set, where the function value can dither for a large number of iterations around two or more attractor points before escaping. – Weather Vane Feb 26 '19 at 18:14
  • @Ṁữŀlɪgắnậcễơưṩᛗ Was curious and I think I found one. I added an image to the question. In the caption of the window are also coordinates, zoom and max iterations count used ... The code and demo is here [Can't find a way to color the Mandelbrot-set the way i'm aiming for](https://stackoverflow.com/a/56197067/2521214) – Spektre May 19 '19 at 14:00
  • @WeatherVane no the FPU errors produce pixelated artifacts on their own ... the shapes are from the complex math itself and has nothing to do with the FPU roundings. – Spektre May 19 '19 at 14:03
  • @WeatherVane Can you possibly show your code (and possible inaccuracies) so I can add a language tag? I was hoping to have a better answer here. – S.S. Anne Aug 28 '19 at 18:18
  • @JL2210 your bounty is a generous offer to attract attention to the question. Do you mean the code that iterates one point? After making so many versions that produce similar results to others, I don't think that scaling the coordinates of each point would be an issue. I have many versions kicking around. The better ones use assembler with hand-crafted register use, in two varieties a) fixed point and b) using FPU stack. None of the code is recent but I'll post something soon. – Weather Vane Aug 28 '19 at 18:39
  • @WeatherVane I think language-related questions attract more attention than questions that don't include code. I think the most common language that you've written this in would work. – S.S. Anne Aug 28 '19 at 18:54
  • @JL2210 despite what they say about C code optimisers my C iterations always worked very slowly, and I found that nothing short of "last cycle scraping" in assembler would do – considering the *billions* of iterations necessary. I'm not sure how relevant the code really is. I'll try to add *something* to my question soon, though. – Weather Vane Aug 28 '19 at 18:59
  • 1
    One relatively easy way to test this with the code you have is to change the precision of the FPU using `FLDCW` to change between 24, 53, and 64 bit precision. You might also want to include an `FADD ST(0),0` after your two init loads to get the loaded values rounded, since `FLD` is not effected by the precision. – 1201ProgramAlarm Aug 31 '19 at 03:54

1 Answers1

7

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!

Jim Phillips
  • 86
  • 1
  • 2
  • 4
    The question has not attracted very much interest. I accept your answer although I am not totally convinced that after many iterations the arithmetic does not gain an increasing error, and then meet the terminating condition in a way that produces the patterns. One day I will experiment with a fixed-point arithmetic test on a very small area, that is fairly shallow, extending the number of bits storage (perhaps on disk) at each iteration so as not to lose any significance. Fixed point is good because the values are always in the range ±4. – Weather Vane Oct 10 '18 at 16:43
  • @WeatherVane: ... and if magnitudes get very small, they probably stay small (and thus are inside the set), so fixed absolute precision (fixed point) is fine vs. fixed relative precision (floating point). The first program I ever optimized (by modifying the gcc asm output) was a C Mandelbrot program on my Atari Mega4 STe (68020) that I typed in from a magazine. :) It used fixed-point integer. – Peter Cordes Aug 28 '19 at 20:41