/*FAST MATH*/

#define PI  radians(180.0)
#define TAU radians(360.0)
const float EPS = 1e-5;

float pow2(float x) {return x * x; }
vec2 pow2(vec2 x) {return x * x; }
vec3 pow2(vec3 x) {return x * x; }
vec4 pow2(vec4 x) {return x * x; }

float pow1_5(float x) {return x - x * pow2(1.0 - x); }
vec3 pow1_5(vec3 x) {return x - x * pow2(1.0 - x); }

float pow3(float x) {return x * x*x; }
vec2 pow3(vec2 x) {return x * x*x; }
vec3 pow3(vec3 x) {return x * x*x; }
vec4 pow3(vec4 x) {return x * x*x; }

float pow4(float x) {return pow2(pow2(x)); }
vec2 pow4(vec2 x) {return pow2(pow2(x)); }
vec3 pow4(vec3 x) {return pow2(pow2(x)); }
vec4 pow4(vec4 x) {return pow2(pow2(x)); }

float pow8(float x) {return pow4(pow4(x)); }
vec2 pow8(vec2 x) {return pow4(pow4(x)); }
vec3 pow8(vec3 x) {return pow4(pow4(x)); }
vec4 pow8(vec4 x) {return pow4(pow4(x)); }

float pow16(float x) {return pow4(pow4(x)); }
float pow32(float x) {return pow2(pow16(x)); }

#define MaxEPS(x)max(x, EPS)

#define clamp01(x)clamp(x, 0.0, 1.0)
#define clampInv11(x)clamp(x, - 1.0, 1.0)

#define clamp00125(x)clamp(x, 0.0, 0.125)

#define clampVec2_01(x)clamp(x, vec2(0.0), vec2(1.0))

#define clampVec3_01(x)clamp(x, vec3(0.0), vec3(1.0))
#define clampVec3Inv_11(x)clamp(x, vec3(-1.0), vec3(1.0))

#define clampVec4_01(x)clamp(x, vec4(0.0), vec4(1.0))

#define clampLmC_00933(x)clamp(x, vec2(0.0), vec2(0.9333, 1.0))

#define Max0(x)max(x, 0.0)

float sqrt1(float x) {
    x = 1.0 - x;
    x *= x;
    return 1.0 - x;
}

float sqrt2(float x) {
    x = 1.0 - x;
    x *= x;
    x *= x;
    return 1.0 - x;
}
float sqrt3(float x) {
    x = 1.0 - x;
    x *= x;
    x *= x;
    x *= x;
    return 1.0 - x;
}
vec2 sqrt3(vec2 x) {
    x = 1.0 - x;
    x *= x;
    x *= x;
    x *= x;
    return 1.0 - x;
}
vec3 sqrt3(vec3 x) {
    x = 1.0 - x;
    x *= x;
    x *= x;
    x *= x;
    return 1.0 - x;
}
vec4 sqrt3(vec4 x) {
    x = 1.0 - x;
    x *= x;
    x *= x;
    x *= x;
    return 1.0 - x;
}

float sqrt1inv(float x) {
        x = 1.0 - x;
        x *= x;
        return x;
    }

float Smooth3(float x)
{
    x = clamp(x, 0.0, 1.0);
    return x * x * (3.0 - 2.0 * x);
}

vec2 Smooth3(vec2 x)
{
	x = clamp(x, 0.0, 1.0);
	return x * x * (3.0 - 2.0 * x);
}

float smoothClamp(float f, float minf, float maxf) {
    if (f <= minf) {
        return minf;
    } else
    if (f >= maxf) {
        return maxf;
    } else {
        float nf = (f - minf) / (maxf - minf);
        float res = 0.0;
        if (nf < 0.5) {
            res = 2.0 * pow2(nf);
        }else {
            float fi = -2.0 * nf + 2.0;
            res = 1 - pow2(fi) / 2.0;
        }
        return res * (maxf - minf) + minf;
    }
}
vec2 smoothClamp2(vec2 v, vec2 minv, vec2 maxv) {
    return vec2(
        smoothClamp(v.x, minv.x, maxv.x),
        smoothClamp(v.y, minv.y, maxv.y)
    );
}
vec3 smoothClamp3(vec3 v, vec3 minv, vec3 maxv) {
    return vec3(
        smoothClamp(v.x, minv.x, maxv.x),
        smoothClamp(v.y, minv.y, maxv.y),
        smoothClamp(v.z, minv.z, maxv.z)
    );
}
vec4 smoothClamp4(vec4 v, vec4 minv, vec4 maxv) {
    return vec4(
        smoothClamp(v.x, minv.x, maxv.x),
        smoothClamp(v.y, minv.y, maxv.y),
        smoothClamp(v.z, minv.z, maxv.z),
        smoothClamp(v.w, minv.w, maxv.w)
    );
}

bool CheckForColor(vec3 albedo, vec3 check) {
    vec3 dif = albedo - check / 255.0;
    return dif == clamp(dif, vec3(-0.001), vec3(0.001));
}