Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Mandelbrot Perturbation Demonstration written by Kouzeru,
- // credits goes to pianomiles, and CSA in partial contribution.
- // sukop, implementation of double-double arithmetics reference.
- // Instructions:
- // Use mouse, hover to the spot and scroll to zoom, click to drag.
- // Increase roughness as far as you zoomed to see more in details,
- // as it costs more computation work, keep the roughness low as
- // possible while keeping details.
- // When the image goes pixelated or glitched, right-click to it.
- // Or just switch precision mode into appropriate choice.
- // Increase the color speed when the spots hard to distinguish.
- float zoom,scl,maxIT,cmag,bailOut,logBOut,log2,deg,fpfAvg=0;
- int lMillis,mHover,frames,maxITl,zooml,refIT,precMode;
- double[] xPos,yPos,xRef,yRef,xRefO,yRefO;
- boolean infoShow;String precName[]={
- "Single-Precision delta","Double-Precision delta",
- "Single-Precision main","Double-Precision main",
- "Quadruple-Precision main"};
- PFont font;
- //Double-double precision arithmetic methods.
- //I'm going to call them quad here to avoid confusion.
- //A reference which is actually rewritten from Python to Java:
- //https://github.com/sukop/doubledouble/blob/master/doubledouble.py
- static class dd{private static double r,e,s,t,u,v,f,g;
- private static double[] qs(double x,double y){
- r = x+y;e = y-(r-x);double[] z={r,e}; return z;}
- private static void ts(double x,double y){
- r = x+y;t = r-x;e = x-(r-t);e+= y-t;}
- private static void pr(double x,double y){
- u = x*134217729;v = y*134217729;
- u-= u-x; v-= v-y; f = x-u; g = y-v;
- r = x*y; e = u*v-r; e+= u*g+f*v; e+= f*g; }
- private static void sq(double x){
- u = x*134217729; u-= u-x; f = x-u;
- r = x*x; e = u*u-r; e+= 2*u*f; e+= f*f; }
- static double[] add(double[] x,double[] y){
- ts(x[0], y[0]); e+=x[1]+y[1];return qs(r,e);}
- static double[] sub(double[] x,double[] y){
- ts(x[0],-y[0]); e+=x[1]-y[1];return qs(r,e);}
- static double[] mul(double[] x,double[] y){
- pr(x[0],y[0]); e+=x[0]*y[1]+x[1]*y[0]; return qs(r,e);}
- static double[] div(double[] x,double[] y){
- t = x[0]/y[0]; pr(t,y[0]); s = x[0]-r-e+x[1];
- s = (s-t*y[1])/y[0]; return qs(t,s);}
- static double[] squ(double[] x){
- sq(x[0]); e+=2*x[0]*x[1]; return qs(r,e);}
- static double[] sqr(double[] x){
- if(x[0]<=0){ if(x[0]<0||x[1]<0){
- double[] z={Double.NaN,Double.NaN}; return z;}}
- t = java.lang.Math.sqrt(x[0]); sq(x[0]);
- s = x[0]-r-e+x[1]; s/= t+t; return qs(t,s); };
- static double[] neg(double[] x){
- double[] z={-x[0],-x[1]}; return z;}
- static double[] abs(double[] x){double[] z={0,0};
- if(x[0]<0){z[0]=-x[0]; z[1]=-x[1];
- }else{z[0]=x[0]; z[1]=x[1];} return z;}
- static double[] doub(double[] x){
- double[] z = { x[0]*2, x[1]*2};return z;}
- static double[] half(double[] x){
- double[] z = { x[0]/2, x[1]/2};return z;}
- static double[] copy(double[] x){
- double[] z = { x[0], x[1]};return z;}
- static double[] parse(double x){
- double[] z = { x,0 }; return z;}
- //AAAAA BASIQUE DOUBLE DOUBLE TO STRING VICEVERSA CONVERSION
- static boolean dSgn; static int dExp; static int[] dDgt;
- private static int p(char x){ //just to make the code short
- return Integer.parseInt(String.valueOf(x));}
- private static void digitsStr(String x){
- int[] d=new int[40]; int b,e=d.length,f,g=0,h=0,
- i=x.charAt(0)=='-'||x.charAt(0)=='+'?1:0,j=x.lastIndexOf('e');
- if(j<0){j=x.lastIndexOf('E');if(j<0){j=x.length();}}
- f=x.lastIndexOf('.');f=f<0?j:f;
- while(i<f){if(p(x.charAt(i))>0){break;}i++;}
- while(i<f){d[h++]=p(x.charAt(i++));g++;}
- if(g>0){g--;}if(f<j){i++;}
- if(h==0){while(i<j){g--;if(p(x.charAt(i))>0){
- break;}i++;}if(i==j){g=0;}}
- while(i<j&&h<e){d[h++]=p(x.charAt(i++));}
- while(h<e){d[h++]=0;}i=j+1;j=x.length();b=0;if(i<j){
- if(x.charAt(i++)=='-'){while(i<j){b=b*10-p(x.charAt(i++));}
- }else{while(i<j){b=b*10+p(x.charAt(i++));}}}
- dSgn=x.charAt(0)=='-';dExp=b+g;dDgt=d;
- }
- private static String digitsFixed(int s,int e,int[] d){
- int i=d.length-1,j,k;d[--i]|=d[i+1]<5?0:1;
- while(d[i]==0&&i>0){i--;};
- String a=(s!=0)?"-":"";int b=0,c=i,f=0;
- if(e<0){a+="0.";f++;while(++e!=0&&b<c){a+="0";b++;f++;}b=0;
- }else{e++;while(b<e&b<c){a+=d[b++];f++;}
- while(b++<e&b<c){a+="0";f++;}a+=".";}
- while(b<c){a+=d[b++];f++;}return a;
- }
- static double[] parse(String x){
- int g,h,i,j; double a=Double.parseDouble(x),b=0,k;
- digitsStr(String.format("%1.40e",a<0?-a:a));
- int e=dExp; int[] c=dDgt; digitsStr(x); int[] d=dDgt;
- for(g=0,h=i=c.length-1;i>=0;i--){
- j=d[i]-c[i]-g+10;g=j<10?1:0;c[i]=j%10;}
- if(g!=0){k=-1;while(++i<h){c[i]=9-c[i];}
- c[i]=10-c[i];}else{k=1;}
- for(j=0;j<h;j++){if(c[j]>0){break;}}
- b=0;while(j<=h){b+=c[h--]*k;k*=10;}
- k/=10;e-=j;i=0;if(e<0){while(i-->e){
- k*=10;}}else{while(i++<e){k/=10;}}
- b=(a<0?-b:b)/(k<0?-k:k);
- double[] z={a,b}; return z;
- }
- static String string(double[] x){
- digitsStr(String.format("%1.40g",x[0]));
- boolean a=dd.dSgn;int c=dd.dExp; int[] e=dDgt;
- digitsStr(String.format("%1.40g",x[1]));
- boolean b=dd.dSgn;int d=dd.dExp; int[] f=dDgt;
- int g=0,h=e.length,i,j;
- if(f[0]>0){d=c-d;i=h;if(a!=b){
- while(--i>=0){j=i>=d?f[i-d]:0;
- j=e[i]-j-g+10;g=j<10?1:0;f[i]=j%10;}
- if(g!=0){while(++i<h){f[i]=9-f[i];}
- f[i-1]++;}i=j=0;
- while(i<h){if(f[i]>0){break;}i++;}c-=i;
- }else{while(--i>=0){j=i>=d?f[i-d]:0;
- j=e[i]+j-g+1 ;g=j<10?1:0;f[i]=j%10;}
- i=j=0;if(g==0){f[0]=1;j++;c++;}g=0;}
- while(i<h){e[j++]=f[i++];}
- while(j<h){e[j++]=0;}
- }return digitsFixed((a?1:0)^g,c,e);
- };
- }
- int[] HSV2RGB(float h,float s,float v){
- float r,g,b,k;s=s<0?0:s<1?s:1;v=v<0?0:v<1?v:1;
- k=0.5-sin(deg*(((((h+=3)%1)*60)-30)));
- r=(h+5)%6<3?1:0;r+=(((h+4)%6<3?1:0)-r)*k;
- g=(h+3)%6<3?1:0;g+=(((h+2)%6<3?1:0)-g)*k;
- b=(h+1)%6<3?1:0;b+=(((h+0)%6<3?1:0)-b)*k;
- r=1+(r-1)*s;g=1+(g-1)*s;b=1+(b-1)*s;
- r*=255*v;g*=255*v;b*=255*v;
- int[] col={(int)r,(int)g,(int)b};
- return col;
- }
- int setColour(float IT){if(IT<maxIT){
- IT = IT>0?sqrt(IT*cmag):0;
- float col = (sin(deg*IT*10)+1)/2;
- float br = (cos(deg*IT*40) + 1)/2;
- float h = (((col+0.05))%1)*6;
- float s = min(br*2,1);
- float v = (1-(br*br));
- int[] c = HSV2RGB(h,s,v);
- return color(c[0],c[1],c[2]);
- }else{return color(0);}
- }
- double[] refX,refY;
- float[] refXf,refYf;
- //precalculate single point with quad precision
- float precalc(double[] x,double[] y){
- double[] a=dd.copy(x),b=dd.copy(y),
- a2=dd.squ(a),b2=dd.squ(b);int IT=0;
- if(precMode==0){
- refXf= new float[(int) maxIT+4];
- refYf= new float[(int) maxIT+4];
- refXf[0]=(float)a[0];refYf[0]=(float)b[0];
- }else{
- refX = new double[(int) maxIT+4];
- refY = new double[(int) maxIT+4];
- refX[0]=a[0];refY[0]=b[0];
- }
- while(IT++<maxIT){b=dd.add(dd.doub(dd.mul(a,b)),y);
- a=dd.add(dd.sub(a2,b2),x);a2=dd.squ(a);b2=dd.squ(b);
- if(precMode!=0){refX[IT]=a[0];refY[IT]=b[0];}else{
- refXf[IT]=(float)a[0];refYf[IT]=(float)b[0];}
- if(a2[0]+b2[0]>=4){break;}
- }return (refIT=IT);
- }
- //precalculate single point with double precision
- float precalcd(double x,double y){
- double a=x,b=y,a2=a*a,b2=b*b;int IT=0;
- if(precMode==0){
- refXf= new float[(int) maxIT+4];
- refYf= new float[(int) maxIT+4];
- refXf[0]=(float)a;refYf[0]=(float)b;
- }else{
- refX = new double[(int) maxIT+4];
- refY = new double[(int) maxIT+4];
- refX[0]=a; refY[0]=b;
- }
- while(IT++<maxIT){b=2*a*b+y;a=a2-b2+x;
- if(precMode!=0){refX[IT]=a;refY[IT]=b;}else{
- refXf[IT]=(float)a;refYf[IT]=(float)b;}
- if((a2=a*a)+(b2=b*b)>=4){break;}
- }return (refIT=IT);
- }
- //iterate delta with double precision
- float iteratedd(double x,double y){
- int IT=0;x+=xRefO[0];y+=yRefO[0];
- double a=x,b=y,e,f,c=refX[0],d=refY[0],
- g=c+x,h=d+y,i,j;while(IT++<refIT){
- i =a*c;i-=b*d;j =a+b;j*=a-b;
- b*=a+c;b+=a*d;b+=b+y;a =i+i+j+x;
- c=refX[IT];d=refY[IT];
- e=a+c;f=b+d;i=e*e;j=f*f;
- if(i+j>=bailOut){
- i=log((float)(i+j));e-=g;f-=h;
- j=log((float)(e*e+f*f))/2;
- i=(logBOut-j)/(i-j);
- return (float)IT+log((float)i+1)/log2;
- }}return IT;
- }
- //iterate delta with single precision
- //wait wait, even with less type conversion,
- //it still running slow than double, what?
- float iterateds(double dx,double dy){
- int IT=0;dx+=xRefO[0];dy+=yRefO[0];
- float x=(float)dx,y=(float)dy,a=x,b=y,
- e,f,c=refXf[0],d=refYf[0],
- g=c+x,h=d+y,i,j;while(IT++<refIT){
- i =a*c;i-=b*d;j =a+b;j*=a-b;
- b*=a+c;b+=a*d;b+=b+y;a =i+i+j+x;
- c=refXf[IT];d=refYf[IT];
- e=a+c;f=b+d;i=e*e;j=f*f;
- if(i+j>=bailOut){
- i=log(i+j);e-=g;f-=h;
- j=log(e*e+f*f)/2;
- i=(logBOut-j)/(i-j);
- return (float)IT+log(i+1)/log2;
- }}return IT;
- }
- //iterate the set with quad precision
- float iterateq(double dx,double dy){
- double[] x = dd.add(dd.parse(dx),xPos),
- y = dd.add(dd.parse(dy),yPos),
- a=dd.copy(x),b=dd.copy(y),
- a2=dd.squ(a),b2=dd.squ(b);
- float m,n,o,p,q;int IT=0;
- while(IT++<maxIT){
- b=dd.add(dd.doub(dd.mul(a,b)),y);
- a=dd.add(dd.sub(a2,b2),x);
- a2=dd.squ(a);b2=dd.squ(b);
- if(a2[0]+b2[0]>=bailOut){
- m=(float)(a[0]-x[0]);
- n=(float)(b[0]-y[0]);
- p=log((float)(a2[0]+b2[0]));
- q=log(m*m+n*n)/2;
- o=(logBOut-q)/(p-q);
- return (float)IT+log(o+1)/log2;
- }
- }
- return IT;
- }
- //iterate the set with double precision
- float iterated(double x,double y){
- int IT=0; x+=xPos[0];y+=yPos[0];
- double a=x,b=y,a2=a*a,b2=b*b;
- while(IT++<maxIT){
- b=2*a*b+y;a=a2-b2+x;
- if((a2=a*a)+(b2=b*b)>bailOut){
- a2=log((float)(a2+b2));a-=x;b-=y;
- b2=log((float)(a*a+b*b))/2;
- a2=((double)logBOut-b2)/(a2-b2);
- return (float)IT+log((float)a2+1)/log2;
- }}return IT;
- }
- //iterate the set with single precision
- float iterates(double xd,double yd){
- int IT=0; xd+=xPos[0];yd+=yPos[0];
- float x=(float)xd,y=(float)yd;
- float a=x,b=y,a2=a*a,b2=b*b;
- while(IT++<maxIT){b=2*a*b+y;a=a2-b2+x;
- if((a2=a*a)+(b2=b*b)>bailOut){
- a2=log(a2+b2);a-=x;b-=y;
- b2=log(a*a+b*b)/2;
- a2=(logBOut-b2)/(a2-b2);
- return (float)IT+log(a2+1)/log2;
- }}return IT;
- }
- void setup(){
- size(640,480);background(0);
- font = createFont("Monospaced.bold",18);
- deg = atan(1)*4/180;
- lMillis=millis();
- scl = height;
- logBOut = log(4);
- log2 = log(2);
- cmag = 1;
- mHover = 0;
- precMode = 1;
- infoShow = true;
- xPos = dd.parse( "0.26544602163041845079010564709539");
- yPos = dd.parse("-0.003176395242688470419416969446745");
- xRef = dd.parse( "0.26544602163041845079010785861635");
- yRef = dd.parse("-0.0031763952426884704194213468422653");
- zooml= (int)(16*log(1.4432772E-23)/log2);
- maxITl= (int)(16*log(6400)/log2);
- zoom = exp((float)(zooml*log2/16));
- loadPixels();//frameRate(60);
- textFont(font,18);
- }
- void mouseWheel(MouseEvent e){
- zooml+=e.getCount();
- };
- void draw(){
- if(mousePressed){switch(mouseButton){
- case LEFT:{
- xPos =dd.add(xPos,dd.parse((double)(pmouseX-mouseX)*zoom/scl));
- yPos =dd.sub(yPos,dd.parse((double)(pmouseY-mouseY)*zoom/scl));
- break;
- }
- case RIGHT:{
- if(precMode<2){
- xRef=dd.add(xPos,dd.parse((double)((mouseX-width/2)/scl)*zoom));
- yRef=dd.sub(yPos,dd.parse((double)((mouseY-height/2)/scl)*zoom));
- }
- break;
- }
- }}
- if(keyPressed){switch(key){
- case 'z':{maxITl-=2;break;}
- case 'x':{maxITl+=2;break;}
- case 'a':{logBOut-=0.125;break;}
- case 's':{logBOut+=0.125;break;}
- case 'q':{cmag/=1.125;break;}
- case 'w':{cmag*=1.125;break;}
- case 'k':{precMode=0;break;} //use single delta
- case 'l':{precMode=1;break;} //use double delta
- case 'i':{precMode=2;break;} //use single iter
- case 'o':{precMode=3;break;} //use double iter
- case 'p':{precMode=4;break;} //use quad iter
- }}
- maxIT=exp((float)(maxITl*log2/16));bailOut = exp(logBOut);
- float lzoom=zoom;zoom=exp((float)(zooml*log2/16));
- double[] xTar = dd.add(xPos,dd.parse((double)(lzoom*((mouseX-width/2)/scl))));
- double[] yTar = dd.add(yPos,dd.parse((double)(lzoom*((height/2-mouseY)/scl))));
- xPos = dd.add(dd.mul(dd.sub(xPos,xTar),dd.parse(zoom/lzoom)),xTar);
- yPos = dd.add(dd.mul(dd.sub(yPos,yTar),dd.parse(zoom/lzoom)),yTar);
- xRefO= dd.sub(xPos,xRef);yRefO= dd.sub(yPos,yRef);
- float rx = scl*(float)dd.sub(xRef,xPos)[0]/zoom+width/2;
- float ry = height/2-scl*(float)dd.sub(yRef,yPos)[0]/zoom;
- int framesPerFrame = -frames;
- if(precMode<2){precalc(xRef,yRef);}
- for(lMillis=millis()+50;millis()<lMillis;){
- int fr = frames++&255;
- int sx = (fr>>0&1)<<3|(fr>>2&1)<<2|(fr>>4&1)<<1|(fr>>6&1)<<0;
- int sy =((fr>>1&1)<<3|(fr>>3&1)<<2|(fr>>5&1)<<1|(fr>>7&1)<<0)^sx;
- for(int j=sy;j<height;j+=16){
- for(int i=sx;i<width;i+=16){
- float x=zoom*(i-width/2)/scl;
- float y=zoom*(height/2-j)/scl;
- float IT=0;
- switch(precMode){
- case 0: IT = iterateds(x,y); break;
- case 1: IT = iteratedd(x,y); break;
- case 2: IT = iterates(x,y); break;
- case 3: IT = iterated(x,y); break;
- case 4: IT = iterateq(x,y); break;
- }
- pixels[i+j*width]=setColour(IT);
- }
- }
- }
- framesPerFrame += frames;
- fpfAvg+=((float)framesPerFrame-fpfAvg)/4;
- updatePixels();
- for(int i=0;i<2;i++){fill(240*i);
- if(infoShow){
- textAlign(LEFT,TOP);
- text("Real: "+(xPos[0]<0?"":" ")+dd.string(xPos), 4-i, 4-i);
- text("Imag: "+(yPos[0]<0?"":" ")+dd.string(yPos), 4-i, 20-i);
- text("RefR: "+(xRef[0]<0?"":" ")+dd.string(xRef), 4-i, 36-i);
- text("RefI: "+(yRef[0]<0?"":" ")+dd.string(yRef), 4-i, 52-i);
- text("Magn: "+Float.toString(zoom), 4-i, 68-i);
- text("Iter: "+Float.toString(maxIT), 4-i, 84-i);
- text("BOut: "+Float.toString(bailOut), 4-i, 100-i);
- text("Prec: "+precName[precMode],4-i, 116-i);
- text("FPFA: "+String.format("%1.3f",fpfAvg),4-i, 132-i);
- if(mouseX!=pmouseX||mouseY!=pmouseY){mHover=millis()+5000;}
- if(millis()<mHover){textAlign(CENTER,BOTTOM);
- text("press 'm' key to hide info", width/2-i, height-100-i);
- text("scroll up/down to zoom out/in", width/2-i, height-84-i);
- text("left-click drag to move the view", width/2-i, height-68-i);
- text("z/x to increase/decrease roughness", width/2-i, height-52-i);
- text("right-click to choose reference point", width/2-i, height-36-i);
- text("a/s for bailOut, q/w for the color speed", width/2-i, height-20-i);
- text("k/l/i/o/p to switch between precision mode", width/2-i, height-6-i);
- }
- }
- }
- if(precMode<2){fill(255);stroke(0);strokeWeight(1);
- rectMode(CENTER);rect(rx,ry,3,9);rect(rx,ry,9,3);
- stroke(255);rect(rx,ry,1,3);}
- }
- void keyPressed(){
- switch(key){
- case 'm': infoShow = !infoShow; break;
- }
- switch(keyCode){
- case 32 : background(0); loadPixels(); break;
- }
- }
Add Comment
Please, Sign In to add comment