I wrote a edge walker to measure iteration scaling factors for the Mandelbrot boundary. The is similar to what Gerrit has been doing except I am looking at relative small iteration counts and a resolution that captures the entire boundary.

For any finite iteration count the iterative calculation can be re-written as a polynomial Pn(C). The edge walker extracts the iso-contour:

Pn(C) - Escape_limit = 0

Then measures the length. The order of Pn(C) goes 2^n. In a Taylor expansion of a real function every additional inflection point requires an increment to the order of the real poly. I suspect the boundary follows some similar order to complexity relationship. Unfortunately I do not know how to express this formally.

Since I don't have an analytical method to relate resolution to error I used a cannery method. The calculations are done at 1.0e-7 and 1.0e-8 resolution. When the two results start to diverge I know that he 1.0e-7 is missing detail and the 1.0e-8 will start failing in 3 or 4 iterations.

The scaling graph shows an asymptotic approach to 1.165. This is at the edge of the 100M resolution so I need to do some longer runs to verify this.

The more interesting result is looking at the ratio of the main body vs the rest of the boundary. Here we see a steady increase of the ratio per iteration. If this continues then any simple measure at finite resolution will not be a good estimate in the limit.

I am attaching the program code. The build command is

gcc -O1 Brot_walker.cpp -o Brot_walker -lm

Example command lines:

>Brot_walker -e 10 -l 10 -n 17 -r 1000000 -p -.75 .000001 -p -2 0 -p -.75 -.000001

>Brot_walker -h

`// Non-attribution public domain. No rights reserved.`

// Segfaults and floating point errors are not my fault.

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

#include <unistd.h>

#include <fenv.h>

//#include <xmmintrin.h>

// BUILD:

// gcc -O1 Brot_walker.cpp -o Brot_walker -lm

// icc -O1 Brot_walker.cpp -o Brot_walker -lm

int brot(double r, double i, double Escape, int n){

int a;

double zr = r;

double zi = i;

if(n==-1){ // if n==-1 do sphere for testing

if(((r*r+i*i)-(Escape*Escape))>0){

return(0);

}else{

return(1);

}

}else if(n==-2){ // if n==-2 do square for testing

if((fabs(r)>Escape) ||(fabs(i)>Escape)){

return(0);

}else{

return(1);

}

}else if(n==-3){ // if n==-3 do shamrock for testing

//if((fabs(r)>Escape) ||(fabs(i)>Escape)){

if(((fabs(r)+.1)*(fabs(i)+.1))>Escape){

return(0);

}else{

return(1);

}

}else {

for(a=0;a<n;a++){

double tmp_zr;

tmp_zr = zr*zr - zi*zi +r;

zi = 2*zr*zi + i;

zr = tmp_zr;

if(((zr*zr+zi*zi)-(Escape*Escape))>0){

return(0);

}

}

return(1);

}

}

int help(){

const char * h ="//Edge walker (counter clockwise).\n"

"// The edge walker works on a grid with units d=1/resolution (-r).\n"

"// The walker state consists of a position and a direction.\n"

"// position: r=pos_r*d and i=pos_i*d.\n"

"// direction: dir { 0=( 0, i), 1=(-1, 0), 2=( 0, -i), 3=( 0, 1)\n"

"//\n"

"// The walker is assumed to be standing on a point in the set with\n"

"// the right ( 0, 1) being !set. The walker is pointed in the ( 0, i)\n"

"// direction it its frame of reference.\n"

"//\n"

"// In the next walker state (step) is found by finding the first NN cell\n"

"// in the set starting with the upper right ( 1, 1) and scanning counter\n"

"// clockwise. The cell in the CC direction is !set.\n"

"//\n"

"// The edge walker takes a path of unit steps in the real or imaginary direction\n"

"// or diagonal steps at 45. Just counting step distance is not a good measure\n"

"// since this has lots of wiggles. For this reason distance needs to be measured\n"

"// for several steps to avoid measuring tracking zig zags.\n"

"//\n"

"// Usage:\n"

"// Brot_walker -e Escape_d -l meter_steps -n iters -r unit_res [-p im re]\n"

"//\n"

"// -n number of iterations of Z^2+C. \n"

"// -e should be small for small iteration count.\n"

"// -l should be in the 10 range to minimize the zig zag error.\n"

"// -r resolution can be in the 10M to 100M range. Time is linear in res.\n"

"// -p point to start measuring from in the CC direction back to point of origin.\n"

"// -p You can specify 1024 points if you want.\n"

"// The starting pixel for point measurement is the closes walker step to point.\n";

printf("%s",h);

exit(1);

}

int main(int argc, char *argv[]){

//Define order to look for next inside edge point.

int look_r[8] = { 1, 0,-1,-1,-1, 0, 1, 1};

int look_i[8] = { 1, 1, 1, 0,-1,-1,-1, 0};

int next_dir[8] ={ 3, 0, 0, 1, 1, 2, 2, 3};

double total_l=0;

// Keep the last 1024 points for long step measurements (-l).

int trail_r[1024];

int trail_i[1024];

int points=0; // Number of points being measured.

double pDD[1024]; // Closest distance to boundary.

double pr[1024]; // Real part of point

double pi[1024]; // imaginary part of point.

double pl[1024]; // Measured distance to starting point.

int pos_r, pos_i;

int stop_r, stop_i;

double r,i;

long step;

int dir;

int opt;

double Escape,d;

int Length;

int resolution;

int n;

int a;

for(a=1;a<argc;a++) {

if( strcmp("-e",argv[a]) == 0) {

a++;

Escape = (double) atof(argv[a]);

}else if( strcmp("-n",argv[a]) == 0) {

a++;

n = atoi(argv[a]);

}else if( strcmp("-l",argv[a]) == 0) {

a++;

Length = atoi(argv[a]);

//}else if( strcmp("-ftz",argv[a]) == 0) {

//_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);

}else if( strcmp("-p",argv[a]) == 0) {

a++;

pr[points] = (double)atof(argv[a]);

a++;

pi[points] = (double)atof(argv[a]);

pDD[points] = 1000000000; // big number

pl[points] = 0;

points++;

}else if( strcmp("-r",argv[a]) == 0) {

a++;

resolution = atoi(argv[a]);

d= 1.0/resolution;

} else {

help();

}

}

printf("// Brot_walker -n %d -e %g -r %d -l %d ", n, Escape, resolution, Length);

for(a=0;a<points;a++){

printf("-p %g %g ",pr[a],pi[a]);

}

printf("\n");

// Start at (0,0) and move in the +r direction until finding an edge.

pos_r=0;

pos_i=0;

while(brot((pos_r+1)*d, pos_i*d,Escape, n)){

pos_r++;

}

printf("start pos %d %d\n",pos_r, pos_i);

dir = 0; // Positive i direction.

// (r,i) is inside the edge and (r+d,i) is outside

trail_r[0] = pos_r;

trail_i[0] = pos_i;

stop_r=pos_r;

stop_i=pos_i;

step = 0;

while((pos_r!=stop_r)||(pos_i!=stop_i)||(step<2*Length)){

step ++;

int look_dir = (2*dir)&7;

r = (pos_r+look_r[look_dir])*d;

i = (pos_i+look_i[look_dir])*d;

while(brot(r, i, Escape, n)==0){

look_dir = (look_dir +1)&7;

r = (pos_r+look_r[look_dir])*d;

i = (pos_i+look_i[look_dir])*d;

}

//printf("here %d %d %d %g %g\n",pos_r, pos_i,dir ,r,i);

pos_r += look_r[look_dir];

pos_i += look_i[look_dir];

dir = next_dir[look_dir];

trail_r[step&1023]=pos_r;

trail_i[step&1023]=pos_i;

if(step == Length){

stop_r=pos_r;

stop_i=pos_i;

}

if(step>=Length){

r = d*(pos_r - trail_r[(step-Length)&1023]);

i = d*(pos_i - trail_i[(step-Length)&1023]);

double tmp_l = sqrt(r*r+i*i)/Length;

total_l = total_l + tmp_l;

for(a=0;a<points;a++){

pl[a] = pl[a] + tmp_l;

double DD = (pr[a]-d*pos_r)*(pr[a]-d*pos_r)+(pi[a]-d*pos_i)*(pi[a]-d*pos_i);

if(DD < pDD[a]){

pDD[a]=DD;

pl[a]=0;

}

}

}

}

printf("total lenght %g steps %ld\n",total_l,step);

for(a=0;a<points;a++){

printf("point (%g,%g) lenght to start %g point to edge %g\n",pr[a],pi[a],pl[a],sqrt(pDD[a]));

}

return(0);

}