//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Runtime.CompilerServices;
using Unity.IL2CPP.CompilerServices;

#pragma warning disable 0660, 0661

namespace Unity.Mathematics
{
    /// <summary>A 4x4 matrix of doubles.</summary>
    [System.Serializable]
    [Il2CppEagerStaticClassConstruction]
    public partial struct double4x4 : System.IEquatable<double4x4>, IFormattable
    {
        /// <summary>Column 0 of the matrix.</summary>
        public double4 c0;
        /// <summary>Column 1 of the matrix.</summary>
        public double4 c1;
        /// <summary>Column 2 of the matrix.</summary>
        public double4 c2;
        /// <summary>Column 3 of the matrix.</summary>
        public double4 c3;

        /// <summary>double4x4 identity transform.</summary>
        public static readonly double4x4 identity = new double4x4(1.0, 0.0, 0.0, 0.0,   0.0, 1.0, 0.0, 0.0,   0.0, 0.0, 1.0, 0.0,   0.0, 0.0, 0.0, 1.0);

        /// <summary>double4x4 zero value.</summary>
        public static readonly double4x4 zero;

        /// <summary>Constructs a double4x4 matrix from four double4 vectors.</summary>
        /// <param name="c0">The matrix column c0 will be set to this value.</param>
        /// <param name="c1">The matrix column c1 will be set to this value.</param>
        /// <param name="c2">The matrix column c2 will be set to this value.</param>
        /// <param name="c3">The matrix column c3 will be set to this value.</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(double4 c0, double4 c1, double4 c2, double4 c3)
        {
            this.c0 = c0;
            this.c1 = c1;
            this.c2 = c2;
            this.c3 = c3;
        }

        /// <summary>Constructs a double4x4 matrix from 16 double values given in row-major order.</summary>
        /// <param name="m00">The matrix at row 0, column 0 will be set to this value.</param>
        /// <param name="m01">The matrix at row 0, column 1 will be set to this value.</param>
        /// <param name="m02">The matrix at row 0, column 2 will be set to this value.</param>
        /// <param name="m03">The matrix at row 0, column 3 will be set to this value.</param>
        /// <param name="m10">The matrix at row 1, column 0 will be set to this value.</param>
        /// <param name="m11">The matrix at row 1, column 1 will be set to this value.</param>
        /// <param name="m12">The matrix at row 1, column 2 will be set to this value.</param>
        /// <param name="m13">The matrix at row 1, column 3 will be set to this value.</param>
        /// <param name="m20">The matrix at row 2, column 0 will be set to this value.</param>
        /// <param name="m21">The matrix at row 2, column 1 will be set to this value.</param>
        /// <param name="m22">The matrix at row 2, column 2 will be set to this value.</param>
        /// <param name="m23">The matrix at row 2, column 3 will be set to this value.</param>
        /// <param name="m30">The matrix at row 3, column 0 will be set to this value.</param>
        /// <param name="m31">The matrix at row 3, column 1 will be set to this value.</param>
        /// <param name="m32">The matrix at row 3, column 2 will be set to this value.</param>
        /// <param name="m33">The matrix at row 3, column 3 will be set to this value.</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(double m00, double m01, double m02, double m03,
                         double m10, double m11, double m12, double m13,
                         double m20, double m21, double m22, double m23,
                         double m30, double m31, double m32, double m33)
        {
            this.c0 = new double4(m00, m10, m20, m30);
            this.c1 = new double4(m01, m11, m21, m31);
            this.c2 = new double4(m02, m12, m22, m32);
            this.c3 = new double4(m03, m13, m23, m33);
        }

        /// <summary>Constructs a double4x4 matrix from a single double value by assigning it to every component.</summary>
        /// <param name="v">double to convert to double4x4</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(double v)
        {
            this.c0 = v;
            this.c1 = v;
            this.c2 = v;
            this.c3 = v;
        }

        /// <summary>Constructs a double4x4 matrix from a single bool value by converting it to double and assigning it to every component.</summary>
        /// <param name="v">bool to convert to double4x4</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(bool v)
        {
            this.c0 = math.select(new double4(0.0), new double4(1.0), v);
            this.c1 = math.select(new double4(0.0), new double4(1.0), v);
            this.c2 = math.select(new double4(0.0), new double4(1.0), v);
            this.c3 = math.select(new double4(0.0), new double4(1.0), v);
        }

        /// <summary>Constructs a double4x4 matrix from a bool4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">bool4x4 to convert to double4x4</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(bool4x4 v)
        {
            this.c0 = math.select(new double4(0.0), new double4(1.0), v.c0);
            this.c1 = math.select(new double4(0.0), new double4(1.0), v.c1);
            this.c2 = math.select(new double4(0.0), new double4(1.0), v.c2);
            this.c3 = math.select(new double4(0.0), new double4(1.0), v.c3);
        }

        /// <summary>Constructs a double4x4 matrix from a single int value by converting it to double and assigning it to every component.</summary>
        /// <param name="v">int to convert to double4x4</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(int v)
        {
            this.c0 = v;
            this.c1 = v;
            this.c2 = v;
            this.c3 = v;
        }

        /// <summary>Constructs a double4x4 matrix from a int4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">int4x4 to convert to double4x4</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(int4x4 v)
        {
            this.c0 = v.c0;
            this.c1 = v.c1;
            this.c2 = v.c2;
            this.c3 = v.c3;
        }

        /// <summary>Constructs a double4x4 matrix from a single uint value by converting it to double and assigning it to every component.</summary>
        /// <param name="v">uint to convert to double4x4</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(uint v)
        {
            this.c0 = v;
            this.c1 = v;
            this.c2 = v;
            this.c3 = v;
        }

        /// <summary>Constructs a double4x4 matrix from a uint4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">uint4x4 to convert to double4x4</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(uint4x4 v)
        {
            this.c0 = v.c0;
            this.c1 = v.c1;
            this.c2 = v.c2;
            this.c3 = v.c3;
        }

        /// <summary>Constructs a double4x4 matrix from a single float value by converting it to double and assigning it to every component.</summary>
        /// <param name="v">float to convert to double4x4</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(float v)
        {
            this.c0 = v;
            this.c1 = v;
            this.c2 = v;
            this.c3 = v;
        }

        /// <summary>Constructs a double4x4 matrix from a float4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">float4x4 to convert to double4x4</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double4x4(float4x4 v)
        {
            this.c0 = v.c0;
            this.c1 = v.c1;
            this.c2 = v.c2;
            this.c3 = v.c3;
        }


        /// <summary>Implicitly converts a single double value to a double4x4 matrix by assigning it to every component.</summary>
        /// <param name="v">double to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static implicit operator double4x4(double v) { return new double4x4(v); }

        /// <summary>Explicitly converts a single bool value to a double4x4 matrix by converting it to double and assigning it to every component.</summary>
        /// <param name="v">bool to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static explicit operator double4x4(bool v) { return new double4x4(v); }

        /// <summary>Explicitly converts a bool4x4 matrix to a double4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">bool4x4 to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static explicit operator double4x4(bool4x4 v) { return new double4x4(v); }

        /// <summary>Implicitly converts a single int value to a double4x4 matrix by converting it to double and assigning it to every component.</summary>
        /// <param name="v">int to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static implicit operator double4x4(int v) { return new double4x4(v); }

        /// <summary>Implicitly converts a int4x4 matrix to a double4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">int4x4 to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static implicit operator double4x4(int4x4 v) { return new double4x4(v); }

        /// <summary>Implicitly converts a single uint value to a double4x4 matrix by converting it to double and assigning it to every component.</summary>
        /// <param name="v">uint to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static implicit operator double4x4(uint v) { return new double4x4(v); }

        /// <summary>Implicitly converts a uint4x4 matrix to a double4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">uint4x4 to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static implicit operator double4x4(uint4x4 v) { return new double4x4(v); }

        /// <summary>Implicitly converts a single float value to a double4x4 matrix by converting it to double and assigning it to every component.</summary>
        /// <param name="v">float to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static implicit operator double4x4(float v) { return new double4x4(v); }

        /// <summary>Implicitly converts a float4x4 matrix to a double4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">float4x4 to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static implicit operator double4x4(float4x4 v) { return new double4x4(v); }


        /// <summary>Returns the result of a componentwise multiplication operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise multiplication.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise multiplication.</param>
        /// <returns>double4x4 result of the componentwise multiplication.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator * (double4x4 lhs, double4x4 rhs) { return new double4x4 (lhs.c0 * rhs.c0, lhs.c1 * rhs.c1, lhs.c2 * rhs.c2, lhs.c3 * rhs.c3); }

        /// <summary>Returns the result of a componentwise multiplication operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise multiplication.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise multiplication.</param>
        /// <returns>double4x4 result of the componentwise multiplication.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator * (double4x4 lhs, double rhs) { return new double4x4 (lhs.c0 * rhs, lhs.c1 * rhs, lhs.c2 * rhs, lhs.c3 * rhs); }

        /// <summary>Returns the result of a componentwise multiplication operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise multiplication.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise multiplication.</param>
        /// <returns>double4x4 result of the componentwise multiplication.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator * (double lhs, double4x4 rhs) { return new double4x4 (lhs * rhs.c0, lhs * rhs.c1, lhs * rhs.c2, lhs * rhs.c3); }


        /// <summary>Returns the result of a componentwise addition operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise addition.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise addition.</param>
        /// <returns>double4x4 result of the componentwise addition.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator + (double4x4 lhs, double4x4 rhs) { return new double4x4 (lhs.c0 + rhs.c0, lhs.c1 + rhs.c1, lhs.c2 + rhs.c2, lhs.c3 + rhs.c3); }

        /// <summary>Returns the result of a componentwise addition operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise addition.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise addition.</param>
        /// <returns>double4x4 result of the componentwise addition.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator + (double4x4 lhs, double rhs) { return new double4x4 (lhs.c0 + rhs, lhs.c1 + rhs, lhs.c2 + rhs, lhs.c3 + rhs); }

        /// <summary>Returns the result of a componentwise addition operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise addition.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise addition.</param>
        /// <returns>double4x4 result of the componentwise addition.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator + (double lhs, double4x4 rhs) { return new double4x4 (lhs + rhs.c0, lhs + rhs.c1, lhs + rhs.c2, lhs + rhs.c3); }


        /// <summary>Returns the result of a componentwise subtraction operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise subtraction.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise subtraction.</param>
        /// <returns>double4x4 result of the componentwise subtraction.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator - (double4x4 lhs, double4x4 rhs) { return new double4x4 (lhs.c0 - rhs.c0, lhs.c1 - rhs.c1, lhs.c2 - rhs.c2, lhs.c3 - rhs.c3); }

        /// <summary>Returns the result of a componentwise subtraction operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise subtraction.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise subtraction.</param>
        /// <returns>double4x4 result of the componentwise subtraction.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator - (double4x4 lhs, double rhs) { return new double4x4 (lhs.c0 - rhs, lhs.c1 - rhs, lhs.c2 - rhs, lhs.c3 - rhs); }

        /// <summary>Returns the result of a componentwise subtraction operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise subtraction.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise subtraction.</param>
        /// <returns>double4x4 result of the componentwise subtraction.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator - (double lhs, double4x4 rhs) { return new double4x4 (lhs - rhs.c0, lhs - rhs.c1, lhs - rhs.c2, lhs - rhs.c3); }


        /// <summary>Returns the result of a componentwise division operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise division.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise division.</param>
        /// <returns>double4x4 result of the componentwise division.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator / (double4x4 lhs, double4x4 rhs) { return new double4x4 (lhs.c0 / rhs.c0, lhs.c1 / rhs.c1, lhs.c2 / rhs.c2, lhs.c3 / rhs.c3); }

        /// <summary>Returns the result of a componentwise division operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise division.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise division.</param>
        /// <returns>double4x4 result of the componentwise division.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator / (double4x4 lhs, double rhs) { return new double4x4 (lhs.c0 / rhs, lhs.c1 / rhs, lhs.c2 / rhs, lhs.c3 / rhs); }

        /// <summary>Returns the result of a componentwise division operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise division.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise division.</param>
        /// <returns>double4x4 result of the componentwise division.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator / (double lhs, double4x4 rhs) { return new double4x4 (lhs / rhs.c0, lhs / rhs.c1, lhs / rhs.c2, lhs / rhs.c3); }


        /// <summary>Returns the result of a componentwise modulus operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise modulus.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise modulus.</param>
        /// <returns>double4x4 result of the componentwise modulus.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator % (double4x4 lhs, double4x4 rhs) { return new double4x4 (lhs.c0 % rhs.c0, lhs.c1 % rhs.c1, lhs.c2 % rhs.c2, lhs.c3 % rhs.c3); }

        /// <summary>Returns the result of a componentwise modulus operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise modulus.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise modulus.</param>
        /// <returns>double4x4 result of the componentwise modulus.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator % (double4x4 lhs, double rhs) { return new double4x4 (lhs.c0 % rhs, lhs.c1 % rhs, lhs.c2 % rhs, lhs.c3 % rhs); }

        /// <summary>Returns the result of a componentwise modulus operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise modulus.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise modulus.</param>
        /// <returns>double4x4 result of the componentwise modulus.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator % (double lhs, double4x4 rhs) { return new double4x4 (lhs % rhs.c0, lhs % rhs.c1, lhs % rhs.c2, lhs % rhs.c3); }


        /// <summary>Returns the result of a componentwise increment operation on a double4x4 matrix.</summary>
        /// <param name="val">Value to use when computing the componentwise increment.</param>
        /// <returns>double4x4 result of the componentwise increment.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator ++ (double4x4 val) { return new double4x4 (++val.c0, ++val.c1, ++val.c2, ++val.c3); }


        /// <summary>Returns the result of a componentwise decrement operation on a double4x4 matrix.</summary>
        /// <param name="val">Value to use when computing the componentwise decrement.</param>
        /// <returns>double4x4 result of the componentwise decrement.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator -- (double4x4 val) { return new double4x4 (--val.c0, --val.c1, --val.c2, --val.c3); }


        /// <summary>Returns the result of a componentwise less than operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise less than.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise less than.</param>
        /// <returns>bool4x4 result of the componentwise less than.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator < (double4x4 lhs, double4x4 rhs) { return new bool4x4 (lhs.c0 < rhs.c0, lhs.c1 < rhs.c1, lhs.c2 < rhs.c2, lhs.c3 < rhs.c3); }

        /// <summary>Returns the result of a componentwise less than operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise less than.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise less than.</param>
        /// <returns>bool4x4 result of the componentwise less than.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator < (double4x4 lhs, double rhs) { return new bool4x4 (lhs.c0 < rhs, lhs.c1 < rhs, lhs.c2 < rhs, lhs.c3 < rhs); }

        /// <summary>Returns the result of a componentwise less than operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise less than.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise less than.</param>
        /// <returns>bool4x4 result of the componentwise less than.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator < (double lhs, double4x4 rhs) { return new bool4x4 (lhs < rhs.c0, lhs < rhs.c1, lhs < rhs.c2, lhs < rhs.c3); }


        /// <summary>Returns the result of a componentwise less or equal operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise less or equal.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise less or equal.</param>
        /// <returns>bool4x4 result of the componentwise less or equal.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator <= (double4x4 lhs, double4x4 rhs) { return new bool4x4 (lhs.c0 <= rhs.c0, lhs.c1 <= rhs.c1, lhs.c2 <= rhs.c2, lhs.c3 <= rhs.c3); }

        /// <summary>Returns the result of a componentwise less or equal operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise less or equal.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise less or equal.</param>
        /// <returns>bool4x4 result of the componentwise less or equal.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator <= (double4x4 lhs, double rhs) { return new bool4x4 (lhs.c0 <= rhs, lhs.c1 <= rhs, lhs.c2 <= rhs, lhs.c3 <= rhs); }

        /// <summary>Returns the result of a componentwise less or equal operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise less or equal.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise less or equal.</param>
        /// <returns>bool4x4 result of the componentwise less or equal.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator <= (double lhs, double4x4 rhs) { return new bool4x4 (lhs <= rhs.c0, lhs <= rhs.c1, lhs <= rhs.c2, lhs <= rhs.c3); }


        /// <summary>Returns the result of a componentwise greater than operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise greater than.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise greater than.</param>
        /// <returns>bool4x4 result of the componentwise greater than.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator > (double4x4 lhs, double4x4 rhs) { return new bool4x4 (lhs.c0 > rhs.c0, lhs.c1 > rhs.c1, lhs.c2 > rhs.c2, lhs.c3 > rhs.c3); }

        /// <summary>Returns the result of a componentwise greater than operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise greater than.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise greater than.</param>
        /// <returns>bool4x4 result of the componentwise greater than.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator > (double4x4 lhs, double rhs) { return new bool4x4 (lhs.c0 > rhs, lhs.c1 > rhs, lhs.c2 > rhs, lhs.c3 > rhs); }

        /// <summary>Returns the result of a componentwise greater than operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise greater than.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise greater than.</param>
        /// <returns>bool4x4 result of the componentwise greater than.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator > (double lhs, double4x4 rhs) { return new bool4x4 (lhs > rhs.c0, lhs > rhs.c1, lhs > rhs.c2, lhs > rhs.c3); }


        /// <summary>Returns the result of a componentwise greater or equal operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise greater or equal.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise greater or equal.</param>
        /// <returns>bool4x4 result of the componentwise greater or equal.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator >= (double4x4 lhs, double4x4 rhs) { return new bool4x4 (lhs.c0 >= rhs.c0, lhs.c1 >= rhs.c1, lhs.c2 >= rhs.c2, lhs.c3 >= rhs.c3); }

        /// <summary>Returns the result of a componentwise greater or equal operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise greater or equal.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise greater or equal.</param>
        /// <returns>bool4x4 result of the componentwise greater or equal.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator >= (double4x4 lhs, double rhs) { return new bool4x4 (lhs.c0 >= rhs, lhs.c1 >= rhs, lhs.c2 >= rhs, lhs.c3 >= rhs); }

        /// <summary>Returns the result of a componentwise greater or equal operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise greater or equal.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise greater or equal.</param>
        /// <returns>bool4x4 result of the componentwise greater or equal.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator >= (double lhs, double4x4 rhs) { return new bool4x4 (lhs >= rhs.c0, lhs >= rhs.c1, lhs >= rhs.c2, lhs >= rhs.c3); }


        /// <summary>Returns the result of a componentwise unary minus operation on a double4x4 matrix.</summary>
        /// <param name="val">Value to use when computing the componentwise unary minus.</param>
        /// <returns>double4x4 result of the componentwise unary minus.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator - (double4x4 val) { return new double4x4 (-val.c0, -val.c1, -val.c2, -val.c3); }


        /// <summary>Returns the result of a componentwise unary plus operation on a double4x4 matrix.</summary>
        /// <param name="val">Value to use when computing the componentwise unary plus.</param>
        /// <returns>double4x4 result of the componentwise unary plus.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 operator + (double4x4 val) { return new double4x4 (+val.c0, +val.c1, +val.c2, +val.c3); }


        /// <summary>Returns the result of a componentwise equality operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise equality.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise equality.</param>
        /// <returns>bool4x4 result of the componentwise equality.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator == (double4x4 lhs, double4x4 rhs) { return new bool4x4 (lhs.c0 == rhs.c0, lhs.c1 == rhs.c1, lhs.c2 == rhs.c2, lhs.c3 == rhs.c3); }

        /// <summary>Returns the result of a componentwise equality operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise equality.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise equality.</param>
        /// <returns>bool4x4 result of the componentwise equality.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator == (double4x4 lhs, double rhs) { return new bool4x4 (lhs.c0 == rhs, lhs.c1 == rhs, lhs.c2 == rhs, lhs.c3 == rhs); }

        /// <summary>Returns the result of a componentwise equality operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise equality.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise equality.</param>
        /// <returns>bool4x4 result of the componentwise equality.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator == (double lhs, double4x4 rhs) { return new bool4x4 (lhs == rhs.c0, lhs == rhs.c1, lhs == rhs.c2, lhs == rhs.c3); }


        /// <summary>Returns the result of a componentwise not equal operation on two double4x4 matrices.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise not equal.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise not equal.</param>
        /// <returns>bool4x4 result of the componentwise not equal.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator != (double4x4 lhs, double4x4 rhs) { return new bool4x4 (lhs.c0 != rhs.c0, lhs.c1 != rhs.c1, lhs.c2 != rhs.c2, lhs.c3 != rhs.c3); }

        /// <summary>Returns the result of a componentwise not equal operation on a double4x4 matrix and a double value.</summary>
        /// <param name="lhs">Left hand side double4x4 to use to compute componentwise not equal.</param>
        /// <param name="rhs">Right hand side double to use to compute componentwise not equal.</param>
        /// <returns>bool4x4 result of the componentwise not equal.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator != (double4x4 lhs, double rhs) { return new bool4x4 (lhs.c0 != rhs, lhs.c1 != rhs, lhs.c2 != rhs, lhs.c3 != rhs); }

        /// <summary>Returns the result of a componentwise not equal operation on a double value and a double4x4 matrix.</summary>
        /// <param name="lhs">Left hand side double to use to compute componentwise not equal.</param>
        /// <param name="rhs">Right hand side double4x4 to use to compute componentwise not equal.</param>
        /// <returns>bool4x4 result of the componentwise not equal.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static bool4x4 operator != (double lhs, double4x4 rhs) { return new bool4x4 (lhs != rhs.c0, lhs != rhs.c1, lhs != rhs.c2, lhs != rhs.c3); }



        /// <summary>Returns the double4 element at a specified index.</summary>
        unsafe public ref double4 this[int index]
        {
            get
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if ((uint)index >= 4)
                    throw new System.ArgumentException("index must be between[0...3]");
#endif
                fixed (double4x4* array = &this) { return ref ((double4*)array)[index]; }
            }
        }

        /// <summary>Returns true if the double4x4 is equal to a given double4x4, false otherwise.</summary>
        /// <param name="rhs">Right hand side argument to compare equality with.</param>
        /// <returns>The result of the equality comparison.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public bool Equals(double4x4 rhs) { return c0.Equals(rhs.c0) && c1.Equals(rhs.c1) && c2.Equals(rhs.c2) && c3.Equals(rhs.c3); }

        /// <summary>Returns true if the double4x4 is equal to a given double4x4, false otherwise.</summary>
        /// <param name="o">Right hand side argument to compare equality with.</param>
        /// <returns>The result of the equality comparison.</returns>
        public override bool Equals(object o) { return o is double4x4 converted && Equals(converted); }


        /// <summary>Returns a hash code for the double4x4.</summary>
        /// <returns>The computed hash code.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override int GetHashCode() { return (int)math.hash(this); }


        /// <summary>Returns a string representation of the double4x4.</summary>
        /// <returns>String representation of the value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override string ToString()
        {
            return string.Format("double4x4({0}, {1}, {2}, {3},  {4}, {5}, {6}, {7},  {8}, {9}, {10}, {11},  {12}, {13}, {14}, {15})", c0.x, c1.x, c2.x, c3.x, c0.y, c1.y, c2.y, c3.y, c0.z, c1.z, c2.z, c3.z, c0.w, c1.w, c2.w, c3.w);
        }

        /// <summary>Returns a string representation of the double4x4 using a specified format and culture-specific format information.</summary>
        /// <param name="format">Format string to use during string formatting.</param>
        /// <param name="formatProvider">Format provider to use during string formatting.</param>
        /// <returns>String representation of the value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public string ToString(string format, IFormatProvider formatProvider)
        {
            return string.Format("double4x4({0}, {1}, {2}, {3},  {4}, {5}, {6}, {7},  {8}, {9}, {10}, {11},  {12}, {13}, {14}, {15})", c0.x.ToString(format, formatProvider), c1.x.ToString(format, formatProvider), c2.x.ToString(format, formatProvider), c3.x.ToString(format, formatProvider), c0.y.ToString(format, formatProvider), c1.y.ToString(format, formatProvider), c2.y.ToString(format, formatProvider), c3.y.ToString(format, formatProvider), c0.z.ToString(format, formatProvider), c1.z.ToString(format, formatProvider), c2.z.ToString(format, formatProvider), c3.z.ToString(format, formatProvider), c0.w.ToString(format, formatProvider), c1.w.ToString(format, formatProvider), c2.w.ToString(format, formatProvider), c3.w.ToString(format, formatProvider));
        }

    }

    public static partial class math
    {
        /// <summary>Returns a double4x4 matrix constructed from four double4 vectors.</summary>
        /// <param name="c0">The matrix column c0 will be set to this value.</param>
        /// <param name="c1">The matrix column c1 will be set to this value.</param>
        /// <param name="c2">The matrix column c2 will be set to this value.</param>
        /// <param name="c3">The matrix column c3 will be set to this value.</param>
        /// <returns>double4x4 constructed from arguments.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(double4 c0, double4 c1, double4 c2, double4 c3) { return new double4x4(c0, c1, c2, c3); }

        /// <summary>Returns a double4x4 matrix constructed from from 16 double values given in row-major order.</summary>
        /// <param name="m00">The matrix at row 0, column 0 will be set to this value.</param>
        /// <param name="m01">The matrix at row 0, column 1 will be set to this value.</param>
        /// <param name="m02">The matrix at row 0, column 2 will be set to this value.</param>
        /// <param name="m03">The matrix at row 0, column 3 will be set to this value.</param>
        /// <param name="m10">The matrix at row 1, column 0 will be set to this value.</param>
        /// <param name="m11">The matrix at row 1, column 1 will be set to this value.</param>
        /// <param name="m12">The matrix at row 1, column 2 will be set to this value.</param>
        /// <param name="m13">The matrix at row 1, column 3 will be set to this value.</param>
        /// <param name="m20">The matrix at row 2, column 0 will be set to this value.</param>
        /// <param name="m21">The matrix at row 2, column 1 will be set to this value.</param>
        /// <param name="m22">The matrix at row 2, column 2 will be set to this value.</param>
        /// <param name="m23">The matrix at row 2, column 3 will be set to this value.</param>
        /// <param name="m30">The matrix at row 3, column 0 will be set to this value.</param>
        /// <param name="m31">The matrix at row 3, column 1 will be set to this value.</param>
        /// <param name="m32">The matrix at row 3, column 2 will be set to this value.</param>
        /// <param name="m33">The matrix at row 3, column 3 will be set to this value.</param>
        /// <returns>double4x4 constructed from arguments.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(double m00, double m01, double m02, double m03,
                                          double m10, double m11, double m12, double m13,
                                          double m20, double m21, double m22, double m23,
                                          double m30, double m31, double m32, double m33)
        {
            return new double4x4(m00, m01, m02, m03,
                                 m10, m11, m12, m13,
                                 m20, m21, m22, m23,
                                 m30, m31, m32, m33);
        }

        /// <summary>Returns a double4x4 matrix constructed from a single double value by assigning it to every component.</summary>
        /// <param name="v">double to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(double v) { return new double4x4(v); }

        /// <summary>Returns a double4x4 matrix constructed from a single bool value by converting it to double and assigning it to every component.</summary>
        /// <param name="v">bool to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(bool v) { return new double4x4(v); }

        /// <summary>Return a double4x4 matrix constructed from a bool4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">bool4x4 to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(bool4x4 v) { return new double4x4(v); }

        /// <summary>Returns a double4x4 matrix constructed from a single int value by converting it to double and assigning it to every component.</summary>
        /// <param name="v">int to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(int v) { return new double4x4(v); }

        /// <summary>Return a double4x4 matrix constructed from a int4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">int4x4 to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(int4x4 v) { return new double4x4(v); }

        /// <summary>Returns a double4x4 matrix constructed from a single uint value by converting it to double and assigning it to every component.</summary>
        /// <param name="v">uint to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(uint v) { return new double4x4(v); }

        /// <summary>Return a double4x4 matrix constructed from a uint4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">uint4x4 to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(uint4x4 v) { return new double4x4(v); }

        /// <summary>Returns a double4x4 matrix constructed from a single float value by converting it to double and assigning it to every component.</summary>
        /// <param name="v">float to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(float v) { return new double4x4(v); }

        /// <summary>Return a double4x4 matrix constructed from a float4x4 matrix by componentwise conversion.</summary>
        /// <param name="v">float4x4 to convert to double4x4</param>
        /// <returns>Converted value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 double4x4(float4x4 v) { return new double4x4(v); }

        /// <summary>Return the result of rotating a double3 vector by a double4x4 matrix</summary>
        /// <param name ="a">Left hand side matrix argument that specifies the rotation.</param>
        /// <param name ="b">Right hand side vector argument to be rotated.</param>
        /// <returns>The rotated vector.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double3 rotate(double4x4 a, double3 b)
        {
            return (a.c0 * b.x + a.c1 * b.y + a.c2 * b.z).xyz;
        }

        /// <summary>Return the result of transforming a double3 point by a double4x4 matrix</summary>
        /// <param name ="a">Left hand side matrix argument that specifies the transformation.</param>
        /// <param name ="b">Right hand side point argument to be transformed.</param>
        /// <returns>The transformed point.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double3 transform(double4x4 a, double3 b)
        {
            return (a.c0 * b.x + a.c1 * b.y + a.c2 * b.z + a.c3).xyz;
        }

        /// <summary>Return the double4x4 transpose of a double4x4 matrix.</summary>
        /// <param name="v">Value to transpose.</param>
        /// <returns>Transposed value.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static double4x4 transpose(double4x4 v)
        {
            return double4x4(
                v.c0.x, v.c0.y, v.c0.z, v.c0.w,
                v.c1.x, v.c1.y, v.c1.z, v.c1.w,
                v.c2.x, v.c2.y, v.c2.z, v.c2.w,
                v.c3.x, v.c3.y, v.c3.z, v.c3.w);
        }

        /// <summary>Returns the double4x4 full inverse of a double4x4 matrix.</summary>
        /// <param name="m">Matrix to invert.</param>
        /// <returns>The inverted matrix.</returns>
        public static double4x4 inverse(double4x4 m)
        {
            double4 c0 = m.c0;
            double4 c1 = m.c1;
            double4 c2 = m.c2;
            double4 c3 = m.c3;

            double4 r0y_r1y_r0x_r1x = movelh(c1, c0);
            double4 r0z_r1z_r0w_r1w = movelh(c2, c3);
            double4 r2y_r3y_r2x_r3x = movehl(c0, c1);
            double4 r2z_r3z_r2w_r3w = movehl(c3, c2);

            double4 r1y_r2y_r1x_r2x = shuffle(c1, c0, ShuffleComponent.LeftY, ShuffleComponent.LeftZ, ShuffleComponent.RightY, ShuffleComponent.RightZ);
            double4 r1z_r2z_r1w_r2w = shuffle(c2, c3, ShuffleComponent.LeftY, ShuffleComponent.LeftZ, ShuffleComponent.RightY, ShuffleComponent.RightZ);
            double4 r3y_r0y_r3x_r0x = shuffle(c1, c0, ShuffleComponent.LeftW, ShuffleComponent.LeftX, ShuffleComponent.RightW, ShuffleComponent.RightX);
            double4 r3z_r0z_r3w_r0w = shuffle(c2, c3, ShuffleComponent.LeftW, ShuffleComponent.LeftX, ShuffleComponent.RightW, ShuffleComponent.RightX);

            double4 r0_wzyx = shuffle(r0z_r1z_r0w_r1w, r0y_r1y_r0x_r1x, ShuffleComponent.LeftZ, ShuffleComponent.LeftX, ShuffleComponent.RightX, ShuffleComponent.RightZ);
            double4 r1_wzyx = shuffle(r0z_r1z_r0w_r1w, r0y_r1y_r0x_r1x, ShuffleComponent.LeftW, ShuffleComponent.LeftY, ShuffleComponent.RightY, ShuffleComponent.RightW);
            double4 r2_wzyx = shuffle(r2z_r3z_r2w_r3w, r2y_r3y_r2x_r3x, ShuffleComponent.LeftZ, ShuffleComponent.LeftX, ShuffleComponent.RightX, ShuffleComponent.RightZ);
            double4 r3_wzyx = shuffle(r2z_r3z_r2w_r3w, r2y_r3y_r2x_r3x, ShuffleComponent.LeftW, ShuffleComponent.LeftY, ShuffleComponent.RightY, ShuffleComponent.RightW);
            double4 r0_xyzw = shuffle(r0y_r1y_r0x_r1x, r0z_r1z_r0w_r1w, ShuffleComponent.LeftZ, ShuffleComponent.LeftX, ShuffleComponent.RightX, ShuffleComponent.RightZ);

            // Calculate remaining inner term pairs. inner terms have zw=-xy, so we only have to calculate xy and can pack two pairs per vector.
            double4 inner12_23 = r1y_r2y_r1x_r2x * r2z_r3z_r2w_r3w - r1z_r2z_r1w_r2w * r2y_r3y_r2x_r3x;
            double4 inner02_13 = r0y_r1y_r0x_r1x * r2z_r3z_r2w_r3w - r0z_r1z_r0w_r1w * r2y_r3y_r2x_r3x;
            double4 inner30_01 = r3z_r0z_r3w_r0w * r0y_r1y_r0x_r1x - r3y_r0y_r3x_r0x * r0z_r1z_r0w_r1w;

            // Expand inner terms back to 4 components. zw signs still need to be flipped
            double4 inner12 = shuffle(inner12_23, inner12_23, ShuffleComponent.LeftX, ShuffleComponent.LeftZ, ShuffleComponent.RightZ, ShuffleComponent.RightX);
            double4 inner23 = shuffle(inner12_23, inner12_23, ShuffleComponent.LeftY, ShuffleComponent.LeftW, ShuffleComponent.RightW, ShuffleComponent.RightY);

            double4 inner02 = shuffle(inner02_13, inner02_13, ShuffleComponent.LeftX, ShuffleComponent.LeftZ, ShuffleComponent.RightZ, ShuffleComponent.RightX);
            double4 inner13 = shuffle(inner02_13, inner02_13, ShuffleComponent.LeftY, ShuffleComponent.LeftW, ShuffleComponent.RightW, ShuffleComponent.RightY);

            // Calculate minors
            double4 minors0 = r3_wzyx * inner12 - r2_wzyx * inner13 + r1_wzyx * inner23;

            double4 denom = r0_xyzw * minors0;

            // Horizontal sum of denominator. Free sign flip of z and w compensates for missing flip in inner terms.
            denom = denom + shuffle(denom, denom, ShuffleComponent.LeftY, ShuffleComponent.LeftX, ShuffleComponent.RightW, ShuffleComponent.RightZ);   // x+y        x+y            z+w            z+w
            denom = denom - shuffle(denom, denom, ShuffleComponent.LeftZ, ShuffleComponent.LeftZ, ShuffleComponent.RightX, ShuffleComponent.RightX);   // x+y-z-w  x+y-z-w        z+w-x-y        z+w-x-y

            double4 rcp_denom_ppnn = double4(1.0) / denom;
            double4x4 res;
            res.c0 = minors0 * rcp_denom_ppnn;

            double4 inner30 = shuffle(inner30_01, inner30_01, ShuffleComponent.LeftX, ShuffleComponent.LeftZ, ShuffleComponent.RightZ, ShuffleComponent.RightX);
            double4 inner01 = shuffle(inner30_01, inner30_01, ShuffleComponent.LeftY, ShuffleComponent.LeftW, ShuffleComponent.RightW, ShuffleComponent.RightY);

            double4 minors1 = r2_wzyx * inner30 - r0_wzyx * inner23 - r3_wzyx * inner02;
            res.c1 = minors1 * rcp_denom_ppnn;

            double4 minors2 = r0_wzyx * inner13 - r1_wzyx * inner30 - r3_wzyx * inner01;
            res.c2 = minors2 * rcp_denom_ppnn;

            double4 minors3 = r1_wzyx * inner02 - r0_wzyx * inner12 + r2_wzyx * inner01;
            res.c3 = minors3 * rcp_denom_ppnn;
            return res;
        }

        /// <summary>Fast matrix inverse for rigid transforms (orthonormal basis and translation)</summary>
        /// <param name="m">Matrix to invert.</param>
        /// <returns>The inverted matrix.</returns>
        public static double4x4 fastinverse(double4x4 m)
        {
            double4 c0 = m.c0;
            double4 c1 = m.c1;
            double4 c2 = m.c2;
            double4 pos = m.c3;

            double4 zero = double4(0);

            double4 t0 = unpacklo(c0, c2);
            double4 t1 = unpacklo(c1, zero);
            double4 t2 = unpackhi(c0, c2);
            double4 t3 = unpackhi(c1, zero);

            double4 r0 = unpacklo(t0, t1);
            double4 r1 = unpackhi(t0, t1);
            double4 r2 = unpacklo(t2, t3);

            pos = -(r0 * pos.x + r1 * pos.y + r2 * pos.z);
            pos.w = 1.0f;

            return double4x4(r0, r1, r2, pos);
        }

        /// <summary>Returns the determinant of a double4x4 matrix.</summary>
        /// <param name="m">Matrix to use when computing determinant.</param>
        /// <returns>The determinant of the matrix.</returns>
        public static double determinant(double4x4 m)
        {
            double4 c0 = m.c0;
            double4 c1 = m.c1;
            double4 c2 = m.c2;
            double4 c3 = m.c3;

            double m00 = c1.y * (c2.z * c3.w - c2.w * c3.z) - c2.y * (c1.z * c3.w - c1.w * c3.z) + c3.y * (c1.z * c2.w - c1.w * c2.z);
            double m01 = c0.y * (c2.z * c3.w - c2.w * c3.z) - c2.y * (c0.z * c3.w - c0.w * c3.z) + c3.y * (c0.z * c2.w - c0.w * c2.z);
            double m02 = c0.y * (c1.z * c3.w - c1.w * c3.z) - c1.y * (c0.z * c3.w - c0.w * c3.z) + c3.y * (c0.z * c1.w - c0.w * c1.z);
            double m03 = c0.y * (c1.z * c2.w - c1.w * c2.z) - c1.y * (c0.z * c2.w - c0.w * c2.z) + c2.y * (c0.z * c1.w - c0.w * c1.z);

            return c0.x * m00 - c1.x * m01 + c2.x * m02 - c3.x * m03;
        }

        /// <summary>Returns a uint hash code of a double4x4 matrix.</summary>
        /// <param name="v">Matrix value to hash.</param>
        /// <returns>uint hash of the argument.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static uint hash(double4x4 v)
        {
            return csum(fold_to_uint(v.c0) * uint4(0x4DDC6509u, 0x7CF083CBu, 0x5C4D6CEDu, 0xF9137117u) +
                        fold_to_uint(v.c1) * uint4(0xE857DCE1u, 0xF62213C5u, 0x9CDAA959u, 0xAA269ABFu) +
                        fold_to_uint(v.c2) * uint4(0xD54BA36Fu, 0xFD0847B9u, 0x8189A683u, 0xB139D651u) +
                        fold_to_uint(v.c3) * uint4(0xE7579997u, 0xEF7D56C7u, 0x66F38F0Bu, 0x624256A3u)) + 0x5292ADE1u;
        }

        /// <summary>
        /// Returns a uint4 vector hash code of a double4x4 matrix.
        /// When multiple elements are to be hashes together, it can more efficient to calculate and combine wide hash
        /// that are only reduced to a narrow uint hash at the very end instead of at every step.
        /// </summary>
        /// <param name="v">Matrix value to hash.</param>
        /// <returns>uint4 hash of the argument.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static uint4 hashwide(double4x4 v)
        {
            return (fold_to_uint(v.c0) * uint4(0xD2E590E5u, 0xF25BE857u, 0x9BC17CE7u, 0xC8B86851u) +
                    fold_to_uint(v.c1) * uint4(0x64095221u, 0xADF428FFu, 0xA3977109u, 0x745ED837u) +
                    fold_to_uint(v.c2) * uint4(0x9CDC88F5u, 0xFA62D721u, 0x7E4DB1CFu, 0x68EEE0F5u) +
                    fold_to_uint(v.c3) * uint4(0xBC3B0A59u, 0x816EFB5Du, 0xA24E82B7u, 0x45A22087u)) + 0xFC104C3Bu;
        }

    }
}
