/*
 * Mesa 3-D graphics library
 * Version:  6.5
 *
 * Copyright (C) 2006  Brian Paul   All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//
// From Shader Spec, ver. 1.10, rev. 59
//

//bp: XXX these will probably go away since the value needs to be
//determined at runtime and may vary from one GLcontext to another...
const int gl_MaxLights = 8;
const int gl_MaxClipPlanes = 6;
const int gl_MaxTextureUnits = 8;
const int gl_MaxTextureCoords = 8;
const int gl_MaxVertexAttribs = 16;
const int gl_MaxVertexUniformComponents = 512;
const int gl_MaxVaryingFloats = 32;
const int gl_MaxVertexTextureImageUnits = 0;
const int gl_MaxCombinedTextureImageUnits = 2;
const int gl_MaxTextureImageUnits = 2;
const int gl_MaxFragmentUniformComponents = 64;
const int gl_MaxDrawBuffers = 1;

uniform mat4 gl_ModelViewMatrix;
uniform mat4 gl_ProjectionMatrix;
uniform mat4 gl_ModelViewProjectionMatrix;
uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];

uniform mat3 gl_NormalMatrix;
uniform mat3 __NormalMatrixTranspose;  // Mesa only

uniform mat4 gl_ModelViewMatrixInverse;
uniform mat4 gl_ProjectionMatrixInverse;
uniform mat4 gl_ModelViewProjectionMatrixInverse;
uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];

uniform mat4 gl_ModelViewMatrixTranspose;
uniform mat4 gl_ProjectionMatrixTranspose;
uniform mat4 gl_ModelViewProjectionMatrixTranspose;
uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];

uniform mat4 gl_ModelViewMatrixInverseTranspose;
uniform mat4 gl_ProjectionMatrixInverseTranspose;
uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;
uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];

uniform float gl_NormalScale;

struct gl_DepthRangeParameters {
    float near;
    float far;
    float diff;
};

uniform gl_DepthRangeParameters gl_DepthRange;

uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];

struct gl_PointParameters {
    float size;
    float sizeMin;
    float sizeMax;
    float fadeThresholdSize;
    float distanceConstantAttenuation;
    float distanceLinearAttenuation;
    float distanceQuadraticAttenuation;
};

uniform gl_PointParameters gl_Point;

struct gl_MaterialParameters {
    vec4 emission;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
};

uniform gl_MaterialParameters gl_FrontMaterial;
uniform gl_MaterialParameters gl_BackMaterial;

struct gl_LightSourceParameters {
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    vec4 position;
    vec4 halfVector;
    vec3 spotDirection;
    float spotExponent;
    float spotCutoff;
    float spotCosCutoff;
    float constantAttenuation;
    float linearAttenuation;
    float quadraticAttenuation;
};

uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];

struct gl_LightModelParameters {
    vec4 ambient;
};

uniform gl_LightModelParameters gl_LightModel;

struct gl_LightModelProducts {
    vec4 sceneColor;
};

uniform gl_LightModelProducts gl_FrontLightModelProduct;
uniform gl_LightModelProducts gl_BackLightModelProduct;

struct gl_LightProducts {
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
};

uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];

uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];
uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];
uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];
uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];
uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];
uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];
uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];
uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];
uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];

struct gl_FogParameters {
    vec4 color;
    float density;
    float start;
    float end;
    float scale;
};

uniform gl_FogParameters gl_Fog;





//
// 8.1 Angle and Trigonometry Functions
//

//// radians

float radians(const float deg)
{
   const float c = 3.1415926 / 180.0;
   __asm vec4_multiply __retVal.x, deg, c;
}

vec2 radians(const vec2 deg)
{
   const float c = 3.1415926 / 180.0;
   __asm vec4_multiply __retVal.xy, deg.xy, c.xx;
}

vec3 radians(const vec3 deg)
{
   const float c = 3.1415926 / 180.0;
   __asm vec4_multiply __retVal.xyz, deg.xyz, c.xxx;
}

vec4 radians(const vec4 deg)
{
   const float c = 3.1415926 / 180.0;
   __asm vec4_multiply __retVal, deg, c.xxxx;
}


//// degrees

float degrees(const float rad)
{
   const float c = 180.0 / 3.1415926;
   __asm vec4_multiply __retVal.x, rad, c;
}

vec2 degrees(const vec2 rad)
{
   const float c = 3.1415926 / 180.0;
   __asm vec4_multiply __retVal.xy, rad.xy, c.xx;
}

vec3 degrees(const vec3 rad)
{
   const float c = 3.1415926 / 180.0;
   __asm vec4_multiply __retVal.xyz, rad.xyz, c.xxx;
}

vec4 degrees(const vec4 rad)
{
   const float c = 3.1415926 / 180.0;
   __asm vec4_multiply __retVal, rad, c.xxxx;
}


//// sin

float sin(const float radians)
{
   __asm float_sine __retVal.x, radians;
}

vec2 sin(const vec2 radians)
{
   __asm float_sine __retVal.x, radians.x;
   __asm float_sine __retVal.y, radians.y;
}

vec3 sin(const vec3 radians)
{
   __asm float_sine __retVal.x, radians.x;
   __asm float_sine __retVal.y, radians.y;
   __asm float_sine __retVal.z, radians.z;
}

vec4 sin(const vec4 radians)
{
   __asm float_sine __retVal.x, radians.x;
   __asm float_sine __retVal.y, radians.y;
   __asm float_sine __retVal.z, radians.z;
   __asm float_sine __retVal.w, radians.w;
}


//// cos

float cos(const float radians)
{
   __asm float_cosine __retVal.x, radians;
}

vec2 cos(const vec2 radians)
{
   __asm float_cosine __retVal.x, radians.x;
   __asm float_cosine __retVal.y, radians.y;
}

vec3 cos(const vec3 radians)
{
   __asm float_cosine __retVal.x, radians.x;
   __asm float_cosine __retVal.y, radians.y;
   __asm float_cosine __retVal.z, radians.z;
}

vec4 cos(const vec4 radians)
{
   __asm float_cosine __retVal.x, radians.x;
   __asm float_cosine __retVal.y, radians.y;
   __asm float_cosine __retVal.z, radians.z;
   __asm float_cosine __retVal.w, radians.w;
}



//// tan

float tan(const float angle)
{
   const float s = sin(angle);
   const float c = cos(angle);
   return s / c;
}

vec2 tan(const vec2 angle)
{
   const vec2 s = sin(angle);
   const vec2 c = cos(angle);
   return s / c;
}

vec3 tan(const vec3 angle)
{
   const vec3 s = sin(angle);
   const vec3 c = cos(angle);
   return s / c;
}

vec4 tan(const vec4 angle)
{
   const vec4 s = sin(angle);
   const vec4 c = cos(angle);
   return s / c;
}



float asin(const float x)
{
   const float a0 = 1.5707288;  // PI/2?
   const float a1 = -0.2121144;
   const float a2 = 0.0742610;
   //const float a3 = -0.0187293;
   const float halfPi = 3.1415926 * 0.5;
   const float y = abs(x);
   // three terms seem to be enough:
   __retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + a2 * y))) * sign(x);
   // otherwise, try four:
   //__retVal = (halfPi - sqrt(1.0 - y) * (a0 + y * (a1 + y * (a2 + y * a3)))) * sign(x);
}

vec2 asin(const vec2 v)
{
   __retVal.x = asin(v.x);
   __retVal.y = asin(v.y);
}

vec3 asin(const vec3 v)
{
   __retVal.x = asin(v.x);
   __retVal.y = asin(v.y);
   __retVal.z = asin(v.z);
}

vec4 asin(const vec4 v)
{
   __retVal.x = asin(v.x);
   __retVal.y = asin(v.y);
   __retVal.z = asin(v.z);
}

float acos(const float x)
{
   const float halfPi = 3.1415926 * 0.5;
   __retVal = halfPi - asin(x);
}

vec2 acos(const vec2 v)
{
   __retVal.x = acos(v.x);
   __retVal.y = acos(v.y);
}

vec3 acos(const vec3 v)
{
   __retVal.x = acos(v.x);
   __retVal.y = acos(v.y);
   __retVal.z = acos(v.z);
}

vec4 acos(const vec4 v)
{
   __retVal.x = acos(v.x);
   __retVal.y = acos(v.y);
   __retVal.z = acos(v.z);
   __retVal.w = acos(v.w);
}

float atan(const float x)
{
   __retVal = asin(x * inversesqrt(x * x + 1.0));
}

vec2 atan(const vec2 y_over_x)
{
   __retVal.x = atan(y_over_x.x);
   __retVal.y = atan(y_over_x.y);
}

vec3 atan(const vec3 y_over_x)
{
   __retVal.x = atan(y_over_x.x);
   __retVal.y = atan(y_over_x.y);
   __retVal.z = atan(y_over_x.z);
}

vec4 atan(const vec4 y_over_x)
{
   __retVal.x = atan(y_over_x.x);
   __retVal.y = atan(y_over_x.y);
   __retVal.z = atan(y_over_x.z);
   __retVal.w = atan(y_over_x.w);
}

float atan(const float y, const float x)
{
    if (x == 0.0)
       return 0.0;
    float z = atan(y / x);
    if (x < 0.0)
    {
        if (y < 0.0)
            return z - 3.141593;
        return z + 3.141593;
    }
    return z;
}

vec2 atan(const vec2 u, const vec2 v)
{
   __retVal.x = atan(u.x, v.x);
   __retVal.y = atan(u.y, v.y);
}

vec3 atan(const vec3 u, const vec3 v)
{
   __retVal.x = atan(u.x, v.x);
   __retVal.y = atan(u.y, v.y);
   __retVal.z = atan(u.z, v.z);
}

vec4 atan(const vec4 u, const vec4 v)
{
   __retVal.x = atan(u.x, v.x);
   __retVal.y = atan(u.y, v.y);
   __retVal.z = atan(u.z, v.z);
   __retVal.w = atan(u.w, v.w);
}


//
// 8.2 Exponential Functions
//

//// pow

float pow(const float a, const float b)
{
   __asm float_power __retVal.x, a, b;
}

vec2 pow(const vec2 a, const vec2 b)
{
   __asm float_power __retVal.x, a.x, b.x;
   __asm float_power __retVal.y, a.y, b.y;
}

vec3 pow(const vec3 a, const vec3 b)
{
   __asm float_power __retVal.x, a.x, b.x;
   __asm float_power __retVal.y, a.y, b.y;
   __asm float_power __retVal.z, a.z, b.z;
}

vec4 pow(const vec4 a, const vec4 b)
{
   __asm float_power __retVal.x, a.x, b.x;
   __asm float_power __retVal.y, a.y, b.y;
   __asm float_power __retVal.z, a.z, b.z;
   __asm float_power __retVal.w, a.w, b.w;
}


//// exp

float exp(const float a)
{
   const float e = 2.71828;
   __asm float_power __retVal, e, a;
}

vec2 exp(const vec2 a)
{
   const float e = 2.71828;
   __asm float_power __retVal.x, e, a.x;
   __asm float_power __retVal.y, e, a.y;
}

vec3 exp(const vec3 a)
{
   const float e = 2.71828;
   __asm float_power __retVal.x, e, a.x;
   __asm float_power __retVal.y, e, a.y;
   __asm float_power __retVal.z, e, a.z;
}

vec4 exp(const vec4 a)
{
   const float e = 2.71828;
   __asm float_power __retVal.x, e, a.x;
   __asm float_power __retVal.y, e, a.y;
   __asm float_power __retVal.z, e, a.z;
   __asm float_power __retVal.w, e, a.w;
}



//// log2

float log2(const float x)
{
   __asm float_log2 __retVal.x, x;
}

vec2 log2(const vec2 v)
{
   __asm float_log2 __retVal.x, v.x;
   __asm float_log2 __retVal.y, v.y;
}

vec3 log2(const vec3 v)
{
   __asm float_log2 __retVal.x, v.x;
   __asm float_log2 __retVal.y, v.y;
   __asm float_log2 __retVal.z, v.z;
}

vec4 log2(const vec4 v)
{
   __asm float_log2 __retVal.x, v.x;
   __asm float_log2 __retVal.y, v.y;
   __asm float_log2 __retVal.z, v.z;
   __asm float_log2 __retVal.w, v.w;
}


//// log  (natural log)

float log(const float x)
{
   // note:  logBaseB(x) = logBaseN(x) / logBaseN(B)
   // compute log(x) = log2(x) / log2(e)
   // c = 1.0 / log2(e) = 0.693147181
   const float c = 0.693147181;
   return log2(x) * c;
}

vec2 log(const vec2 v)
{
   const float c = 0.693147181;
   return log2(v) * c;
}

vec3 log(const vec3 v)
{
   const float c = 0.693147181;
   return log2(v) * c;
}

vec4 log(const vec4 v)
{
   const float c = 0.693147181;
   return log2(v) * c;
}


//// exp2

float exp2(const float a)
{
   __asm float_exp2 __retVal.x, a;
}

vec2 exp2(const vec2 a)
{
   __asm float_exp2 __retVal.x, a.x;
   __asm float_exp2 __retVal.y, a.y;
}

vec3 exp2(const vec3 a)
{
   __asm float_exp2 __retVal.x, a.x;
   __asm float_exp2 __retVal.y, a.y;
   __asm float_exp2 __retVal.z, a.z;
}

vec4 exp2(const vec4 a)
{
   __asm float_exp2 __retVal.x, a.x;
   __asm float_exp2 __retVal.y, a.y;
   __asm float_exp2 __retVal.z, a.z;
   __asm float_exp2 __retVal.w, a.w;
}


//// sqrt

float sqrt(const float x)
{
   float r;
   __asm float_rsq r, x;
   __asm float_rcp __retVal.x, r;
}

vec2 sqrt(const vec2 v)
{
   float r;
   __asm float_rsq r, v.x;
   __asm float_rcp __retVal.x, r;
   __asm float_rsq r, v.y;
   __asm float_rcp __retVal.y, r;
}

vec3 sqrt(const vec3 v)
{
   float r;
   __asm float_rsq r, v.x;
   __asm float_rcp __retVal.x, r;
   __asm float_rsq r, v.y;
   __asm float_rcp __retVal.y, r;
   __asm float_rsq r, v.z;
   __asm float_rcp __retVal.z, r;
}

vec4 sqrt(const vec4 v)
{
   float r;
   __asm float_rsq r, v.x;
   __asm float_rcp __retVal.x, r;
   __asm float_rsq r, v.y;
   __asm float_rcp __retVal.y, r;
   __asm float_rsq r, v.z;
   __asm float_rcp __retVal.z, r;
   __asm float_rsq r, v.w;
   __asm float_rcp __retVal.w, r;
}


//// inversesqrt

float inversesqrt(const float x)
{
   __asm float_rsq __retVal.x, x;
}

vec2 inversesqrt(const vec2 v)
{
   __asm float_rsq __retVal.x, v.x;
   __asm float_rsq __retVal.y, v.y;
}

vec3 inversesqrt(const vec3 v)
{
   __asm float_rsq __retVal.x, v.x;
   __asm float_rsq __retVal.y, v.y;
   __asm float_rsq __retVal.z, v.z;
}

vec4 inversesqrt(const vec4 v)
{
   __asm float_rsq __retVal.x, v.x;
   __asm float_rsq __retVal.y, v.y;
   __asm float_rsq __retVal.z, v.z;
   __asm float_rsq __retVal.w, v.w;
}


//// normalize

float normalize(const float x)
{
   __retVal.x = 1.0;
}

vec2 normalize(const vec2 v)
{
   const float s = inversesqrt(dot(v, v));
   __asm vec4_multiply __retVal.xy, v, s.xx;
}

vec3 normalize(const vec3 v)
{
//   const float s = inversesqrt(dot(v, v));
//   __retVal = v * s;
// XXX note, we _could_ use __retVal.w instead of tmp and and save a
// register, but that's actually a compilation error because v is a vec3
// and the .w suffix is illegal.  Oh well.
   float tmp;
   __asm vec3_dot tmp, v, v;
   __asm float_rsq tmp, tmp;
   __asm vec4_multiply __retVal.xyz, v, tmp.xxx;
}

vec4 normalize(const vec4 v)
{
   float tmp;
   __asm vec4_dot tmp, v, v;
   __asm float_rsq tmp, tmp;
   __asm vec4_multiply __retVal.xyz, v, tmp.xxx;
}



//
// 8.3 Common Functions
//


//// abs

float abs(const float a)
{
   __asm vec4_abs __retVal.x, a;
}

vec2 abs(const vec2 a)
{
   __asm vec4_abs __retVal.xy, a;
}

vec3 abs(const vec3 a)
{
   __asm vec4_abs __retVal.xyz, a;
}

vec4 abs(const vec4 a)
{
   __asm vec4_abs __retVal, a;
}


//// sign

float sign(const float x)
{
   float p, n;
   __asm vec4_sgt p.x, x, 0.0;            // p = (x > 0)
   __asm vec4_sgt n.x, 0.0, x;            // n = (x < 0)
   __asm vec4_subtract __retVal.x, p, n;  // sign = p - n
}

vec2 sign(const vec2 v)
{
   vec2 p, n;
   __asm vec4_sgt p.xy, v, 0.0;
   __asm vec4_sgt n.xy, 0.0, v;
   __asm vec4_subtract __retVal.xy, p, n;
}

vec3 sign(const vec3 v)
{
   vec3 p, n;
   __asm vec4_sgt p.xyz, v, 0.0;
   __asm vec4_sgt n.xyz, 0.0, v;
   __asm vec4_subtract __retVal.xyz, p, n;
}

vec4 sign(const vec4 v)
{
   vec4 p, n;
   __asm vec4_sgt p, v, 0.0;
   __asm vec4_sgt n, 0.0, v;
   __asm vec4_subtract __retVal, p, n;
}


//// floor

float floor(const float a)
{
   __asm vec4_floor __retVal.x, a;
}

vec2 floor(const vec2 a)
{
   __asm vec4_floor __retVal.xy, a;
}

vec3 floor(const vec3 a)
{
   __asm vec4_floor __retVal.xyz, a;
}

vec4 floor(const vec4 a)
{
   __asm vec4_floor __retVal, a;
}


//// ceil

float ceil(const float a)
{
   // XXX this could be improved
   float b = -a;
   __asm vec4_floor b, b;
   __retVal.x = -b;
}

vec2 ceil(const vec2 a)
{
   vec2 b = -a;
   __asm vec4_floor b, b;
   __retVal.xy = -b;
}

vec3 ceil(const vec3 a)
{
   vec3 b = -a;
   __asm vec4_floor b, b;
   __retVal.xyz = -b;
}

vec4 ceil(const vec4 a)
{
   vec4 b = -a;
   __asm vec4_floor b, b;
   __retVal = -b;
}


//// fract

float fract(const float a)
{
   __asm vec4_frac __retVal.x, a;
}

vec2 fract(const vec2 a)
{
   __asm vec4_frac __retVal.xy, a;
}

vec3 fract(const vec3 a)
{
   __asm vec4_frac __retVal.xyz, a;
}

vec4 fract(const vec4 a)
{
   __asm vec4_frac __retVal, a;
}


//// mod  (very untested!)

float mod(const float a, const float b)
{
    float oneOverB;
    __asm float_rcp oneOverB, b;
    __retVal.x = a - b * floor(a * oneOverB);
}

vec2 mod(const vec2 a, const float b)
{
    float oneOverB;
    __asm float_rcp oneOverB, b;
    __retVal.xy = a - b * floor(a * oneOverB);
}

vec3 mod(const vec3 a, const float b)
{
    float oneOverB;
    __asm float_rcp oneOverB, b;
    __retVal.xyz = a - b * floor(a * oneOverB);
}

vec4 mod(const vec4 a, const float b)
{
    float oneOverB;
    __asm float_rcp oneOverB, b;
    __retVal = a - b * floor(a * oneOverB);
}

vec2 mod(const vec2 a, const vec2 b)
{
    float oneOverBx, oneOverBy;
    __asm float_rcp oneOverBx, b.x;
    __asm float_rcp oneOverBy, b.y;
    __retVal.x = a.x - b.x * floor(a.x * oneOverBx);
    __retVal.y = a.y - b.y * floor(a.y * oneOverBy);
}

vec3 mod(const vec3 a, const vec3 b)
{
    float oneOverBx, oneOverBy, oneOverBz;
    __asm float_rcp oneOverBx, b.x;
    __asm float_rcp oneOverBy, b.y;
    __asm float_rcp oneOverBz, b.z;
    __retVal.x = a.x - b.x * floor(a.x * oneOverBx);
    __retVal.y = a.y - b.y * floor(a.y * oneOverBy);
    __retVal.z = a.z - b.z * floor(a.z * oneOverBz);
}

vec4 mod(const vec4 a, const vec4 b)
{
    float oneOverBx, oneOverBy, oneOverBz, oneOverBw;
    __asm float_rcp oneOverBx, b.x;
    __asm float_rcp oneOverBy, b.y;
    __asm float_rcp oneOverBz, b.z;
    __asm float_rcp oneOverBw, b.w;
    __retVal.x = a.x - b.x * floor(a.x * oneOverBx);
    __retVal.y = a.y - b.y * floor(a.y * oneOverBy);
    __retVal.z = a.z - b.z * floor(a.z * oneOverBz);
    __retVal.w = a.w - b.w * floor(a.w * oneOverBw);
}


//// min

float min(const float a, const float b)
{
   __asm vec4_min __retVal.x, a.x, b.x;
}

vec2 min(const vec2 a, const vec2 b)
{
   __asm vec4_min __retVal.xy, a.xy, b.xy;
}

vec3 min(const vec3 a, const vec3 b)
{
   __asm vec4_min __retVal.xyz, a.xyz, b.xyz;
}

vec4 min(const vec4 a, const vec4 b)
{
   __asm vec4_min __retVal, a, b;
}

vec2 min(const vec2 a, const float b)
{
   __asm vec4_min __retVal, a.xy, b.xx;
}

vec3 min(const vec3 a, const float b)
{
   __asm vec4_min __retVal, a.xyz, b.xxx;
}

vec4 min(const vec4 a, const float b)
{
   __asm vec4_min __retVal, a, b.xxxx;
}


//// max

float max(const float a, const float b)
{
   __asm vec4_max __retVal.x, a.x, b.x;
}

vec2 max(const vec2 a, const vec2 b)
{
   __asm vec4_max __retVal.xy, a.xy, b.xy;
}

vec3 max(const vec3 a, const vec3 b)
{
   __asm vec4_max __retVal.xyz, a.xyz, b.xyz;
}

vec4 max(const vec4 a, const vec4 b)
{
   __asm vec4_max __retVal, a, b;
}

vec2 max(const vec2 a, const float b)
{
   __asm vec4_max __retVal, a.xy, b.xx;
}

vec3 max(const vec3 a, const float b)
{
   __asm vec4_max __retVal, a.xyz, b.xxx;
}

vec4 max(const vec4 a, const float b)
{
   __asm vec4_max __retVal, a, b.xxxx;
}


//// clamp

float clamp(const float val, const float minVal, const float maxVal)
{
   __asm vec4_clamp __retVal, val, minVal, maxVal;
}

vec2 clamp(const vec2 val, const float minVal, const float maxVal)
{
   __asm vec4_clamp __retVal, val, minVal, maxVal;
}

vec3 clamp(const vec3 val, const float minVal, const float maxVal)
{
   __asm vec4_clamp __retVal, val, minVal, maxVal;
}

vec4 clamp(const vec4 val, const float minVal, const float maxVal)
{
   __asm vec4_clamp __retVal, val, minVal, maxVal;
}

vec2 clamp(const vec2 val, const vec2 minVal, const vec2 maxVal)
{
   __asm vec4_clamp __retVal, val, minVal, maxVal;
}

vec3 clamp(const vec3 val, const vec3 minVal, const vec3 maxVal)
{
   __asm vec4_clamp __retVal, val, minVal, maxVal;
}

vec4 clamp(const vec4 val, const vec4 minVal, const vec4 maxVal)
{
   __asm vec4_clamp __retVal, val, minVal, maxVal;
}


//// mix

float mix(const float x, const float y, const float a)
{
   __asm vec4_lrp __retVal, a, y, x;
}

vec2 mix(const vec2 x, const vec2 y, const float a)
{
   __asm vec4_lrp __retVal, a, y, x;
}

vec3 mix(const vec3 x, const vec3 y, const float a)
{
   __asm vec4_lrp __retVal, a, y, x;
}

vec4 mix(const vec4 x, const vec4 y, const float a)
{
   __asm vec4_lrp __retVal, a, y, x;
}

vec2 mix(const vec2 x, const vec2 y, const vec2 a)
{
   __asm vec4_lrp __retVal, a, y, x;
}

vec3 mix(const vec3 x, const vec3 y, const vec3 a)
{
   __asm vec4_lrp __retVal, a, y, x;
}

vec4 mix(const vec4 x, const vec4 y, const vec4 a)
{
   __asm vec4_lrp __retVal, a, y, x;
}


//// step (untested)

float step(const float edge, const float x)
{
   __asm vec4_sgt __retVal.x, x, edge;
}

vec2 step(const vec2 edge, const vec2 x)
{
   __asm vec4_sgt __retVal.xy, x, edge;
}

vec3 step(const vec3 edge, const vec3 x)
{
   __asm vec4_sgt __retVal.xyz, x, edge;
}

vec4 step(const vec4 edge, const vec4 x)
{
   __asm vec4_sgt __retVal, x, edge;
}

vec2 step(const float edge, const vec2 v)
{
   __asm vec4_sgt __retVal.xy, v, edge.xx;
}

vec3 step(const float edge, const vec3 v)
{
   __asm vec4_sgt __retVal.xyz, v, edge.xxx;
}

vec4 step(const float edge, const vec4 v)
{
   __asm vec4_sgt __retVal, v, edge.xxxx;
}


//// smoothstep (untested)

float smoothstep(const float edge0, const float edge1, const float x)
{
    float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
    return t * t * (3.0 - 2.0 * t);
}

vec2 smoothstep(const vec2 edge0, const vec2 edge1, const vec2 v)
{
   vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
   return t * t * (3.0 - 2.0 * t);
}

vec3 smoothstep(const vec3 edge0, const vec3 edge1, const vec3 v)
{
   vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
   return t * t * (3.0 - 2.0 * t);
}

vec4 smoothstep(const vec4 edge0, const vec4 edge1, const vec4 v)
{
   vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
   return t * t * (3.0 - 2.0 * t);
}

vec2 smoothstep(const float edge0, const float edge1, const vec2 v)
{
   vec2 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
   return t * t * (3.0 - 2.0 * t);
}

vec3 smoothstep(const float edge0, const float edge1, const vec3 v)
{
   vec3 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
   return t * t * (3.0 - 2.0 * t);
}

vec4 smoothstep(const float edge0, const float edge1, const vec4 v)
{
   vec4 t = clamp((v - edge0) / (edge1 - edge0), 0.0, 1.0);
   return t * t * (3.0 - 2.0 * t);
}



//
// 8.4 Geometric Functions
//


//// length

float length(const float x)
{
   return abs(x);
}

float length(const vec2 v)
{
   float r;
   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y
   __asm float_rsq r, p;           // r = 1 / sqrt(p)
   __asm float_rcp __retVal.x, r;  // retVal = 1 / r
}

float length(const vec3 v)
{
   float r;
   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y + v.z * v.z
   __asm float_rsq r, p;           // r = 1 / sqrt(p)
   __asm float_rcp __retVal.x, r;  // retVal = 1 / r
}

float length(const vec4 v)
{
   float r;
   const float p = dot(v, v);      // p = v.x * v.x + v.y * v.y + ...
   __asm float_rsq r, p;           // r = 1 / sqrt(p)
   __asm float_rcp __retVal.x, r;  // retVal = 1 / r
}


//// distance

float distance(const float x, const float y)
{
   const float d = x - y;
   __retVal = length(d);
}

float distance(const vec2 v, const vec2 u)
{
   const vec2 d2 = v - u;
   __retVal = length(d2);
}

float distance(const vec3 v, const vec3 u)
{
   const vec3 d3 = v - u;
   __retVal = length(d3);
}

float distance(const vec4 v, const vec4 u)
{
   const vec4 d4 = v - u;
   __retVal = length(d4);
}


//// cross

vec3 cross(const vec3 v, const vec3 u)
{
   __asm vec3_cross __retVal.xyz, v, u;
}


//// faceforward

float faceforward(const float N, const float I, const float Nref)
{
    // this could probably be done better
    const float d = dot(Nref, I);
    float s;
    __asm vec4_sgt s.x, 0.0, d;  // s = (0.0 > d) ? 1 : 0
    return mix(-N, N, s);
}

vec2 faceforward(const vec2 N, const vec2 I, const vec2 Nref)
{
    // this could probably be done better
    const float d = dot(Nref, I);
    float s;
    __asm vec4_sgt s.x, 0.0, d;  // s = (0.0 > d) ? 1 : 0
    return mix(-N, N, s);
}

vec3 faceforward(const vec3 N, const vec3 I, const vec3 Nref)
{
    // this could probably be done better
    const float d = dot(Nref, I);
    float s;
    __asm vec4_sgt s.x, 0.0, d;  // s = (0.0 > d) ? 1 : 0
    return mix(-N, N, s);
}

vec4 faceforward(const vec4 N, const vec4 I, const vec4 Nref)
{
    // this could probably be done better
    const float d = dot(Nref, I);
    float s;
    __asm vec4_sgt s.x, 0.0, d;  // s = (0.0 > d) ? 1 : 0
    return mix(-N, N, s);
}


//// reflect

float reflect(const float I, const float N)
{
   return I - 2.0 * dot(N, I) * N;
}

vec2 reflect(const vec2 I, const vec2 N)
{
   return I - 2.0 * dot(N, I) * N;
}

vec3 reflect(const vec3 I, const vec3 N)
{
   return I - 2.0 * dot(N, I) * N;
}

vec4 reflect(const vec4 I, const vec4 N)
{
   return I - 2.0 * dot(N, I) * N;
}

//// refract

float refract(const float I, const float N, const float eta)
{
   float k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I));
   if (k < 0.0)
       return 0.0;
   return eta * I - (eta * dot(N, I) + sqrt(k)) * N;
}

vec2 refract(const vec2 I, const vec2 N, const float eta)
{
   float k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I));
   if (k < 0.0)
      return 0.0;
   return eta * I - (eta * dot(N, I) + sqrt(k)) * N;
}

vec3 refract(const vec3 I, const vec3 N, const float eta)
{
   float k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I));
   if (k < 0.0)
      return 0.0;
   return eta * I - (eta * dot(N, I) + sqrt(k)) * N;
}

vec4 refract(const vec4 I, const vec4 N, const float eta)
{
   float k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I));
   if (k < 0.0)
      return 0.0;
   return eta * I - (eta * dot(N, I) + sqrt(k)) * N;
}




//
// 8.5 Matrix Functions
//

mat2 matrixCompMult (mat2 m, mat2 n) {
    return mat2 (m[0] * n[0], m[1] * n[1]);
}

mat3 matrixCompMult (mat3 m, mat3 n) {
    return mat3 (m[0] * n[0], m[1] * n[1], m[2] * n[2]);
}

mat4 matrixCompMult (mat4 m, mat4 n) {
    return mat4 (m[0] * n[0], m[1] * n[1], m[2] * n[2], m[3] * n[3]);
}




//
// 8.6 Vector Relational Functions
//

//// lessThan

bvec2 lessThan(const vec2 u, const vec2 v)
{
   __asm vec4_slt __retVal.xy, u, v;
}

bvec3 lessThan(const vec3 u, const vec3 v)
{
   __asm vec4_slt __retVal.xyz, u, v;
}

bvec4 lessThan(const vec4 u, const vec4 v)
{
   __asm vec4_slt __retVal, u, v;
}

bvec2 lessThan(const ivec2 u, const ivec2 v)
{
   __asm vec4_slt __retVal.xy, u, v;
}

bvec3 lessThan(const ivec3 u, const ivec3 v)
{
   __asm vec4_slt __retVal.xyz, u, v;
}

bvec4 lessThan(const ivec4 u, const ivec4 v)
{
   __asm vec4_slt __retVal, u, v;
}


//// lessThanEqual

bvec2 lessThanEqual(const vec2 u, const vec2 v)
{
   __asm vec4_sle __retVal.xy, u, v;
}

bvec3 lessThanEqual(const vec3 u, const vec3 v)
{
   __asm vec4_sle __retVal.xyz, u, v;
}

bvec4 lessThanEqual(const vec4 u, const vec4 v)
{
   __asm vec4_sle __retVal, u, v;
}

bvec2 lessThanEqual(const ivec2 u, const ivec2 v)
{
   __asm vec4_sle __retVal.xy, u, v;
}

bvec3 lessThanEqual(const ivec3 u, const ivec3 v)
{
   __asm vec4_sle __retVal.xyz, u, v;
}

bvec4 lessThanEqual(const ivec4 u, const ivec4 v)
{
   __asm vec4_sle __retVal, u, v;
}


//// greaterThan

bvec2 greaterThan(const vec2 u, const vec2 v)
{
   __asm vec4_sgt __retVal.xy, u, v;
}

bvec3 greaterThan(const vec3 u, const vec3 v)
{
   __asm vec4_sgt __retVal.xyz, u, v;
}

bvec4 greaterThan(const vec4 u, const vec4 v)
{
   __asm vec4_sgt __retVal, u, v;
}

bvec2 greaterThan(const ivec2 u, const ivec2 v)
{
   __asm vec4_sgt __retVal.xy, u, v;
}

bvec3 greaterThan(const ivec3 u, const ivec3 v)
{
   __asm vec4_sgt __retVal.xyz, u, v;
}

bvec4 greaterThan(const ivec4 u, const ivec4 v)
{
   __asm vec4_sgt __retVal, u, v;
}


//// greaterThanEqual

bvec2 greaterThanEqual(const vec2 u, const vec2 v)
{
   __asm vec4_sge __retVal.xy, u, v;
}

bvec3 greaterThanEqual(const vec3 u, const vec3 v)
{
   __asm vec4_sge __retVal.xyz, u, v;
}

bvec4 greaterThanEqual(const vec4 u, const vec4 v)
{
   __asm vec4_sge __retVal, u, v;
}

bvec2 greaterThanEqual(const ivec2 u, const ivec2 v)
{
   __asm vec4_sge __retVal.xy, u, v;
}

bvec3 greaterThanEqual(const ivec3 u, const ivec3 v)
{
   __asm vec4_sge __retVal.xyz, u, v;
}

bvec4 greaterThanEqual(const ivec4 u, const ivec4 v)
{
   __asm vec4_sge __retVal, u, v;
}


//// equal

bvec2 equal(const vec2 u, const vec2 v)
{
   __asm vec4_seq __retVal.xy, u, v;
}

bvec3 equal(const vec3 u, const vec3 v)
{
   __asm vec4_seq __retVal.xyz, u, v;
}

bvec4 equal(const vec4 u, const vec4 v)
{
   __asm vec4_seq __retVal, u, v;
}

bvec2 equal(const ivec2 u, const ivec2 v)
{
   __asm vec4_seq __retVal.xy, u, v;
}

bvec3 equal(const ivec3 u, const ivec3 v)
{
   __asm vec4_seq __retVal.xyz, u, v;
}

bvec4 equal(const ivec4 u, const ivec4 v)
{
   __asm vec4_seq __retVal, u, v;
}


//// notEqual

bvec2 notEqual(const vec2 u, const vec2 v)
{
   __asm vec4_sne __retVal.xy, u, v;
}

bvec3 notEqual(const vec3 u, const vec3 v)
{
   __asm vec4_sne __retVal.xyz, u, v;
}

bvec4 notEqual(const vec4 u, const vec4 v)
{
   __asm vec4_sne __retVal, u, v;
}

bvec2 notEqual(const ivec2 u, const ivec2 v)
{
   __asm vec4_sne __retVal.xy, u, v;
}

bvec3 notEqual(const ivec3 u, const ivec3 v)
{
   __asm vec4_sne __retVal.xyz, u, v;
}

bvec4 notEqual(const ivec4 u, const ivec4 v)
{
   __asm vec4_sne __retVal, u, v;
}


//// any

bool any(const bvec2 v)
{
   float sum;
   __asm vec4_add sum.x, v.x, v.y;
   __asm vec4_sne __retVal.x, sum.x, 0.0;
}

bool any(const bvec3 v)
{
   float sum;
   __asm vec4_add sum.x, v.x, v.y;
   __asm vec4_add sum.x, sum.x, v.z;
   __asm vec4_sne __retVal.x, sum.x, 0.0;
}

bool any(const bvec4 v)
{
   float sum;
   __asm vec4_add sum.x, v.x, v.y;
   __asm vec4_add sum.x, sum.x, v.z;
   __asm vec4_add sum.x, sum.x, v.w;
   __asm vec4_sne __retVal.x, sum.x, 0.0;
}


//// all

bool all (const vec2 v)
{
   float prod;
   __asm vec4_multiply prod.x, v.x, v.y;
   __asm vec4_sne __retVal.x, prod.x, 0.0;
    return v.x && v.y;
}

bool all (const bvec3 v)
{
   float prod;
   __asm vec4_multiply prod.x, v.x, v.y;
   __asm vec4_multiply prod.x, prod.x, v.z;
   __asm vec4_sne __retVal.x, prod.x, 0.0;
}

bool all (const bvec4 v)
{
   float prod;
   __asm vec4_multiply prod.x, v.x, v.y;
   __asm vec4_multiply prod.x, prod.x, v.z;
   __asm vec4_multiply prod.x, prod.x, v.w;
   __asm vec4_sne __retVal.x, prod.x, 0.0;
}



//// not

bvec2 not (const bvec2 v)
{
   __asm vec4_seq __retVal.xy, v, 0.0;
}

bvec3 not (const bvec3 v)
{
   __asm vec4_seq __retVal.xyz, v, 0.0;
}

bvec4 not (const bvec4 v)
{
   __asm vec4_seq __retVal, v, 0.0;
}



//// Texture Lookup Functions  (for both fragment and vertex shaders)

vec4 texture1D(const sampler1D sampler, const float coord)
{
   __asm vec4_tex1d __retVal, sampler, coord;
}

vec4 texture1DProj(const sampler1D sampler, const vec2 coord)
{
   // need to swizzle .y into .w
   __asm vec4_texp1d __retVal, sampler, coord.xyyy;
}

vec4 texture1DProj(const sampler1D sampler, const vec4 coord)
{
   __asm vec4_texp1d __retVal, sampler, coord;
}


vec4 texture2D(const sampler2D sampler, const vec2 coord)
{
   __asm vec4_tex2d __retVal, sampler, coord;
}

vec4 texture2DProj(const sampler2D sampler, const vec3 coord)
{
   // need to swizzle 'z' into 'w'.
   __asm vec4_texp2d __retVal, sampler, coord.xyzz;
}

vec4 texture2DProj(const sampler2D sampler, const vec4 coord)
{
   __asm vec4_texp2d __retVal, sampler, coord;
}


vec4 texture3D(const sampler3D sampler, const vec3 coord)
{
   __asm vec4_tex3d __retVal, sampler, coord;
}

vec4 texture3DProj(const sampler3D sampler, const vec4 coord)
{
   __asm vec4_texp3d __retVal, sampler, coord;
}


vec4 textureCube(const samplerCube sampler, const vec3 coord)
{
   __asm vec4_texcube __retVal, sampler, coord;
}



vec4 shadow1D(const sampler1DShadow sampler, const vec3 coord)
{
   __asm vec4_tex1d __retVal, sampler, coord;
}

vec4 shadow1DProj(const sampler1DShadow sampler, const vec4 coord)
{
   // .s and .p will be divided by .q
   __asm vec4_texp1d __retVal, sampler, coord;
}

vec4 shadow2D(const sampler2DShadow sampler, const vec3 coord)
{
   __asm vec4_tex2d __retVal, sampler, coord;
}

vec4 shadow2DProj(const sampler2DShadow sampler, const vec4 coord)
{
   // .s, .t and .p will be divided by .q
   __asm vec4_texp2d __retVal, sampler, coord;
}


//// GL_ARB_texture_rectangle:
vec4 texture2DRect(const sampler2DRect sampler, const vec2 coord)
{
   __asm vec4_tex_rect __retVal, sampler, coord;
}

vec4 texture2DRectProj(const sampler2DRect sampler, const vec3 coord)
{
   // need to swizzle .y into .w
   __asm vec4_texp_rect __retVal, sampler, coord.xyzz;
}

vec4 texture2DRectProj(const sampler2DRect sampler, const vec4 coord)
{
   __asm vec4_texp_rect __retVal, sampler, ccoord;
}

vec4 shadow2DRect(const sampler2DRectShadow sampler, const vec3 coord)
{
   __asm vec4_tex_rect __retVal, sampler, coord;
}

vec4 shadow2DRectProj(const sampler2DRectShadow sampler, const vec4 coord)
{
   __asm vec4_texp_rect __retVal, sampler, coord;
}



//
// 8.9 Noise Functions
//
// AUTHOR: Stefan Gustavson (stegu@itn.liu.se), Nov 26, 2005
//

float noise1(const float x)
{
   __asm float_noise1 __retVal, x;
}


float noise1(const vec2 x)
{
    __asm float_noise2 __retVal, x;
}

float noise1(const vec3 x)
{
    __asm float_noise3 __retVal, x;
}

float noise1(const vec4 x)
{
    __asm float_noise4 __retVal, x;
}

vec2 noise2(const float x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + 19.34);
}

vec2 noise2(const vec2 x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + vec2(19.34, 7.66));
}

vec2 noise2(const vec3 x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
}

vec2 noise2(const vec4 x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
}

vec3 noise3(const float x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + 19.34);
   __retVal.z = noise1(x + 5.47);
}

vec3 noise3(const vec2 x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + vec2(19.34, 7.66));
   __retVal.z = noise1(x + vec2(5.47, 17.85));
}

vec3 noise3(const vec3 x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
   __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
}

vec3 noise3(const vec4 x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
   __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
}

vec4 noise4(const float x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + 19.34);
   __retVal.z = noise1(x + 5.47);
   __retVal.w = noise1(x + 23.54);
}

vec4 noise4(const vec2 x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + vec2 (19.34, 7.66));
   __retVal.z = noise1(x + vec2 (5.47, 17.85));
   __retVal.w = noise1(x + vec2 (23.54, 29.11));
}

vec4 noise4(const vec3 x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + vec3(19.34, 7.66, 3.23));
   __retVal.z = noise1(x + vec3(5.47, 17.85, 11.04));
   __retVal.w = noise1(x + vec3(23.54, 29.11, 31.91));
}

vec4 noise4(const vec4 x)
{
   __retVal.x = noise1(x);
   __retVal.y = noise1(x + vec4(19.34, 7.66, 3.23, 2.77));
   __retVal.z = noise1(x + vec4(5.47, 17.85, 11.04, 13.19));
   __retVal.w = noise1(x + vec4(23.54, 29.11, 31.91, 37.48));
}
