/// <summary>
 ///     Assume the following structure, return the determinant coeficients for v0, v1, v2, v3
 ///     v0 v1 v2 v3
 ///     x00 x01 x02 x03
 ///     x10 x11 x12 x13
 ///     x20 x21 x22 x23
 /// </summary>
 /// <param name="matrix"></param>
 /// <returns></returns>
 private static Unity.Mathematics.float4 determinantCoef(Unity.Mathematics.float4x3 matrix)
 {
     Unity.Mathematics.float4 bottomRow = matrix.c2;
     float[] determinants = Determinant2X2(matrix.c0, matrix.c1);
     return(new Unity.Mathematics.float4(
                bottomRow.y * determinants[5] - bottomRow.z * determinants[4] + bottomRow.w * determinants[3],
                -(bottomRow.x * determinants[5] - bottomRow.z * determinants[2] +
                  bottomRow.w * determinants[3]),
                bottomRow.x * determinants[4] - bottomRow.y * determinants[2] + bottomRow.w * determinants[0],
                -(bottomRow.x * determinants[3] - bottomRow.y * determinants[1] + bottomRow.z * determinants[0])
                ));
 }
        /// <summary>
        ///     Return the basis of a hyper plane orthagonal to a given vector
        /// </summary>
        /// <param name="v"></param>
        /// <returns></returns>
        public static Unity.Mathematics.float4x3 basisSystem(this Unity.Mathematics.float4 v)
        {
            Unity.Mathematics.math.normalize(v);
            //use method described here:  https://www.geometrictools.com/Documentation/OrthonormalSets.pdf
            if (v.x == 0 && v.y == 0 && v.z == 0 && v.w == 0)
            {
                UnityEngine.Debug.LogError("Can't form basis from zero vector");
            }

            //the vector is the first basis vector for the 4-space, orthag to the hyperplane
            Unity.Mathematics.math.normalize(v);
            //establish a second basis vector
            Unity.Mathematics.float4 basis0;
            if (v.x != 0 || v.y != 0)
            {
                basis0 = new UnityEngine.Vector4(v.y, v.x, 0, 0);
            }
            else
            {
                basis0 = new UnityEngine.Vector4(0, 0, v.w, v.z);
            }

            Unity.Mathematics.math.normalize(basis0);

            float[] determinants = Determinant2X2(v, basis0);

            //index of largest determinant
            int idx = 0;

            for (int i = 0; i < 6; i++)
            {
                if (determinants[i] > determinants[idx])
                {
                    idx = i;
                }
            }

            if (determinants[idx] != 0)
            {
                UnityEngine.Debug.LogError("No non-zero determinant");
            }

            //choose bottom row of det matrix to generate next basis vector
            Unity.Mathematics.float4 bottomRow;
            if (idx == 0 || idx == 1 || idx == 3)
            {
                bottomRow = new Unity.Mathematics.float4(0, 0, 0, 1);
            }
            else if (idx == 2 || idx == 4)
            {
                bottomRow = new Unity.Mathematics.float4(0, 0, 1, 0);
            }
            else
            {
                bottomRow = new Unity.Mathematics.float4(0, 1, 0, 0);
            }

            Unity.Mathematics.float4 basis1 = determinantCoef(new Unity.Mathematics.float4x3(v, basis0, bottomRow));
            Unity.Mathematics.math.normalize(basis1);

            Unity.Mathematics.float4 basis2 = determinantCoef(new Unity.Mathematics.float4x3(v, basis0, basis1));
            Unity.Mathematics.math.normalize(basis2);

            //returns the basis that spans the hyperplane orthogonal to v
            Unity.Mathematics.float4x3 basis = new Unity.Mathematics.float4x3(basis0, basis1, basis2);
            //check that v is orthogonal.
//            v.projectDownDimension(basis, ProjectionMethod.parallel, null, null, null);
//            if (v.x != 0 || v.y != 0 || v.z != 0) UnityEngine.Debug.LogError("Basis is not orthogonal to v");

            return(basis);
        }