float cmag2(vec2 a)
{
    return a[0] * a[0] + a[1] * a[1];
}

float cmag(vec2 a)
{
    return sqrt(cmag2(a));
}

float carg(vec2 a)
{
    return atan(a[1], a[0]);
}

vec2 cmul(vec2 a, vec2 b)
{
    vec2 res;
    float a0b0 = a[0] * b[0];
    float a1b1 = a[1] * b[1];
    res[0] = a0b0 - a1b1;
    res[1] = (a[0] + a[1]) * (b[0] + b[1]) - a0b0 - a1b1;
    return res;
}

vec2 cdiv(vec2 a, vec2 b)
{
    vec2 res;
    res[0] = a[0] * b[0] + a[1] * b[1];
    res[1] = a[1] * b[0] - a[0] * b[1];
    float b2 = cmag2(b);
    return res / b2;
}

float clogre(vec2 a)
{
    return log(cmag(a));
}

float clogim(vec2 a)
{
    return atan(a[1], a[0]);
}

vec2 clog(vec2 a)
{
    return vec2(clogre(a), clogim(a));
}

vec2 cpow(vec2 a, int n)
{
    vec2 res = vec2(1, 0);
    
    if (n == 0)
        return res;
    else if (n < 0)
    {
        if (cmag2(a) < 1e-6)
            return vec2(0, 0);
        a = cdiv(res, a);
        n = -n;
    }

    
    while (n > 1)
    {
        if (n % 2 == 0)
        {
            a = cmul(a, a);
            n = n / 2;
        }
        else
        {
            res = cmul(a, res);
            a = cmul(a, a);
            n = (n - 1) / 2;
        }
    }
    return cmul(a, res);
}

vec2 cpolyeval(vec2 z, vec2 coeff[10], int k)
{
    vec2 res = vec2(0.0f, 0.0f);
    for (int i = 0; i < k; ++i)
    {
        res += cmul(coeff[i], cpow(z, i));
    }

    return res;
}

float random(vec2 uv)
{
    return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453123);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    
    vec2 z = 2.0f*uv - vec2(1.0f, 1.0f);

    vec2 p = vec2(0,0);
    if (iMouse.w < 0.0f)
        p = 2.0f*iMouse.xy/iResolution.xy - vec2(1.0f,1.0f);
    
    float R = 0.9f;
    vec3 _ColorA = vec3(1.0f, 0.0f, 0.0f);
    vec3 _ColorB = vec3(0.0f, 1.0f, 1.0f);
    const float PI = 3.14159265f;
    float t = 2.0f * PI * iTime / 10.0f;


    vec2 q = p + vec2(R * cos(t), R * sin(t));



    int k = 6;
    vec2 coeffa[10];
    vec2 coeffb[10];
    vec2 seed;
    float num1, num2, num3, num4;

    for (int i = 0; i < k; ++i)
    {
        coeffa[i] = vec2(0, 0);
        coeffb[i] = vec2(0, 0);
    }

    coeffa[0] = -p;
    coeffb[0] = -q;
    coeffa[1] = vec2(1, 0);
    coeffb[1] = vec2(1, 0);

    for (int i = 2; i < k; ++i)
    {
        seed[0] = seed[1] = 4.0f * float(i);
        num1 = 10.0f*random(seed);
        seed[0] = seed[1] = 4.0f * float(i) + 1.0f;
        num2 = random(seed);
        seed[0] = seed[1] = 4.0f * float(i) + 2.0f;
        num3 = 10.0f * random(seed);
        seed[0] = seed[1] = 4.0f * float(i) + 3.0f;
        num4 = random(seed);
        coeffa[i] = vec2(num2 * cos(num1 * t), num2 * sin(num1 * t));
        coeffb[i] = vec2(num4 * cos(num3 * t), num4 * sin(num3 * t));
    }


    vec2 num;
    vec2 denom;

    num = cpolyeval(z, coeffa, k);
    denom = cpolyeval(z, coeffb, k);

    float alpha;

    if (cmag2(denom) < 1e-6f)
        alpha = 0.0f;
    else
        alpha = clogim(cdiv(num, denom)) / PI;

    vec3 neutral = vec3(0, 0, 0);
    // Albedo comes from a texture tinted by color
    //fixed alpha = sin(_Time[1]);
    vec3 color;

    if (alpha < 0.0)
        color = mix(neutral, _ColorA, -alpha);
    else
        color = mix(neutral, _ColorB, alpha);

    if (cmag2(denom) < 1e-6f)
        color = vec3(1,1,1);

    
    // Output to screen
    fragColor = vec4(color,1.0);
}
