/*
 * 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.
 */

//
// This file defines nearly all constructors and operators for built-in data
// types, using extended language syntax. In general, compiler treats
// constructors and operators as ordinary functions with some exceptions.
// For example, the language does not allow functions to be called in
// constant expressions - here the exception is made to allow it.
//
// Each implementation provides its own version of this file. Each
// implementation can define the required set of operators and constructors
// in its own fashion.
//
// The extended language syntax is only present when compiling this file.
// It is implicitly included at the very beginning of the compiled shader,
// so no built-in functions can be used.
//
// To communicate with the implementation, a special extended "__asm" keyword
// is used, followed by an instruction name (any valid identifier), a
// destination variable identifier and a list of zero or more source
// variable identifiers.
//
// A variable identifier is a variable name declared earlier in the code
// (as a function parameter, local or global variable).
//
// An instruction name designates an instruction that must be exported
// by the implementation.  Each instruction receives data from source
// variable identifiers and returns data in the destination variable
// identifier.
//
// It is up to the implementation how to define a particular operator
// or constructor. If it is expected to being used rarely, it can be
// defined in terms of other operators and constructors,
// for example:
//
// ivec2 __operator + (const ivec2 x, const ivec2 y) {
//    return ivec2 (x[0] + y[0], x[1] + y[1]);
// }
//
// If a particular operator or constructor is expected to be used very
// often or is an atomic operation (that is, an operation that cannot be
// expressed in terms of other operations or would create a dependency
// cycle) it must be defined using one or more __asm constructs.
//
// Each implementation must define constructors for all scalar types
// (bool, float, int).  There are 9 scalar-to-scalar constructors
// (including identity constructors). However, since the language
// introduces special constructors (like matrix constructor with a single
// scalar value), implementations must also implement these cases.
// The compiler provides the following algorithm when resolving a constructor:
// - try to find a constructor with a prototype matching ours,
// - if no constructor is found and this is a scalar-to-scalar constructor,
//   raise an error,
// - if a constructor is found, execute it and return,
// - count the size of the constructor parameter list - if it is less than
//   the size of our constructor's type, raise an error,
// - for each parameter in the list do a recursive constructor matching for
//   appropriate scalar fields in the constructed variable,
//
// Each implementation must also define a set of operators that deal with
// built-in data types.
// There are four kinds of operators:
// 1) Operators that are implemented only by the compiler: "()" (function
//    call), "," (sequence) and "?:" (selection).
// 2) Operators that are implemented by the compiler by expressing it in
//    terms of other operators:
//    - "." (field selection) - translated to subscript access,
//    - "&&" (logical and) - translated to "<left_expr> ? <right_expr> :
//      false",
//    - "||" (logical or) - translated to "<left_expr> ? true : <right_expr>",
// 3) Operators that can be defined by the implementation and if the required
//    prototype is not found, standard behaviour is used:
//    - "==", "!=", "=" (equality, assignment) - compare or assign
//      matching fields one-by-one;
//      note that at least operators for scalar data types must be defined
//      by the implementation to get it work,
// 4) All other operators not mentioned above. If no required prototype is
//    found, an error is raised. An implementation must follow the language
//    specification to provide all valid operator prototypes.
//



//// Basic, scalar constructors/casts

int __constructor(const float f)
{
   __asm float_to_int __retVal, f;
}

bool __constructor(const int i)
{
   const float zero = 0.0;
   __asm vec4_seq __retVal, i, zero;
}

bool __constructor(const float f)
{
   const float zero = 0.0;
   __asm vec4_seq __retVal, i, zero;
}

int __constructor(const bool b)
{
   __retVal = b;
}

float __constructor(const bool b)
{
   __retVal = b;
}

float __constructor(const int i)
{
    __asm int_to_float __retVal, i;
}

bool __constructor(const bool b)
{
   __retVal = b;
}

int __constructor(const int i)
{
   __retVal = i;
}

float __constructor(const float f)
{
   __retVal = f;
}


//// vec2 constructors

vec2 __constructor(const float x, const float y)
{
   __retVal.x = x;
   __retVal.y = y;
}

vec2 __constructor(const float f)
{
   __retVal.xy = f.xx;
}

vec2 __constructor(const int i)
{
   __retVal.xy = i.xx;
}

vec2 __constructor(const bool b)
{
   __retVal.xy = b.xx;
}

vec2 __constructor(const vec3 v)
{
   __retVal.xy = v.xy;
}

vec2 __constructor(const vec4 v)
{
   __retVal.xy = v.xy;
}


//// vec3 constructors

vec3 __constructor(const float x, const float y, const float z)
{
   __retVal.x = x;
   __retVal.y = y;
   __retVal.z = z;
}

vec3 __constructor(const float f)
{
   __retVal.xyz = f.xxx;
}

vec3 __constructor(const int i)
{
   __asm int_to_float __retVal.xyz, i.xxx;
}

vec3 __constructor(const bool b)
{
   __retVal.xyz = b.xxx;
}

vec3 __constructor(const vec4 v)
{
   __retVal.xyz = v.xyz;
}


//// vec4 constructors

vec4 __constructor(const float x, const float y, const float z, const float w)
{
   __retVal.x = x;
   __retVal.y = y;
   __retVal.z = z;
   __retVal.w = w;
}

vec4 __constructor(const float f)
{
   __retVal = f.xxxx;
}

vec4 __constructor(const int i)
{
   __retVal = i.xxxx;
}

vec4 __constructor(const bool b)
{
   __retVal = b.xxxx;
}

vec4 __constructor(const vec3 v3, const float f)
{
   // XXX this constructor shouldn't be needed anymore
   __retVal.xyz = v3;
   __retVal.w = f;
}


//// ivec2 constructors

ivec2 __constructor(const int i, const int j)
{
   __retVal.x = i;
   __retVal.y = j;
}

ivec2 __constructor(const int i)
{
   __retVal.xy = i.xx;
}

ivec2 __constructor(const float f)
{
   __asm float_to_int __retVal.xy, f.xx;
}

ivec2 __constructor(const bool b)
{
   __asm float_to_int __retVal.xy, b.xx;
}


//// ivec3 constructors

ivec3 __constructor(const int i, const int j, const int k)
{
   __retVal.x = i;
   __retVal.y = j;
   __retVal.z = k;
}

ivec3 __constructor(const int i)
{
   __retVal.xyz = i.xxx;
}

ivec3 __constructor(const float f)
{
   __retVal.xyz = f.xxx;
}

ivec3 __constructor(const bool b)
{
   __retVal.xyz = b.xxx;
}


//// ivec4 constructors

ivec4 __constructor(const int x, const int y, const int z, const int w)
{
   __retVal.x = x;
   __retVal.y = y;
   __retVal.z = z;
   __retVal.w = w;
}

ivec4 __constructor(const int i)
{
   __retVal = i.xxxx;
}

ivec4 __constructor(const float f)
{
   __asm float_to_int __retVal, f.xxxx;
}

ivec4 __constructor(const bool b)
{
   __retVal = b.xxxx;
}


//// bvec2 constructors

bvec2 __constructor(const bool b1, const bool b2)
{
   __retVal.x = b1;
   __retVal.y = b2;
}

bvec2 __constructor(const bool b)
{
   __retVal.xy = b.xx;
}

bvec2 __constructor(const float f)
{
   const vec2 zero = vec2(0.0, 0.0);
   __asm vec4_seq __retVal.xy, f.xx, zero;
}

bvec2 __constructor(const int i)
{
   const ivec2 zero = ivec2(0, 0);
   __asm vec4_seq __retVal.xy, i.xx, zero;
}


//// bvec3 constructors

bvec3 __constructor(const bool b1, const bool b2, const bool b3)
{
   __retVal.x = b1;
   __retVal.y = b2;
   __retVal.z = b3;
}

bvec3 __constructor(const bool b)
{
   __retVal.xyz = b.xxx;
}

bvec3 __constructor(const float f)
{
   const vec3 zero = vec3(0.0, 0.0, 0.0);
   __asm vec4_seq __retVal.xyz, f.xxx, zero;
}

bvec3 __constructor(const int i)
{
   const ivec3 zero = ivec3(0, 0, 0);
   __asm vec4_seq __retVal.xyz, i.xxx, zero;
}


//// bvec4 constructors

bvec4 __constructor(const bool b1, const bool b2, const bool b3, const bool b4)
{
   __retVal.x = b1;
   __retVal.y = b2;
   __retVal.z = b3;
   __retVal.w = b4;
}

bvec4 __constructor(const bool b)
{
   __retVal.xyzw = b.xxxx;
}

bvec4 __constructor(const float f)
{
   const vec4 zero = vec4(0.0, 0.0, 0.0, 0.0);
   __asm vec4_seq __retVal, f.xxxx, zero;
}

bvec4 __constructor(const int i)
{
   const ivec4 zero = ivec4(0, 0, 0, 0);
   __asm vec4_seq __retVal, i.xxxx, zero;
}



//// mat2 constructors

mat2 __constructor(const float m00, const float m10,
                   const float m01, const float m11)
{
   __retVal[0].x = m00;
   __retVal[0].y = m10;
   __retVal[1].x = m01;
   __retVal[1].y = m11;
}

mat2 __constructor(const float f)
{
   __retVal[0].x = f;
   __retVal[0].y = 0.0;
   __retVal[1].x = 0.0;
   __retVal[1].y = f;
}

mat2 __constructor(const int i)
{
   return mat2(float(i));
}

mat2 __constructor(const bool b)
{
   return mat2(float(b));
}

mat2 __constructor(const vec2 c0, const vec2 c1)
{
   __retVal[0] = c0;
   __retVal[1] = c1;
}


//// mat3 constructors

mat3 __constructor(const float m00, const float m10, const float m20,
                   const float m01, const float m11, const float m21,
                   const float m02, const float m12, const float m22)
{
   __retVal[0].x = m00;
   __retVal[0].y = m10;
   __retVal[0].z = m20;
   __retVal[1].x = m01;
   __retVal[1].y = m11;
   __retVal[1].z = m21;
   __retVal[2].x = m02;
   __retVal[2].y = m12;
   __retVal[2].z = m22;
}

mat3 __constructor(const float f)
{
   vec2 v = vec2(f, 0.0);
   __retVal[0] = v.xyy;
   __retVal[1] = v.yxy;
   __retVal[2] = v.yyx;
}

mat3 __constructor(const int i)
{
   return mat3(float(i));
}

mat3 __constructor(const bool b)
{
   return mat3(float(b));
}

mat3 __constructor(const vec3 c0, const vec3 c1, const vec3 c2)
{
   __retVal[0] = c0;
   __retVal[1] = c1;
   __retVal[2] = c2;
}


//// mat4 constructors

mat4 __constructor(const float m00, const float m10, const float m20, const float m30,
                   const float m01, const float m11, const float m21, const float m31,
                   const float m02, const float m12, const float m22, const float m32,
                   const float m03, const float m13, const float m23, const float m33)
{
   __retVal[0].x = m00;
   __retVal[0].y = m10;
   __retVal[0].z = m20;
   __retVal[0].w = m30;
   __retVal[1].x = m01;
   __retVal[1].y = m11;
   __retVal[1].z = m21;
   __retVal[1].w = m31;
   __retVal[2].x = m02;
   __retVal[2].y = m12;
   __retVal[2].z = m22;
   __retVal[2].w = m32;
   __retVal[3].x = m03;
   __retVal[3].y = m13;
   __retVal[3].z = m23;
   __retVal[3].w = m33;
}


mat4 __constructor(const float f)
{
   vec2 v = vec2(f, 0.0);
   __retVal[0] = v.xyyy;
   __retVal[1] = v.yxyy;
   __retVal[2] = v.yyxy;
   __retVal[3] = v.yyyx;
}

mat4 __constructor(const int i)
{
   return mat4(float(i));
}

mat4 __constructor(const bool b)
{
   return mat4(float(b));
}

mat4 __constructor(const vec4 c0, const vec4 c1, const vec4 c2, const vec4 c3)
{
   __retVal[0] = c0;
   __retVal[1] = c1;
   __retVal[2] = c2;
   __retVal[3] = c3;
}



//// Basic int operators

int __operator + (const int a, const int b)
{
// XXX If we ever have int registers, we'll do something like this:
// XXX For now, mostly treat ints as floats.
//    float x, y;
//    __asm int_to_float x, a;
//    __asm int_to_float y, b;
//    __asm vec4_add x.x, x.x, y.x;
//    __asm float_to_int __retVal, x;
   float x;
   __asm vec4_add x, a, b;
   __asm float_to_int __retVal, x;
}

int __operator - (const int a, const int b)
{
   float x;
   __asm vec4_subtract x, a, b;
   __asm float_to_int __retVal, x;
}

int __operator * (const int a, const int b)
{
   float x;
   __asm vec4_multiply x, a, b;
   __asm float_to_int __retVal, x;
}

int __operator / (const int a, const int b)
{
   float bInv, x;
   __asm float_rcp bInv, b;
   __asm vec4_multiply x, a, bInv;
   __asm float_to_int __retVal, x;
}


//// Basic ivec2 operators

ivec2 __operator + (const ivec2 a, const ivec2 b)
{
   vec2 x;
   __asm vec4_add x, a, b;
   __asm float_to_int __retVal, x;
}

ivec2 __operator - (const ivec2 a, const ivec2 b)
{
   vec2 x;
   __asm vec4_subtract x, a, b;
   __asm float_to_int __retVal, x;
}

ivec2 __operator * (const ivec2 a, const ivec2 b)
{
   vec2 x;
   __asm vec4_multiply x, a, b;
   __asm float_to_int __retVal, x;
}

ivec2 __operator / (const ivec2 a, const ivec2 b)
{
   vec2 bInv, x;
   __asm float_rcp bInv.x, b.x;
   __asm float_rcp bInv.y, b.y;
   __asm vec4_multiply x, a, bInv;
   __asm float_to_int __retVal, x;
}


//// Basic ivec3 operators

ivec3 __operator + (const ivec3 a, const ivec3 b)
{
   vec3 x;
   __asm vec4_add x, a, b;
   __asm float_to_int __retVal, x;
}

ivec3 __operator - (const ivec3 a, const ivec3 b)
{
   vec3 x;
   __asm vec4_subtract x, a, b;
   __asm float_to_int __retVal, x;
}

ivec3 __operator * (const ivec3 a, const ivec3 b)
{
   vec3 x;
   __asm vec4_multiply x, a, b;
   __asm float_to_int __retVal, x;
}

ivec3 __operator / (const ivec3 a, const ivec3 b)
{
   vec3 bInv, x;
   __asm float_rcp bInv.x, b.x;
   __asm float_rcp bInv.y, b.y;
   __asm float_rcp bInv.z, b.z;
   __asm vec4_multiply x, a, bInv;
   __asm float_to_int __retVal, x;
}


//// Basic ivec4 operators

ivec4 __operator + (const ivec4 a, const ivec4 b)
{
   vec3 x;
   __asm vec4_add x, a, b;
   __asm float_to_int __retVal, x;
}

ivec4 __operator - (const ivec4 a, const ivec4 b)
{
   vec4 x;
   __asm vec4_subtract x, a, b;
   __asm float_to_int __retVal, x;
}

ivec4 __operator * (const ivec4 a, const ivec4 b)
{
   vec4 x;
   __asm vec4_multiply x, a, b;
   __asm float_to_int __retVal, x;
}

ivec4 __operator / (const ivec4 a, const ivec4 b)
{
   vec4 bInv, x;
   __asm float_rcp bInv.x, b.x;
   __asm float_rcp bInv.y, b.y;
   __asm float_rcp bInv.z, b.z;
   __asm float_rcp bInv.w, b.w;
   __asm vec4_multiply x, a, bInv;
   __asm float_to_int __retVal, x;
}


//// Basic float operators

float __operator + (const float a, const float b)
{
   __asm vec4_add __retVal.x, a, b;
}

float __operator - (const float a, const float b)
{
   __asm vec4_subtract __retVal.x, a, b;
}

float __operator * (const float a, const float b)
{
    __asm vec4_multiply __retVal.x, a, b;
}

float __operator / (const float a, const float b)
{
   float bInv;
   __asm float_rcp bInv.x, b.x;
   __asm vec4_multiply __retVal.x, a, bInv;
}


//// Basic vec2 operators

vec2 __operator + (const vec2 v, const vec2 u)
{
   __asm vec4_add __retVal.xy, v, u;
}

vec2 __operator - (const vec2 v, const vec2 u)
{
    __asm vec4_subtract __retVal.xy, v, u;
}

vec2 __operator * (const vec2 v, const vec2 u)
{
    __asm vec4_multiply __retVal.xy, v, u;
}

vec2 __operator / (const vec2 v, const vec2 u)
{
   vec2 w; // = 1 / u
   __asm float_rcp w.x, u.x;
   __asm float_rcp w.y, u.y;
   __asm vec4_multiply __retVal.xy, v, w;
}


//// Basic vec3 operators

vec3 __operator + (const vec3 v, const vec3 u)
{
   __asm vec4_add __retVal.xyz, v, u;
}

vec3 __operator - (const vec3 v, const vec3 u)
{
    __asm vec4_subtract __retVal.xyz, v, u;
}

vec3 __operator * (const vec3 v, const vec3 u)
{
    __asm vec4_multiply __retVal.xyz, v, u;
}

vec3 __operator / (const vec3 v, const vec3 u)
{
   vec3 w; // = 1 / u
   __asm float_rcp w.x, u.x;
   __asm float_rcp w.y, u.y;
   __asm float_rcp w.z, u.z;
   __asm vec4_multiply __retVal.xyz, v, w;
}


//// Basic vec4 operators

vec4 __operator + (const vec4 v, const vec4 u)
{
   __asm vec4_add __retVal, v, u;
}

vec4 __operator - (const vec4 v, const vec4 u)
{
    __asm vec4_subtract __retVal, v, u;
}

vec4 __operator * (const vec4 v, const vec4 u)
{
    __asm vec4_multiply __retVal, v, u;
}

vec4 __operator / (const vec4 v, const vec4 u)
{
   vec4 w; // = 1 / u
   __asm float_rcp w.x, u.x;
   __asm float_rcp w.y, u.y;
   __asm float_rcp w.z, u.z;
   __asm float_rcp w.w, u.w;
   __asm vec4_multiply __retVal, v, w;
}




//// Basic vec2/float operators

vec2 __operator + (const float a, const vec2 u)
{
   __asm vec4_add __retVal.xy, a.xx, u.xy;
}

vec2 __operator + (const vec2 v, const float b)
{
   __asm vec4_add __retVal.xy, v.xy, b.xx;
}

vec2 __operator - (const float a, const vec2 u)
{
   __asm vec4_subtract __retVal.xy, a.xx, u.xy;
}

vec2 __operator - (const vec2 v, const float b)
{
   __asm vec4_subtract __retVal.xy, v.xy, b.xx;
}

vec2 __operator * (const float a, const vec2 u)
{
   __asm vec4_multiply __retVal.xy, a.xx, u.xy;
}

vec2 __operator * (const vec2 v, const float b)
{
   __asm vec4_multiply __retVal.xy, v.xy, b.xx;
}

vec2 __operator / (const float a, const vec2 u)
{
   vec2 invU;
   __asm float_rcp invU.x, u.x;
   __asm float_rcp invU.y, u.y;
   __asm vec4_multiply __retVal.xy, a.xx, invU.xy;
}

vec2 __operator / (const vec2 v, const float b)
{
   float invB;
   __asm float_rcp invB, b;
   __asm vec4_multiply __retVal.xy, v.xy, invB.xx;
}


//// Basic vec3/float operators

vec3 __operator + (const float a, const vec3 u)
{
   __asm vec4_add __retVal.xyz, a.xxx, u.xyz;
}

vec3 __operator + (const vec3 v, const float b)
{
   __asm vec4_add __retVal.xyz, v.xyz, b.xxx;
}

vec3 __operator - (const float a, const vec3 u)
{
   __asm vec4_subtract __retVal.xyz, a.xxx, u.xyz;
}

vec3 __operator - (const vec3 v, const float b)
{
   __asm vec4_subtract __retVal.xyz, v.xyz, b.xxx;
}

vec3 __operator * (const float a, const vec3 u)
{
   __asm vec4_multiply __retVal.xyz, a.xxx, u.xyz;
}

vec3 __operator * (const vec3 v, const float b)
{
   __asm vec4_multiply __retVal.xyz, v.xyz, b.xxx;
}

vec3 __operator / (const float a, const vec3 u)
{
   vec3 invU;
   __asm float_rcp invU.x, u.x;
   __asm float_rcp invU.y, u.y;
   __asm float_rcp invU.z, u.z;
   __asm vec4_multiply __retVal.xyz, a.xxx, invU.xyz;
}

vec3 __operator / (const vec3 v, const float b)
{
   float invB;
   __asm float_rcp invB, b;
   __asm vec4_multiply __retVal.xyz, v.xyz, invB.xxx;
}


//// Basic vec4/float operators

vec4 __operator + (const float a, const vec4 u)
{
   __asm vec4_add __retVal, a.xxxx, u;
}

vec4 __operator + (const vec4 v, const float b)
{
   __asm vec4_add __retVal, v, b.xxxx;
}

vec4 __operator - (const float a, const vec4 u)
{
   __asm vec4_subtract __retVal, a.xxxx, u;
}

vec4 __operator - (const vec4 v, const float b)
{
   __asm vec4_subtract __retVal, v, b.xxxx;
}

vec4 __operator * (const float a, const vec4 u)
{
   __asm vec4_multiply __retVal, a.xxxx, u;
}

vec4 __operator * (const vec4 v, const float b)
{
   __asm vec4_multiply __retVal, v, b.xxxx;
}

vec4 __operator / (const float a, const vec4 u)
{
   vec4 invU;
   __asm float_rcp invU.x, u.x;
   __asm float_rcp invU.y, u.y;
   __asm float_rcp invU.z, u.z;
   __asm float_rcp invU.w, u.w;
   __asm vec4_multiply __retVal, a.xxxx, invU;
}

vec4 __operator / (const vec4 v, const float b)
{
   float invB;
   __asm float_rcp invB, b;
   __asm vec4_multiply __retVal, v, invB.xxxx;
}



//// Basic ivec2/int operators

ivec2 __operator + (const int a, const ivec2 u)
{
   __retVal = ivec2(a) + u;
}

ivec2 __operator + (const ivec2 v, const int b)
{
   __retVal = v + ivec2(b);
}

ivec2 __operator - (const int a, const ivec2 u)
{
   __retVal = ivec2(a) - u;
}

ivec2 __operator - (const ivec2 v, const int b)
{
   __retVal = v - ivec2(b);
}

ivec2 __operator * (const int a, const ivec2 u)
{
   __retVal = ivec2(a) * u;
}

ivec2 __operator * (const ivec2 v, const int b)
{
   __retVal = v * ivec2(b);
}

ivec2 __operator / (const int a, const ivec2 u)
{
   __retVal = ivec2(a) / u;
}

ivec2 __operator / (const ivec2 v, const int b)
{
   __retVal = v / ivec2(b);
}


//// Basic ivec3/int operators

ivec3 __operator + (const int a, const ivec3 u)
{
   __retVal = ivec3(a) + u;
}

ivec3 __operator + (const ivec3 v, const int b)
{
   __retVal = v + ivec3(b);
}

ivec3 __operator - (const int a, const ivec3 u)
{
   __retVal = ivec3(a) - u;
}

ivec3 __operator - (const ivec3 v, const int b)
{
   __retVal = v - ivec3(b);
}

ivec3 __operator * (const int a, const ivec3 u)
{
   __retVal = ivec3(a) * u;
}

ivec3 __operator * (const ivec3 v, const int b)
{
   __retVal = v * ivec3(b);
}

ivec3 __operator / (const int a, const ivec3 u)
{
   __retVal = ivec3(a) / u;
}

ivec3 __operator / (const ivec3 v, const int b)
{
   __retVal = v / ivec3(b);
}


//// Basic ivec4/int operators

ivec4 __operator + (const int a, const ivec4 u)
{
   __retVal = ivec4(a) + u;
}

ivec4 __operator + (const ivec4 v, const int b)
{
   __retVal = v + ivec4(b);
}

ivec4 __operator - (const int a, const ivec4 u)
{
   __retVal = ivec4(a) - u;
}

ivec4 __operator - (const ivec4 v, const int b)
{
   __retVal = v - ivec4(b);
}

ivec4 __operator * (const int a, const ivec4 u)
{
   __retVal = ivec4(a) * u;
}

ivec4 __operator * (const ivec4 v, const int b)
{
   __retVal = v * ivec4(b);
}

ivec4 __operator / (const int a, const ivec4 u)
{
   __retVal = ivec4(a) / u;
}

ivec4 __operator / (const ivec4 v, const int b)
{
   __retVal = v / ivec4(b);
}




//// Unary negation operator

int __operator - (const int a)
{
   __asm vec4_negate __retVal.x, a;
}

ivec2 __operator - (const ivec2 v)
{
   __asm vec4_negate __retVal, v;
}

ivec3 __operator - (const ivec3 v)
{
   __asm vec4_negate __retVal, v;
}

ivec4 __operator - (const ivec4 v)
{
   __asm vec4_negate __retVal, v;
}

float __operator - (const float a)
{
   __asm vec4_negate __retVal.x, a;
}

vec2 __operator - (const vec2 v)
{
   __asm vec4_negate __retVal.xy, v.xy;
}

vec3 __operator - (const vec3 v)
{
   __asm vec4_negate __retVal.xyz, v.xyz;
}

vec4 __operator - (const vec4 v)
{
   __asm vec4_negate __retVal, v;
}

mat2 __operator - (const mat2 m)
{
   __retVal[0] = -m[0];
   __retVal[1] = -m[1];
}

mat3 __operator - (const mat3 m)
{
   __retVal[0] = -m[0];
   __retVal[1] = -m[1];
   __retVal[2] = -m[2];
}

mat4 __operator - (const mat4 m)
{
   __retVal[0] = -m[0];
   __retVal[1] = -m[1];
   __retVal[2] = -m[2];
   __retVal[3] = -m[3];
}



//// dot product

float dot(const float a, const float b)
{
   __retVal = a * b;
}

float dot(const vec2 a, const vec2 b)
{
   __retVal = a.x * b.x + a.y * b.y;
}

float dot(const vec3 a, const vec3 b)
{
    __asm vec3_dot __retVal, a, b;
}

float dot(const vec4 a, const vec4 b)
{
    __asm vec4_dot __retVal, a, b;
}



//// int assignment operators

void __operator += (inout int a, const int b)
{
   __asm vec4_add a, a, b;
}

void __operator -= (inout int a, const int b)
{
   __asm vec4_subtract a, a, b;
}

void __operator *= (inout int a, const int b)
{
   __asm vec4_multiply a, a, b;
}

void __operator /= (inout int a, const int b)
{
   float invB;
   __asm float_rcp invB, b;
   __asm vec4_multiply a, a, invB;
}


//// ivec2 assignment operators

void __operator += (inout ivec2 v, const ivec2 u)
{
   __asm vec4_add v, v, u;
}

void __operator -= (inout ivec2 v, const ivec2 u)
{
   __asm vec4_subtract v, v, u;
}

void __operator *= (inout ivec2 v, const ivec2 u)
{
   __asm vec4_multiply v, v, u;
}

void __operator /= (inout ivec2 v, const ivec2 u)
{
   ivec2 inv, z;
   __asm float_rcp inv.x, u.x;
   __asm float_rcp inv.y, u.y;
   __asm vec4_multiply z, v, inv;
   __asm float_to_int __retVal, z;
}


//// ivec3 assignment operators

void __operator += (inout ivec3 v, const ivec3 u)
{
   __asm vec4_add v, v, u;
}

void __operator -= (inout ivec3 v, const ivec3 u)
{
   __asm vec4_subtract v, v, u;
}

void __operator *= (inout ivec3 v, const ivec3 u)
{
   __asm vec4_multiply v, v, u;
}

void __operator /= (inout ivec3 v, const ivec3 u)
{
   ivec3 inv, z;
   __asm float_rcp inv.x, u.x;
   __asm float_rcp inv.y, u.y;
   __asm vec4_multiply z, v, inv;
   __asm float_to_int __retVal, z;
}


//// ivec4 assignment operators

void __operator += (inout ivec4 v, const ivec4 u)
{
   __asm vec4_add v, v, u;
}

void __operator -= (inout ivec4 v, const ivec4 u)
{
   __asm vec4_subtract v, v, u;
}

void __operator *= (inout ivec4 v, const ivec4 u)
{
   __asm vec4_multiply v, v, u;
}

void __operator /= (inout ivec4 v, const ivec4 u)
{
   ivec4 inv, z;
   __asm float_rcp inv.x, u.x;
   __asm float_rcp inv.y, u.y;
   __asm vec4_multiply z, v, inv;
   __asm float_to_int __retVal, z;
}


//// float assignment operators

void __operator += (inout float a, const float b)
{
    __asm vec4_add a.x, a.x, b;
}

void __operator -= (inout float a, const float b)
{
    __asm vec4_subtract a.x, a, b;
}

void __operator *= (inout float a, const float b)
{
    __asm vec4_multiply a.x, a, b;
}

void __operator /= (inout float a, const float b)
{
   float w; // = 1 / b
   __asm float_rcp w.x, b;
   __asm vec4_multiply a.x, a, w;
}


//// vec2 assignment operators

void __operator += (inout vec2 v, const vec2 u)
{
   __asm vec4_add v.xy, v.xy, u.xy;
}

void __operator -= (inout vec2 v, const vec2 u)
{
   __asm vec4_subtract v.xy, v.xy, u.xy;
}

void __operator *= (inout vec2 v, const vec2 u)
{
   __asm vec4_multiply v.xy, v.xy, u.xy;
}

void __operator /= (inout vec2 v, const vec2 u)
{
   vec2 w;
   __asm float_rcp w.x, u.x;
   __asm float_rcp w.y, u.y;
   __asm vec4_multiply v.xy, v.xy, w.xy;
}


//// vec3 assignment operators

void __operator += (inout vec3 v, const vec3 u)
{
   __asm vec4_add v.xyz, v, u;
}

void __operator -= (inout vec3 v, const vec3 u)
{
   __asm vec4_subtract v.xyz, v, u;
}

void __operator *= (inout vec3 v, const vec3 u)
{
   __asm vec4_multiply v.xyz, v, u;
}

void __operator /= (inout vec3 v, const vec3 u)
{
   vec3 w;
   __asm float_rcp w.x, u.x;
   __asm float_rcp w.y, u.y;
   __asm float_rcp w.z, u.z;
   __asm vec4_multiply v.xyz, v.xyz, w.xyz;
}


//// vec4 assignment operators

void __operator += (inout vec4 v, const vec4 u)
{
   __asm vec4_add v, v, u;
}

void __operator -= (inout vec4 v, const vec4 u)
{
   __asm vec4_subtract v, v, u;
}

void __operator *= (inout vec4 v, const vec4 u)
{
   __asm vec4_multiply v, v, u;
}

void __operator /= (inout vec4 v, const vec4 u)
{
   vec4 w;
   __asm float_rcp w.x, u.x;
   __asm float_rcp w.y, u.y;
   __asm float_rcp w.z, u.z;
   __asm float_rcp w.w, u.w;
   __asm vec4_multiply v, v, w;
}



//// ivec2/int assignment operators

void __operator += (inout ivec2 v, const int a)
{
   __asm vec4_add v.xy, v.xy, a.xx;
}

void __operator -= (inout ivec2 v, const int a)
{
   __asm vec4_subtract v.xy, v.xy, a.xx;
}

void __operator *= (inout ivec2 v, const int a)
{
   __asm vec4_multiply v.xy, v.xy, a.xx;
   v.x *= a;
   v.y *= a;
}

void __operator /= (inout ivec2 v, const int a)
{
// XXX rcp
    v.x /= a;
    v.y /= a;
}


//// ivec3/int assignment operators

void __operator += (inout ivec3 v, const int a)
{
   __asm vec4_add v.xyz, v.xyz, a.xxx;
}

void __operator -= (inout ivec3 v, const int a)
{
   __asm vec4_subtract v.xyz, v.xyz, a.xxx;
}

void __operator *= (inout ivec3 v, const int a)
{
   __asm vec4_multiply v.xyz, v.xyz, a.xxx;
}

void __operator /= (inout ivec3 v, const int a)
{
   // XXX rcp
    v.x /= a;
    v.y /= a;
    v.z /= a;
}


//// ivec4/int assignment operators

void __operator += (inout ivec4 v, const int a)
{
   __asm vec4_add v, v, a.xxxx;
}

void __operator -= (inout ivec4 v, const int a)
{
   __asm vec4_subtract v, v, a.xxxx;
}

void __operator *= (inout ivec4 v, const int a)
{
   __asm vec4_multiply v, v, a.xxxx;
}

void __operator /= (inout ivec4 v, const int a)
{
    v.x /= a;
    v.y /= a;
    v.z /= a;
    v.w /= a;
}



//// vec2/float assignment operators

void __operator += (inout vec2 v, const float a)
{
   __asm vec4_add v.xy, v, a.xx;
}

void __operator -= (inout vec2 v, const float a)
{
   __asm vec4_subtract v.xy, v, a.xx;
}

void __operator *= (inout vec2 v, const float a)
{
   __asm vec4_multiply v.xy, v, a.xx;
}

void __operator /= (inout vec2 v, const float a)
{
   float invA;
   __asm float_rcp invA, a;
   __asm vec4_multiply v.xy, v.xy, a.xx;
}


//// vec3/float assignment operators

void __operator += (inout vec3 v, const float a)
{
   __asm vec4_add v.xyz, v, a.xxx;
}

void __operator -= (inout vec3 v, const float a)
{
   __asm vec4_subtract v.xyz, v, a.xxx;
}

void __operator *= (inout vec3 v, const float a)
{
   __asm vec4_multiply v.xyz, v, a.xxx;
}

void __operator /= (inout vec3 v, const float a)
{
   float invA;
   __asm float_rcp invA, a;
   __asm vec4_multiply v.xyz, v.xyz, a.xxx;
}


//// vec4/float assignment operators

void __operator += (inout vec4 v, const float a)
{
   __asm vec4_add v, v, a.xxxx;
}

void __operator -= (inout vec4 v, const float a)
{
   __asm vec4_subtract v, v, a.xxxx;
}

void __operator *= (inout vec4 v, const float a)
{
   __asm vec4_multiply v, v, a.xxxx;
}

void __operator /= (inout vec4 v, const float a)
{
   float invA;
   __asm float_rcp invA, a;
   __asm vec4_multiply v, v, a.xxxx;
}





//// Basic mat2 operations

mat2 __operator + (const mat2 m, const mat2 n)
{
   __retVal[0] = m[0] + n[0];
   __retVal[1] = m[1] + n[1];
}

mat2 __operator - (const mat2 m, const mat2 n)
{
   __retVal[0] = m[0] - n[0];
   __retVal[1] = m[1] - n[1];
}

mat2 __operator * (const mat2 m, const mat2 n)
{
   vec2 mRow0, mRow1;
   mRow0.x = m[0].x;
   mRow0.y = m[1].x;
   mRow1.x = m[0].y;
   mRow1.y = m[1].y;
   __retVal[0].x = dot(mRow0, n[0]);
   __retVal[1].x = dot(mRow0, n[1]);
   __retVal[0].y = dot(mRow1, n[0]);
   __retVal[1].y = dot(mRow1, n[1]);
}

mat2 __operator / (const mat2 m, const mat2 n)
{
   __retVal[0] = m[0] / n[0];
   __retVal[1] = m[1] / n[1];
}


//// Basic mat3 operations

mat3 __operator + (const mat3 m, const mat3 n)
{
   __retVal[0] = m[0] + n[0];
   __retVal[1] = m[1] + n[1];
   __retVal[2] = m[2] + n[2];
}

mat3 __operator - (const mat3 m, const mat3 n)
{
   __retVal[0] = m[0] - n[0];
   __retVal[1] = m[1] - n[1];
   __retVal[2] = m[2] - n[2];
}

mat3 __operator * (const mat3 m, const mat3 n)
{
   // sub-blocks to reduce register usage
   {
      vec3 mRow0;
      mRow0.x = m[0].x;
      mRow0.y = m[1].x;
      mRow0.z = m[2].x;
      __retVal[0].x = dot(mRow0, n[0]);
      __retVal[1].x = dot(mRow0, n[1]);
      __retVal[2].x = dot(mRow0, n[2]);
   }
   {
      vec3 mRow1;
      mRow1.x = m[0].y;
      mRow1.y = m[1].y;
      mRow1.z = m[2].y;
      __retVal[0].y = dot(mRow1, n[0]);
      __retVal[1].y = dot(mRow1, n[1]);
      __retVal[2].y = dot(mRow1, n[2]);
   }
   {
      vec3 mRow2;
      mRow2.x = m[0].z;
      mRow2.y = m[1].z;
      mRow2.z = m[2].z;
      __retVal[0].z = dot(mRow2, n[0]);
      __retVal[1].z = dot(mRow2, n[1]);
      __retVal[2].z = dot(mRow2, n[2]);
   }
}

mat3 __operator / (const mat3 m, const mat3 n)
{
    __retVal[0] = m[0] / n[0];
    __retVal[1] = m[1] / n[1];
    __retVal[2] = m[2] / n[2];
}


//// Basic mat4 operations

mat4 __operator + (const mat4 m, const mat4 n)
{
   __retVal[0] = m[0] + n[0];
   __retVal[1] = m[1] + n[1];
   __retVal[2] = m[2] + n[2];
   __retVal[3] = m[3] + n[3];
}

mat4 __operator - (const mat4 m, const mat4 n)
{
   __retVal[0] = m[0] - n[0];
   __retVal[1] = m[1] - n[1];
   __retVal[2] = m[2] - n[2];
   __retVal[3] = m[3] - n[3];
}

mat4 __operator * (const mat4 m, const mat4 n)
{
   // sub-blocks to reduce temporary usage
   {
      vec4 mRow0;
      mRow0.x = m[0].x;
      mRow0.y = m[1].x;
      mRow0.z = m[2].x;
      mRow0.w = m[3].x;
      __retVal[0].x = dot(mRow0, n[0]);
      __retVal[1].x = dot(mRow0, n[1]);
      __retVal[2].x = dot(mRow0, n[2]);
      __retVal[3].x = dot(mRow0, n[3]);
   }
   {
      vec4 mRow1;
      mRow1.x = m[0].y;
      mRow1.y = m[1].y;
      mRow1.z = m[2].y;
      mRow1.w = m[3].y;
      __retVal[0].y = dot(mRow1, n[0]);
      __retVal[1].y = dot(mRow1, n[1]);
      __retVal[2].y = dot(mRow1, n[2]);
      __retVal[3].y = dot(mRow1, n[3]);
   }
   {
      vec4 mRow2;
      mRow2.x = m[0].z;
      mRow2.y = m[1].z;
      mRow2.z = m[2].z;
      mRow2.w = m[3].z;
      __retVal[0].z = dot(mRow2, n[0]);
      __retVal[1].z = dot(mRow2, n[1]);
      __retVal[2].z = dot(mRow2, n[2]);
      __retVal[3].z = dot(mRow2, n[3]);
   }
   {
      vec4 mRow3;
      mRow3.x = m[0].w;
      mRow3.y = m[1].w;
      mRow3.z = m[2].w;
      mRow3.w = m[3].w;
      __retVal[0].w = dot(mRow3, n[0]);
      __retVal[1].w = dot(mRow3, n[1]);
      __retVal[2].w = dot(mRow3, n[2]);
      __retVal[3].w = dot(mRow3, n[3]);
   }
}

mat4 __operator / (const mat4 m, const mat4 n)
{
    __retVal[0] = m[0] / n[0];
    __retVal[1] = m[1] / n[1];
    __retVal[2] = m[2] / n[2];
    __retVal[3] = m[3] / n[3];
}


//// mat2/float operations

mat2 __operator + (const float a, const mat2 n)
{
   __retVal[0] = a + n[0];
   __retVal[1] = a + n[1];
}

mat2 __operator + (const mat2 m, const float b)
{
   __retVal[0] = m[0] + b;
   __retVal[1] = m[1] + b;
}

mat2 __operator - (const float a, const mat2 n)
{
   __retVal[0] = a - n[0];
   __retVal[1] = a - n[1];
}

mat2 __operator - (const mat2 m, const float b)
{
   __retVal[0] = m[0] - b;
   __retVal[1] = m[1] - b;
}

mat2 __operator * (const float a, const mat2 n)
{
   __retVal[0] = a * n[0];
   __retVal[1] = a * n[1];
}

mat2 __operator * (const mat2 m, const float b)
{
   __retVal[0] = m[0] * b;
   __retVal[1] = m[1] * b;
}

mat2 __operator / (const float a, const mat2 n)
{
   __retVal[0] = a / n[0];
   __retVal[1] = a / n[1];
}

mat2 __operator / (const mat2 m, const float b)
{
   __retVal[0] = m[0] / b;
   __retVal[1] = m[1] / b;
}


//// mat3/float operations

mat3 __operator + (const float a, const mat3 n)
{
   __retVal[0] = a + n[0];
   __retVal[1] = a + n[1];
   __retVal[2] = a + n[2];
}

mat3 __operator + (const mat3 m, const float b)
{
   __retVal[0] = m[0] + b;
   __retVal[1] = m[1] + b;
   __retVal[2] = m[2] + b;
}

mat3 __operator - (const float a, const mat3 n)
{
   __retVal[0] = a - n[0];
   __retVal[1] = a - n[1];
   __retVal[2] = a - n[2];
}

mat3 __operator - (const mat3 m, const float b)
{
   __retVal[0] = m[0] - b;
   __retVal[1] = m[1] - b;
   __retVal[2] = m[2] - b;
}

mat3 __operator * (const float a, const mat3 n)
{
   __retVal[0] = a * n[0];
   __retVal[1] = a * n[1];
   __retVal[2] = a * n[2];
}

mat3 __operator * (const mat3 m, const float b)
{
   __retVal[0] = m[0] * b;
   __retVal[1] = m[1] * b;
   __retVal[2] = m[2] * b;
}

mat3 __operator / (const float a, const mat3 n)
{
   __retVal[0] = a / n[0];
   __retVal[1] = a / n[1];
   __retVal[2] = a / n[2];
}

mat3 __operator / (const mat3 m, const float b)
{
   __retVal[0] = m[0] / b;
   __retVal[1] = m[1] / b;
   __retVal[2] = m[2] / b;
}


//// mat4/float operations

mat4 __operator + (const float a, const mat4 n)
{
   __retVal[0] = a + n[0];
   __retVal[1] = a + n[1];
   __retVal[2] = a + n[2];
   __retVal[3] = a + n[3];
}

mat4 __operator + (const mat4 m, const float b)
{
   __retVal[0] = m[0] + b;
   __retVal[1] = m[1] + b;
   __retVal[2] = m[2] + b;
   __retVal[3] = m[3] + b;
}

mat4 __operator - (const float a, const mat4 n)
{
   __retVal[0] = a - n[0];
   __retVal[1] = a - n[1];
   __retVal[2] = a - n[2];
   __retVal[3] = a - n[3];
}

mat4 __operator - (const mat4 m, const float b)
{
   __retVal[0] = m[0] - b;
   __retVal[1] = m[1] - b;
   __retVal[2] = m[2] - b;
   __retVal[3] = m[3] - b;
}

mat4 __operator * (const float a, const mat4 n)
{
   __retVal[0] = a * n[0];
   __retVal[1] = a * n[1];
   __retVal[2] = a * n[2];
   __retVal[3] = a * n[3];
}

mat4 __operator * (const mat4 m, const float b)
{
   __retVal[0] = m[0] * b;
   __retVal[1] = m[1] * b;
   __retVal[2] = m[2] * b;
   __retVal[3] = m[3] * b;
}

mat4 __operator / (const float a, const mat4 n)
{
   __retVal[0] = a / n[0];
   __retVal[1] = a / n[1];
   __retVal[2] = a / n[2];
   __retVal[3] = a / n[3];
}

mat4 __operator / (const mat4 m, const float b)
{
   __retVal[0] = m[0] / b;
   __retVal[1] = m[1] / b;
   __retVal[2] = m[2] / b;
   __retVal[3] = m[3] / b;
}



//// matrix / vector products

vec2 __operator * (const mat2 m, const vec2 v)
{
   vec2 r0, r1;
   r0.x = m[0].x;
   r0.y = m[1].x;
   r1.x = m[0].y;
   r1.y = m[1].y;
   __retVal.x = dot(r0, v);
   __retVal.y = dot(r1, v);
}

vec2 __operator * (const vec2 v, const mat2 m)
{
   __retVal.x = dot(v, m[0]);
   __retVal.y = dot(v, m[1]);
}

vec3 __operator * (const mat3 m, const vec3 v)
{
   {
      vec3 r0;
      r0.x = m[0].x;
      r0.y = m[1].x;
      r0.z = m[2].x;
      __asm vec3_dot __retVal.x, r0, v;
   }
   {
      vec3 r1;
      r1.x = m[0].y;
      r1.y = m[1].y;
      r1.z = m[2].y;
      __asm vec3_dot __retVal.y, r1, v;
   }
   {
      vec3 r2;
      r2.x = m[0].z;
      r2.y = m[1].z;
      r2.z = m[2].z;
      __asm vec3_dot __retVal.z, r2, v;
   }
}

vec3 __operator * (const vec3 v, const mat3 m)
{
   __retVal.x = dot(v, m[0]);
   __retVal.y = dot(v, m[1]);
   __retVal.z = dot(v, m[2]);
}

vec4 __operator * (const mat4 m, const vec4 v)
{
   // extract rows, then do dot product
   {
      vec4 r0;
      r0.x = m[0].x;
      r0.y = m[1].x;
      r0.z = m[2].x;
      r0.w = m[3].x;
      __asm vec4_dot __retVal.x, r0, v;
   }
   {
      vec4 r1;
      r1.x = m[0].y;
      r1.y = m[1].y;
      r1.z = m[2].y;
      r1.w = m[3].y;
      __asm vec4_dot __retVal.y, r1, v;
   }
   {
      vec4 r2;
      r2.x = m[0].z;
      r2.y = m[1].z;
      r2.z = m[2].z;
      r2.w = m[3].z;
      __asm vec4_dot __retVal.z, r2, v;
   }
   {
      vec4 r3;
      r3.x = m[0].w;
      r3.y = m[1].w;
      r3.z = m[2].w;
      r3.w = m[3].w;
      __asm vec4_dot __retVal.w, r3, v;
   }
}

vec4 __operator * (const vec4 v, const mat4 m)
{
   //mm
   __retVal.x = dot(v, m[0]);
   __retVal.y = dot(v, m[1]);
   __retVal.z = dot(v, m[2]);
   __retVal.w = dot(v, m[3]);
}



//// mat2 assignment operators

void __operator += (inout mat2 m, const mat2 n)
{
    m[0] += n[0];
    m[1] += n[1];
}

void __operator -= (inout mat2 m, const mat2 n)
{
    m[0] -= n[0];
    m[1] -= n[1];
}

void __operator *= (inout mat2 m, const mat2 n)
{
    m = m * n;
}

void __operator /= (inout mat2 m, const mat2 n)
{
    m[0] /= n[0];
    m[1] /= n[1];
}


//// mat3 assignment operators

void __operator += (inout mat3 m, const mat3 n)
{
    m[0] += n[0];
    m[1] += n[1];
    m[2] += n[2];
}

void __operator -= (inout mat3 m, const mat3 n)
{
    m[0] -= n[0];
    m[1] -= n[1];
    m[2] -= n[2];
}

void __operator *= (inout mat3 m, const mat3 n)
{
    m = m * n;
}

void __operator /= (inout mat3 m, const mat3 n)
{
    m[0] /= n[0];
    m[1] /= n[1];
    m[2] /= n[2];
}


// mat4 assignment operators

void __operator += (inout mat4 m, const mat4 n)
{
    m[0] += n[0];
    m[1] += n[1];
    m[2] += n[2];
    m[3] += n[3];
}

void __operator -= (inout mat4 m, const mat4 n) {
    m[0] -= n[0];
    m[1] -= n[1];
    m[2] -= n[2];
    m[3] -= n[3];
}

void __operator *= (inout mat4 m, const mat4 n)
{
    m = m * n;
}

void __operator /= (inout mat4 m, const mat4 n)
{
    m[0] /= n[0];
    m[1] /= n[1];
    m[2] /= n[2];
    m[3] /= n[3];
}


//// mat2/float assignment operators

void __operator += (inout mat2 m, const float a) {
    m[0] += a;
    m[1] += a;
}

void __operator -= (inout mat2 m, const float a) {
    m[0] -= a;
    m[1] -= a;
}

void __operator *= (inout mat2 m, const float a) {
    m[0] *= a;
    m[1] *= a;
}

void __operator /= (inout mat2 m, const float a) {
    m[0] /= a;
    m[1] /= a;
}


//// mat3/float assignment operators

void __operator += (inout mat3 m, const float a) {
    m[0] += a;
    m[1] += a;
    m[2] += a;
}

void __operator -= (inout mat3 m, const float a) {
    m[0] -= a;
    m[1] -= a;
    m[2] -= a;
}

void __operator *= (inout mat3 m, const float a) {
    m[0] *= a;
    m[1] *= a;
    m[2] *= a;
}

void __operator /= (inout mat3 m, const float a) {
    m[0] /= a;
    m[1] /= a;
    m[2] /= a;
}


//// mat4/float assignment operators

void __operator += (inout mat4 m, const float a) {
    m[0] += a;
    m[1] += a;
    m[2] += a;
    m[3] += a;
}

void __operator -= (inout mat4 m, const float a) {
    m[0] -= a;
    m[1] -= a;
    m[2] -= a;
    m[3] -= a;
}

void __operator *= (inout mat4 m, const float a) {
    m[0] *= a;
    m[1] *= a;
    m[2] *= a;
    m[3] *= a;
}

void __operator /= (inout mat4 m, const float a) {
    m[0] /= a;
    m[1] /= a;
    m[2] /= a;
    m[3] /= a;
}



//// vec/mat assignment operators

void __operator *= (inout vec2 v, const mat2 m)
{
    v = v * m;
}

void __operator *= (inout vec3 v, const mat3 m)
{
    v = v * m;
}

void __operator *= (inout vec4 v, const mat4 m)
{
    v = v * m;
}



//// pre-decrement operators

int __operator --(inout int a)
{
    a = a - 1;
   __retVal = a;
}

ivec2 __operator --(inout ivec2 v)
{
   v = v - ivec2(1);
   __retVal = v;
}

ivec3 __operator --(inout ivec3 v)
{
   v = v - ivec3(1);
   __retVal = v;
}

ivec4 __operator --(inout ivec4 v)
{
   v = v - ivec4(1);
   __retVal = v;
}


float __operator --(inout float a)
{
   a = a - 1.0;
   __retVal = a;
}

vec2 __operator --(inout vec2 v)
{
   v = v - vec2(1.0);
   __retVal = v;
}

vec3 __operator --(inout vec3 v)
{
   v = v - vec3(1.0);
   __retVal = v;
}

vec4 __operator --(inout vec4 v)
{
   v = v - vec4(1.0);
   __retVal = v;
}


mat2 __operator --(inout mat2 m)
{
   m[0] = m[0] - vec2(1.0);
   m[1] = m[1] - vec2(1.0);
   __retVal = m;
}

mat3 __operator --(inout mat3 m)
{
   m[0] = m[0] - vec3(1.0);
   m[1] = m[1] - vec3(1.0);
   m[2] = m[2] - vec3(1.0);
   __retVal = m;
}

mat4 __operator --(inout mat4 m)
{
   m[0] = m[0] - vec4(1.0);
   m[1] = m[1] - vec4(1.0);
   m[2] = m[2] - vec4(1.0);
   m[3] = m[3] - vec4(1.0);
   __retVal = m;
}


//// pre-increment operators

int __operator ++(inout int a)
{
    a = a + 1;
    __retVal = a;
}

ivec2 __operator ++(inout ivec2 v)
{
   v = v + ivec2(1);
   __retVal = v;
}

ivec3 __operator ++(inout ivec3 v)
{
   v = v + ivec3(1);
   __retVal = v;
}

ivec4 __operator ++(inout ivec4 v)
{
   v = v + ivec4(1);
   __retVal = v;
}


float __operator ++(inout float a)
{
    a = a + 1.0;
    __retVal = a;
}

vec2 __operator ++(inout vec2 v)
{
   v = v + vec2(1.0);
   __retVal = v;
}

vec3 __operator ++(inout vec3 v)
{
   v = v + vec3(1.0);
   __retVal = v;
}

vec4 __operator ++(inout vec4 v)
{
   v = v + vec4(1.0);
   __retVal = v;
}


mat2 __operator ++(inout mat2 m)
{
   m[0] = m[0] + vec2(1.0);
   m[1] = m[1] + vec2(1.0);
   __retVal = m;
}

mat3 __operator ++(inout mat3 m)
{
   m[0] = m[0] + vec3(1.0);
   m[1] = m[1] + vec3(1.0);
   m[2] = m[2] + vec3(1.0);
   __retVal = m;
}

mat4 __operator ++(inout mat4 m)
{
   m[0] = m[0] + vec4(1.0);
   m[1] = m[1] + vec4(1.0);
   m[2] = m[2] + vec4(1.0);
   m[3] = m[3] + vec4(1.0);
   __retVal = m;
}



//// post-decrement

int __postDecr(inout int a)
{
   __retVal = a;
   a = a - 1;
}

ivec2 __postDecr(inout ivec2 v)
{
   __retVal = v;
   v = v - ivec2(1);
}

ivec3 __postDecr(inout ivec3 v)
{
   __retVal = v;
   v = v - ivec3(1);
}

ivec4 __postDecr(inout ivec4 v)
{
   __retVal = v;
   v = v - ivec4(1);
}


float __postDecr(inout float a)
{
   __retVal = a;
   a = a - 1.0;
}

vec2 __postDecr(inout vec2 v)
{
   __retVal = v;
   v = v - vec2(1.0);
}

vec3 __postDecr(inout vec3 v)
{
   __retVal = v;
   v = v - vec3(1.0);
}

vec4 __postDecr(inout vec4 v)
{
   __retVal = v;
   v = v - vec4(1.0);
}


mat2 __postDecr(inout mat2 m)
{
   __retVal = m;
   m[0] = m[0] - vec2(1.0);
   m[1] = m[1] - vec2(1.0);
}

mat3 __postDecr(inout mat3 m)
{
   __retVal = m;
   m[0] = m[0] - vec3(1.0);
   m[1] = m[1] - vec3(1.0);
   m[2] = m[2] - vec3(1.0);
}

mat4 __postDecr(inout mat4 m)
{
   __retVal = m;
   m[0] = m[0] - vec4(1.0);
   m[1] = m[1] - vec4(1.0);
   m[2] = m[2] - vec4(1.0);
   m[3] = m[3] - vec4(1.0);
}


//// post-increment

float __postIncr(inout float a)
{
   __retVal = a;
   a = a + 1;
}

vec2 __postIncr(inout vec2 v)
{
   __retVal = v;
   v = v + vec2(1.0);
}

vec3 __postIncr(inout vec3 v)
{
   __retVal = v;
   v = v + vec3(1.0);
}

vec4 __postIncr(inout vec4 v)
{
   __retVal = v;
   v = v + vec4(1.0);
}


int __postIncr(inout int a)
{
   __retVal = a;
   a = a + 1;
}

ivec2 __postIncr(inout ivec2 v)
{
   __retVal = v;
   v = v + ivec2(1);
}

ivec3 __postIncr(inout ivec3 v)
{
   __retVal = v;
   v = v + ivec3(1);
}

ivec4 __postIncr(inout ivec4 v)
{
   __retVal = v;
   v = v + ivec3(1);
}


mat2 __postIncr(inout mat2 m)
{
   mat2 n = m;
   m[0] = m[0] + vec2(1.0);
   m[1] = m[1] + vec2(1.0);
   return n;
}

mat3 __postIncr(inout mat3 m)
{
   mat3 n = m;
   m[0] = m[0] + vec3(1.0);
   m[1] = m[1] + vec3(1.0);
   m[2] = m[2] + vec3(1.0);
   return n;
}

mat4 __postIncr(inout mat4 m)
{
   mat4 n = m;
   m[0] = m[0] + vec4(1.0);
   m[1] = m[1] + vec4(1.0);
   m[2] = m[2] + vec4(1.0);
   m[3] = m[3] + vec4(1.0);
   return n;
}



//// inequality operators


// XXX are the inequality operators for floats/ints really needed????
bool __operator < (const float a, const float b)
{
   __asm vec4_sgt __retVal.x, b, a;
}


bool __operator < (const int a, const int b) {
    return float (a) < float (b);
}

bool __operator > (const float a, const float b) {
    bool c;
    __asm float_less c, b, a;
    return c;
}

bool __operator > (const int a, const int b) {
    return float (a) > float (b);
}

bool __operator >= (const float a, const float b) {
    bool g, e;
    __asm float_less  g, b, a;
    __asm float_equal e, a, b;
    return g || e;
}

bool __operator >= (const int a, const int b) {
    return float (a) >= float (b);
}

bool __operator <= (const float a, const float b) {
    bool g, e;
    __asm float_less  g, a, b;
    __asm float_equal e, a, b;
    return g || e;
}

bool __operator <= (const int a, const int b) {
    return float (a) <= float (b);
}



//
// MESA-specific extension functions.
//

void printMESA (const float f) {
    __asm float_print f;
}

void printMESA (const int i) {
    __asm int_print i;
}

void printMESA (const bool b) {
    __asm bool_print b;
}

void printMESA (const vec2 v) {
    printMESA (v.x);
    printMESA (v.y);
}

void printMESA (const vec3 v) {
    printMESA (v.x);
    printMESA (v.y);
    printMESA (v.z);
}

void printMESA (const vec4 v) {
    printMESA (v.x);
    printMESA (v.y);
    printMESA (v.z);
    printMESA (v.w);
}

void printMESA (const ivec2 v) {
    printMESA (v.x);
    printMESA (v.y);
}

void printMESA (const ivec3 v) {
    printMESA (v.x);
    printMESA (v.y);
    printMESA (v.z);
}

void printMESA (const ivec4 v) {
    printMESA (v.x);
    printMESA (v.y);
    printMESA (v.z);
    printMESA (v.w);
}

void printMESA (const bvec2 v) {
    printMESA (v.x);
    printMESA (v.y);
}

void printMESA (const bvec3 v) {
    printMESA (v.x);
    printMESA (v.y);
    printMESA (v.z);
}

void printMESA (const bvec4 v) {
    printMESA (v.x);
    printMESA (v.y);
    printMESA (v.z);
    printMESA (v.w);
}

void printMESA (const mat2 m) {
    printMESA (m[0]);
    printMESA (m[1]);
}

void printMESA (const mat3 m) {
    printMESA (m[0]);
    printMESA (m[1]);
    printMESA (m[2]);
}

void printMESA (const mat4 m) {
    printMESA (m[0]);
    printMESA (m[1]);
    printMESA (m[2]);
    printMESA (m[3]);
}

void printMESA (const sampler1D e) {
    __asm int_print e;
}

void printMESA (const sampler2D e) {
    __asm int_print e;
}

void printMESA (const sampler3D e) {
    __asm int_print e;
}

void printMESA (const samplerCube e) {
    __asm int_print e;
}

void printMESA (const sampler1DShadow e) {
    __asm int_print e;
}

void printMESA (const sampler2DShadow e) {
    __asm int_print e;
}

