I=(S=Uno.Matrix = function(){
}).prototype;

S.UnsignedZToClipSpace = function(m)
{
    return Uno.Matrix.Mul(Uno.Matrix.Mul(m, Uno.Matrix.Scaling_1(1.0, 1.0, 2.0)), Uno.Matrix.Translation_1(0.0, 0.0, -1.0));
};

S.LookAtRH = function(eye, target, up)
{
    var zaxis = Uno.Vector.Normalize(Uno.Float3.operator_Sub(eye, target));
    var xaxis = Uno.Vector.Normalize(Uno.Vector.Cross(up, zaxis));
    var yaxis = Uno.Vector.Normalize(Uno.Vector.Cross(zaxis, xaxis));
    var result = Uno.Matrix.Identity();
    result.M11 = xaxis.X;
    result.M21 = xaxis.Y;
    result.M31 = xaxis.Z;
    result.M12 = yaxis.X;
    result.M22 = yaxis.Y;
    result.M32 = yaxis.Z;
    result.M13 = zaxis.X;
    result.M23 = zaxis.Y;
    result.M33 = zaxis.Z;
    result.M41 = -Uno.Vector.Dot(xaxis, eye);
    result.M42 = -Uno.Vector.Dot(yaxis, eye);
    result.M43 = -Uno.Vector.Dot(zaxis, eye);
    return result;
};

S.PerspectiveRH = function(fov, aspect, znear, zfar)
{
    var yScale = 1.0 / Math.tan(fov * 0.5);
    var xScale = yScale / aspect;
    var halfWidth = znear / xScale;
    var halfHeight = znear / yScale;
    var left = -halfWidth;
    var right = halfWidth;
    var bottom = -halfHeight;
    var top = halfHeight;
    var zRange = zfar / (zfar - znear);
    var result = Uno.Matrix.Identity();
    result.M11 = (2.0 * znear) / (right - left);
    result.M22 = (2.0 * znear) / (top - bottom);
    result.M31 = (left + right) / (left - right);
    result.M32 = (top + bottom) / (bottom - top);
    result.M33 = zRange;
    result.M34 = 1.0;
    result.M43 = (-znear) * zRange;
    result.M31 = -result.M31;
    result.M32 = -result.M32;
    result.M33 = -result.M33;
    result.M34 = -result.M34;
    return Uno.Matrix.UnsignedZToClipSpace(result);
};

S.Scaling = function(scale)
{
    var result = Uno.Matrix.Identity();
    result.M11 = scale.X;
    result.M22 = scale.Y;
    result.M33 = scale.Z;
    return result;
};

S.Scaling_1 = function(x, y, z)
{
    var result = Uno.Matrix.Identity();
    result.M11 = x;
    result.M22 = y;
    result.M33 = z;
    return result;
};

S.RotationAxis = function(axisNormalized, angleRadians)
{
    var x = axisNormalized.X;
    var y = axisNormalized.Y;
    var z = axisNormalized.Z;
    var c = Math.cos(angleRadians);
    var s = Math.sin(angleRadians);
    var xx = x * x;
    var yy = y * y;
    var zz = z * z;
    var xy = x * y;
    var xz = x * z;
    var yz = y * z;
    var result = Uno.Matrix.Identity();
    result.M11 = xx + (c * (1.0 - xx));
    result.M12 = (xy - (c * xy)) + (s * z);
    result.M13 = (xz - (c * xz)) - (s * y);
    result.M21 = (xy - (c * xy)) - (s * z);
    result.M22 = yy + (c * (1.0 - yy));
    result.M23 = (yz - (c * yz)) + (s * x);
    result.M31 = (xz - (c * xz)) + (s * y);
    result.M32 = (yz - (c * yz)) - (s * x);
    result.M33 = zz + (c * (1.0 - zz));
    return result;
};

S.RotationQuaternion = function(rotation)
{
    var xx = rotation.X * rotation.X;
    var yy = rotation.Y * rotation.Y;
    var zz = rotation.Z * rotation.Z;
    var xy = rotation.X * rotation.Y;
    var zw = rotation.Z * rotation.W;
    var zx = rotation.Z * rotation.X;
    var yw = rotation.Y * rotation.W;
    var yz = rotation.Y * rotation.Z;
    var xw = rotation.X * rotation.W;
    var result = Uno.Matrix.Identity();
    result.M11 = 1.0 - (2.0 * (yy + zz));
    result.M12 = 2.0 * (xy + zw);
    result.M13 = 2.0 * (zx - yw);
    result.M21 = 2.0 * (xy - zw);
    result.M22 = 1.0 - (2.0 * (zz + xx));
    result.M23 = 2.0 * (yz + xw);
    result.M31 = 2.0 * (zx + yw);
    result.M32 = 2.0 * (yz - xw);
    result.M33 = 1.0 - (2.0 * (yy + xx));
    return result;
};

S.Transpose = function(m)
{
    return Uno.Float4x4.$1(Uno.Float4.$1(m.M11, m.M21, m.M31, m.M41), Uno.Float4.$1(m.M12, m.M22, m.M32, m.M42), Uno.Float4.$1(m.M13, m.M23, m.M33, m.M43), Uno.Float4.$1(m.M14, m.M24, m.M34, m.M44));
};

S.Translation = function(offset)
{
    var result = Uno.Matrix.Identity();
    result.M41 = offset.X;
    result.M42 = offset.Y;
    result.M43 = offset.Z;
    return result;
};

S.Translation_1 = function(x, y, z)
{
    var result = Uno.Matrix.Identity();
    result.M41 = x;
    result.M42 = y;
    result.M43 = z;
    return result;
};

S.Mul = function(left, right)
{
    var result = new Uno.Float4x4;
    result.M11 = (((left.M11 * right.M11) + (left.M12 * right.M21)) + (left.M13 * right.M31)) + (left.M14 * right.M41);
    result.M12 = (((left.M11 * right.M12) + (left.M12 * right.M22)) + (left.M13 * right.M32)) + (left.M14 * right.M42);
    result.M13 = (((left.M11 * right.M13) + (left.M12 * right.M23)) + (left.M13 * right.M33)) + (left.M14 * right.M43);
    result.M14 = (((left.M11 * right.M14) + (left.M12 * right.M24)) + (left.M13 * right.M34)) + (left.M14 * right.M44);
    result.M21 = (((left.M21 * right.M11) + (left.M22 * right.M21)) + (left.M23 * right.M31)) + (left.M24 * right.M41);
    result.M22 = (((left.M21 * right.M12) + (left.M22 * right.M22)) + (left.M23 * right.M32)) + (left.M24 * right.M42);
    result.M23 = (((left.M21 * right.M13) + (left.M22 * right.M23)) + (left.M23 * right.M33)) + (left.M24 * right.M43);
    result.M24 = (((left.M21 * right.M14) + (left.M22 * right.M24)) + (left.M23 * right.M34)) + (left.M24 * right.M44);
    result.M31 = (((left.M31 * right.M11) + (left.M32 * right.M21)) + (left.M33 * right.M31)) + (left.M34 * right.M41);
    result.M32 = (((left.M31 * right.M12) + (left.M32 * right.M22)) + (left.M33 * right.M32)) + (left.M34 * right.M42);
    result.M33 = (((left.M31 * right.M13) + (left.M32 * right.M23)) + (left.M33 * right.M33)) + (left.M34 * right.M43);
    result.M34 = (((left.M31 * right.M14) + (left.M32 * right.M24)) + (left.M33 * right.M34)) + (left.M34 * right.M44);
    result.M41 = (((left.M41 * right.M11) + (left.M42 * right.M21)) + (left.M43 * right.M31)) + (left.M44 * right.M41);
    result.M42 = (((left.M41 * right.M12) + (left.M42 * right.M22)) + (left.M43 * right.M32)) + (left.M44 * right.M42);
    result.M43 = (((left.M41 * right.M13) + (left.M42 * right.M23)) + (left.M43 * right.M33)) + (left.M44 * right.M43);
    result.M44 = (((left.M41 * right.M14) + (left.M42 * right.M24)) + (left.M43 * right.M34)) + (left.M44 * right.M44);
    return result;
};

S.Invert = function(value, result)
{
    var b0 = (value.M31 * value.M42) - (value.M32 * value.M41);
    var b1 = (value.M31 * value.M43) - (value.M33 * value.M41);
    var b2 = (value.M34 * value.M41) - (value.M31 * value.M44);
    var b3 = (value.M32 * value.M43) - (value.M33 * value.M42);
    var b4 = (value.M34 * value.M42) - (value.M32 * value.M44);
    var b5 = (value.M33 * value.M44) - (value.M34 * value.M43);
    var d11 = ((value.M22 * b5) + (value.M23 * b4)) + (value.M24 * b3);
    var d12 = ((value.M21 * b5) + (value.M23 * b2)) + (value.M24 * b1);
    var d13 = ((value.M21 * (-b4)) + (value.M22 * b2)) + (value.M24 * b0);
    var d14 = ((value.M21 * b3) + (value.M22 * (-b1))) + (value.M23 * b0);
    var det = (((value.M11 * d11) - (value.M12 * d12)) + (value.M13 * d13)) - (value.M14 * d14);

    if (Math.abs(det) <= 1e-08)
    {
        result(Uno.Matrix.Identity());
        return false;
    }

    det = 1.0 / det;
    var a0 = (value.M11 * value.M22) - (value.M12 * value.M21);
    var a1 = (value.M11 * value.M23) - (value.M13 * value.M21);
    var a2 = (value.M14 * value.M21) - (value.M11 * value.M24);
    var a3 = (value.M12 * value.M23) - (value.M13 * value.M22);
    var a4 = (value.M14 * value.M22) - (value.M12 * value.M24);
    var a5 = (value.M13 * value.M24) - (value.M14 * value.M23);
    var d21 = ((value.M12 * b5) + (value.M13 * b4)) + (value.M14 * b3);
    var d22 = ((value.M11 * b5) + (value.M13 * b2)) + (value.M14 * b1);
    var d23 = ((value.M11 * (-b4)) + (value.M12 * b2)) + (value.M14 * b0);
    var d24 = ((value.M11 * b3) + (value.M12 * (-b1))) + (value.M13 * b0);
    var d31 = ((value.M42 * a5) + (value.M43 * a4)) + (value.M44 * a3);
    var d32 = ((value.M41 * a5) + (value.M43 * a2)) + (value.M44 * a1);
    var d33 = ((value.M41 * (-a4)) + (value.M42 * a2)) + (value.M44 * a0);
    var d34 = ((value.M41 * a3) + (value.M42 * (-a1))) + (value.M43 * a0);
    var d41 = ((value.M32 * a5) + (value.M33 * a4)) + (value.M34 * a3);
    var d42 = ((value.M31 * a5) + (value.M33 * a2)) + (value.M34 * a1);
    var d43 = ((value.M31 * (-a4)) + (value.M32 * a2)) + (value.M34 * a0);
    var d44 = ((value.M31 * a3) + (value.M32 * (-a1))) + (value.M33 * a0);
    result().M11 = d11 * det;
    result().M12 = (-d21) * det;
    result().M13 = d31 * det;
    result().M14 = (-d41) * det;
    result().M21 = (-d12) * det;
    result().M22 = d22 * det;
    result().M23 = (-d32) * det;
    result().M24 = d42 * det;
    result().M31 = d13 * det;
    result().M32 = (-d23) * det;
    result().M33 = d33 * det;
    result().M34 = (-d43) * det;
    result().M41 = (-d14) * det;
    result().M42 = d24 * det;
    result().M43 = (-d34) * det;
    result().M44 = d44 * det;
    return true;
};

S.Invert_1 = function(value)
{
    var m = new Uno.Float4x4;
    Uno.Matrix.Invert(value, ref(function(){return m}, function($){m=$}, this));
    return m;
};

S.Decompose = function(value, scale, rotationQuaternion, translation)
{
    translation().X = value.M41;
    translation().Y = value.M42;
    translation().Z = value.M43;
    scale().X = Math.sqrt(((value.M11 * value.M11) + (value.M12 * value.M12)) + (value.M13 * value.M13));
    scale().Y = Math.sqrt(((value.M21 * value.M21) + (value.M22 * value.M22)) + (value.M23 * value.M23));
    scale().Z = Math.sqrt(((value.M31 * value.M31) + (value.M32 * value.M32)) + (value.M33 * value.M33));

    if (((Math.abs(scale().X) < 1e-06) || (Math.abs(scale().Y) < 1e-06)) || (Math.abs(scale().Z) < 1e-06))
    {
        rotationQuaternion(Uno.Quaternion.Identity());
        return false;
    }

    var rotationMatrix = Uno.Float3x3.$0(value.M11 / scale().X, value.M12 / scale().X, value.M13 / scale().X, value.M21 / scale().Y, value.M22 / scale().Y, value.M23 / scale().Y, value.M31 / scale().Z, value.M32 / scale().Z, value.M33 / scale().Z);
    Uno.Quaternion.RotationMatrix(rotationMatrix, rotationQuaternion);
    return true;
};

S.Identity = function()
{
    return Uno.Float4x4.$1(Uno.Float4.$1(1.0, 0.0, 0.0, 0.0), Uno.Float4.$1(0.0, 1.0, 0.0, 0.0), Uno.Float4.$1(0.0, 0.0, 1.0, 0.0), Uno.Float4.$1(0.0, 0.0, 0.0, 1.0));
};
