#include #include #include #include #include #include #include #include #include #include "lodepng.h" #ifndef CMPLX #define CMPLX(r,i) ((r) + (i)*I) #endif const int MAXITER=200; const double EPS=1e-1; static double complex att_func(double complex x,double exponent){ return clog((1-cpow(x,exponent+1))/(1-x)); // return csqrt(M_SQRT2*x); // sqrt(2) and 0 // return csqrt(1+x); // phi // return csqrt(2*x-1); // attracts REALLY SLOWLY to 1+0i // return clog(x); // two basins and two infinities // return clog(x*x); // "241" basins // return clog(x*x+x); // 3 basins but intricate structure // return clog(x*x*x*x+x*x*x+x*x+x+1); // 2 basin fractal? // return csqrt(x*x*x+x*x+x+1); } struct colour{ unsigned char r,g,b; }; static struct colour make_colour(double complex z){ static const double N=3; double norm=cabs(z); if(norm>N)norm=N; int normclr=(int)(norm/N*255); int argclr=(int)((carg(z)+M_PI)/(2*M_PI)*255); return (struct colour){normclr,argclr,0}; } struct config{ double unitsz; int width,height; double midx,midy; double exponent; }; struct thread_info{ pthread_t th; int ystart,yend; unsigned char *img; bool do_basins; struct config cfg; }; static void* thread_entry(void *arg_vp){ struct thread_info *th_info=arg_vp; int ystart=th_info->ystart; int yend=th_info->yend; unsigned char *img=th_info->img; bool do_basins=th_info->do_basins; struct config cfg=th_info->cfg; int nbasins=0,bsz=0; double complex *basins=NULL; if(do_basins){ bsz=16; basins=malloc(bsz*sizeof(double complex)); assert(basins); } printf("Thread: y in [%d,%d)\n",ystart,yend); for(int iy=ystart;iy=2){ cfg.exponent=strtod(argv[1],NULL); } const char *fname; if(argc>=3){ fname=argv[2]; } else { fname="out.png"; } printf("Config:\n"); printf("unitsz = %lf\n",cfg.unitsz); printf("width = %d\n",cfg.width); printf("height = %d\n",cfg.height); printf("midx = %lf\n",cfg.midx); printf("midy = %lf\n",cfg.midy); printf("exponent = %lf\n",cfg.exponent); unsigned char img[cfg.width*cfg.height*3]; int nthreads=sysconf(_SC_NPROCESSORS_ONLN); if(nthreads==4)nthreads/=2; if(nthreads>=999||nthreads<1)nthreads=1; fprintf(stderr,"Using %d thread%s\n",nthreads,nthreads==1?"":"s"); pthread_attr_t attr; if(pthread_attr_init(&attr)!=0){ perror("pthread_attr_init"); return 1; } struct thread_info ths[nthreads]; for(int i=0;i