#define PI 3.14159265358979323
#define T .05
//#define ZOOM 200.
#define ZOOM (0.055*iResolution.y)

#define tt (1.0 + 0.8*sin(iTime/1.))


#define hue(a) (.6 + .6*cos(2.*PI*a + vec3(0,-2.*PI/3.,2.*PI/3.)))
#define cmul(z1, z2) (mat2(z1, -z1.y, z1.x)*z2)
#define cdiv(z1, z2) (z1*mat2(z2, -z2.y, z2.x)/dot(z2, z2))
#define clog(z) vec2(0.5*log(dot(z,z)), atan(z.y, z.x))

vec2 cexp(vec2 z, vec2 c)
{
    float argz, m, a;
    float lnz = dot(z,z);
    
    if (lnz == 0.) return vec2(0., 0.);
    else {
        lnz = 0.5*log(lnz);
        argz = atan(z.y, z.x);
        
        m = exp(c.x*lnz - c.y*argz);
        a = c.x*argz + c.y*lnz;
        
        return m*vec2(cos(a), sin(a));
    }
}


vec3 hrgb(vec2 w)
{
    
    float m = length(w);
    float a = (PI + atan(w.y, w.x))/(2.0*PI);
    float aa = atan(w.y, w.x);
    
    //m = log(1. + 100.*m);

    float mm = fract(m);
    float p = fract(mod(a, 1.0/16.0));

    vec3 c;

    c.r =  0.5 - 0.5*sin(2.0*PI*a - PI/2.0);
    c.g = (0.5 + 0.5*sin(2.0*PI*a*1.5 - PI/2.0)) * float(a < 0.66);
    c.b = (0.5 + 0.5*sin(2.0*PI*a*1.5 + PI/2.0)) * float(a > 0.33);
    
    //c = 0.5*(c + hue(a));
    
    c -= 0.3*mm + 2.*p;
   
    int b = (abs(int(2.*fract(w.x)))) 
          ^ (abs(int(2.*fract(w.y))));
    
    if (b == 0)
        if (abs(aa) > PI/2.) 
            if (aa > 0.) c = vec3(1.,0.,0.); else c = vec3(0.,1.,0.);
        else 
            if (aa > 0.) c = vec3(1.,1.,1.); else c = vec3(0.,0.,1.);
    else {
        c = vec3(0.,0.,0.);
    }
    
    //if (//length(w) + T/2. > 1. &&
    //    (fract(w.x) < T || fract(-w.x) < T ||
    //     fract(w.y) < T || fract(-w.y) < T)) c -= 0.4;
    
    return c;
}

vec2 f(vec2 z, int n)
{
    vec2 w, p, q, g;

    //w = cexp( vec2(exp(1.), 0.), z );
    
    //w = z - vec2(0.5, 0.);
    //w = cdiv( w, (z - vec2(-0.35,-0.35)) );
    //w = cdiv( w, (z - vec2(-0.35, 0.35)) );
    
    //w = cmul( (z - vec2(-0.35,-0.35)),
    //          (z - vec2(-0.35, 0.35)) );
    //w = cdiv( w, (z - vec2(0.5, 0.)));
    
    //float m = 1. + tt;
    
    float r = 3.5;
    
    w = vec2(0., 0.);
    
    for (int i=0; i<n; i++) {
    
        //x = 100*cos(a) + 140*sin(a*2)
        //y = 100*sin(a) + 140*cos(a*2)
    
    
        //C: z(t)
        p = vec2(r*cos(float(i)*2.*PI/float(n)) + tt*r*sin(float(i)*8.*PI/float(n)), 
                 r*sin(float(i)*2.*PI/float(n)) + tt*r*cos(float(i)*8.*PI/float(n)));
        
        //f(z(t)) 
        //q = cmul(p, p); //=z^3
        //q = cmul(p, q);
        
        //q = sin(p)
        //q.x = sin(p.x)*cosh(p.y);
        //q.y = cos(p.x)*sinh(p.y);
        
        //
        q = p; //cexp(vec2(exp(1.), 0.), p);
        
        
        //f(z)/(z - z0)^(m + 1)
        g = p - z;
        //g = cexp(g, vec2(m + 1., 0.));
        q = cdiv(q, g);
        
        //dz/dt
        //q = cmul(q, 
        //    vec2(-r*sin(float(i)*2.*PI/float(n)), 
        //          r*cos(float(i)*2.*PI/float(n))));
        g = vec2(-r*sin(float(i)*2.*PI/float(n)) + tt*4.*r*cos(float(i)*4.*PI/float(n)), 
                  r*cos(float(i)*2.*PI/float(n)) - tt*4.*r*sin(float(i)*4.*PI/float(n)) );
              
        q = cmul(q, g);
        w += q;
    }
    //dt
    w *= 2.*PI/float(n);
    
    //1/(2 pi i)
    w = cmul(w, vec2(0., -1./(2.*PI)) );
   
    //m!
    float gamma = 1.;//sqrt(2.*PI*m)*pow(m/exp(1.), m);
    w *= gamma;
    
    
    return w;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 z, w, w1, w2, w3, w4;
    int n = 300;
    
    z = fragCoord - iResolution.xy/2.;

    //if (iMouse.xy != vec2(0., 0.)) //to center at origin
    //    z -= iMouse.xy - iResolution.xy/2.;
    
    
    //z /= ZOOM;
    
    
    
    //z -= vec2(0.5, 0.)*ZOOM;
    
    w  = f( z/ZOOM, n );
    //fragColor = vec4(hrgb(w), 1.0);
    
    
    
    w1 = f( (z + vec2(-.25,-.25))/ZOOM, n );
    w2 = f( (z + vec2(-.25, .25))/ZOOM, n );
    w3 = f( (z + vec2( .25,-.25))/ZOOM, n );
    w4 = f( (z + vec2( .25, .25))/ZOOM, n );
    
    
    fragColor = vec4(0.2*(hrgb(w) +
                          hrgb(w1) + hrgb(w2) + 
                          hrgb(w3) + hrgb(w4)), 1.0);
                         
}
