/*FAST MATH*/

const float PI  = 3.14159265359;
const float TAU = 6.28318530718;
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 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 Smooth3(float 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));
}