Beispiel #1
0
        /**
         * <p>
         * Performs the following operation:<br>
         * <br>
         * B = A + &alpha;I
         * <p>
         *
         * @param A A square matrix.  Not modified.
         * @param B A square matrix that the results are saved to.  Modified.
         * @param alpha Scaling factor for the identity matrix.
         */
        public static void addIdentity(FMatrix1Row A, FMatrix1Row B, float alpha)
        {
            if (A.numCols != A.numRows)
            {
                throw new ArgumentException("A must be square");
            }
            if (B.numCols != A.numCols || B.numRows != A.numRows)
            {
                throw new ArgumentException("B must be the same shape as A");
            }

            int n = A.numCols;

            int index = 0;

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++, index++)
                {
                    if (i == j)
                    {
                        B.set(index, A.get(index) + alpha);
                    }
                    else
                    {
                        B.set(index, A.get(index));
                    }
                }
            }
        }
Beispiel #2
0
        /**
         * <p>
         * Element wise p-norm:<br>
         * <br>
         * norm = {&sum;<sub>i=1:m</sub> &sum;<sub>j=1:n</sub> { |a<sub>ij</sub>|<sup>p</sup>}}<sup>1/p</sup>
         * </p>
         *
         * <p>
         * This is not the same as the induced p-norm used on matrices, but is the same as the vector p-norm.
         * </p>
         *
         * @param A Matrix. Not modified.
         * @param p p value.
         * @return The norm's value.
         */
        public static float elementP(FMatrix1Row A, float p)
        {
            if (p == 1)
            {
                return(CommonOps_FDRM.elementSumAbs(A));
            }
            if (p == 2)
            {
                return(normF(A));
            }
            else
            {
                float max = CommonOps_FDRM.elementMaxAbs(A);

                if (max == 0.0f)
                {
                    return(0.0f);
                }

                float total = 0;

                int size = A.getNumElements();

                for (int i = 0; i < size; i++)
                {
                    float a = A.get(i) / max;

                    total += (float)Math.Pow(Math.Abs(a), p);
                }

                return(max * (float)Math.Pow(total, 1.0f / p));
            }
        }
Beispiel #3
0
        /**
         * Takes a matrix and splits it into a set of row or column vectors.
         *
         * @param A original matrix.
         * @param column If true then column vectors will be created.
         * @return Set of vectors.
         */
        public static FMatrixRMaj[] splitIntoVectors(FMatrix1Row A, bool column)
        {
            int w = column ? A.numCols : A.numRows;

            int M = column ? A.numRows : 1;
            int N = column ? 1 : A.numCols;

            int o = Math.Max(M, N);

            FMatrixRMaj[] ret = new FMatrixRMaj[w];

            for (int i = 0; i < w; i++)
            {
                FMatrixRMaj a = new FMatrixRMaj(M, N);

                if (column)
                {
                    subvector(A, 0, i, o, false, 0, a);
                }
                else
                {
                    subvector(A, i, 0, o, true, 0, a);
                }

                ret[i] = a;
            }

            return(ret);
        }
Beispiel #4
0
        /**
         * Performs a transpose across block sub-matrices.  Reduces
         * the number of cache misses on larger matrices.
         *
         * *NOTE* If this is beneficial is highly dependent on the computer it is run on. e.g:
         * - Q6600 Almost twice as fast as standard.
         * - Pentium-M Same speed and some times a bit slower than standard.
         *
         * @param A Original matrix.  Not modified.
         * @param A_tran Transposed matrix.  Modified.
         * @param blockLength Length of a block.
         */
        public static void block(FMatrix1Row A, FMatrix1Row A_tran,
                                 int blockLength)
        {
            for (int i = 0; i < A.numRows; i += blockLength)
            {
                int blockHeight = Math.Min(blockLength, A.numRows - i);

                int indexSrc = i * A.numCols;
                int indexDst = i;

                for (int j = 0; j < A.numCols; j += blockLength)
                {
                    int blockWidth = Math.Min(blockLength, A.numCols - j);

//                int indexSrc = i*A.numCols + j;
//                int indexDst = j*A_tran.numCols + i;

                    int indexSrcEnd = indexSrc + blockWidth;
//                for( int l = 0; l < blockWidth; l++ , indexSrc++ ) {
                    for (; indexSrc < indexSrcEnd; indexSrc++)
                    {
                        int rowSrc = indexSrc;
                        int rowDst = indexDst;
                        int end    = rowDst + blockHeight;
//                    for( int k = 0; k < blockHeight; k++ , rowSrc += A.numCols ) {
                        for (; rowDst < end; rowSrc += A.numCols)
                        {
                            // faster to write in sequence than to read in sequence
                            A_tran.data[rowDst++] = A.data[rowSrc];
                        }
                        indexDst += A_tran.numCols;
                    }
                }
            }
        }
Beispiel #5
0
        public static void inner_small(FMatrix1Row a, FMatrix1Row c)
        {
            for (int i = 0; i < a.numCols; i++)
            {
                for (int j = i; j < a.numCols; j++)
                {
                    int   indexC1 = i * c.numCols + j;
                    int   indexC2 = j * c.numCols + i;
                    int   indexA  = i;
                    int   indexB  = j;
                    float sum     = 0;
                    int   end     = indexA + a.numRows * a.numCols;
                    for (; indexA < end; indexA += a.numCols, indexB += a.numCols)
                    {
                        sum += a.data[indexA] * a.data[indexB];
                    }
                    c.data[indexC1] = c.data[indexC2] = sum;
                }
            }
//        for( int i = 0; i < a.numCols; i++ ) {
//            for( int j = i; j < a.numCols; j++ ) {
//                float sum = 0;
//                for( int k = 0; k < a.numRows; k++ ) {
//                    sum += a.get(k,i)*a.get(k,j);
//                }
//                c.set(i,j,sum);
//                c.set(j,i,sum);
//            }
//        }
        }
        /**
         * <p>
         * Adds to A &isin; &real; <sup>m &times; n</sup> the results of an outer product multiplication
         * of the two vectors.  This is also known as a rank 1 update.<br>
         * <br>
         * A = A + &gamma; x * y<sup>T</sup>
         * where x &isin; &real; <sup>m</sup> and y &isin; &real; <sup>n</sup> are vectors.
         * </p>
         * <p>
         * Which is equivalent to: A<sub>ij</sub> = A<sub>ij</sub> + &gamma; x<sub>i</sub>*y<sub>j</sub>
         * </p>
         *
         * <p>
         * These functions are often used inside of highly optimized code and therefor sanity checks are
         * kept to a minimum.  It is not recommended that any of these functions be used directly.
         * </p>
         *
         * @param gamma A multiplication factor for the outer product.
         * @param x A vector with m elements. Not modified.
         * @param y A vector with n elements. Not modified.
         * @param A A Matrix with m by n elements. Modified.
         */
        public static void addOuterProd(float gamma, FMatrixD1 x, FMatrixD1 y, FMatrix1Row A)
        {
            int m = A.numRows;
            int n = A.numCols;

            int index = 0;

            if (gamma == 1.0f)
            {
                for (int i = 0; i < m; i++)
                {
                    float xdat = x.get(i);
                    for (int j = 0; j < n; j++)
                    {
                        A.plus(index++, xdat * y.get(j));
                    }
                }
            }
            else
            {
                for (int i = 0; i < m; i++)
                {
                    float xdat = x.get(i);
                    for (int j = 0; j < n; j++)
                    {
                        A.plus(index++, gamma * xdat * y.get(j));
                    }
                }
            }
        }
        public static float det4(FMatrix1Row mat)
        {
            float[] data = mat.data;

            float a11 = data[5];
            float a12 = data[6];
            float a13 = data[7];
            float a21 = data[9];
            float a22 = data[10];
            float a23 = data[11];
            float a31 = data[13];
            float a32 = data[14];
            float a33 = data[15];

            float ret = 0;

            ret += data[0] * (+a11 * (a22 * a33 - a23 * a32) - a12 * (a21 * a33 - a23 * a31) +
                              a13 * (a21 * a32 - a22 * a31));
            a11  = data[4];
            a21  = data[8];
            a31  = data[12];
            ret -= data[1] * (+a11 * (a22 * a33 - a23 * a32) - a12 * (a21 * a33 - a23 * a31) +
                              a13 * (a21 * a32 - a22 * a31));
            a12  = data[5];
            a22  = data[9];
            a32  = data[13];
            ret += data[2] * (+a11 * (a22 * a33 - a23 * a32) - a12 * (a21 * a33 - a23 * a31) +
                              a13 * (a21 * a32 - a22 * a31));
            a13  = data[6];
            a23  = data[10];
            a33  = data[14];
            ret -= data[3] * (+a11 * (a22 * a33 - a23 * a32) - a12 * (a21 * a33 - a23 * a31) +
                              a13 * (a21 * a32 - a22 * a31));
            return(ret);
        }
Beispiel #8
0
        public static void outer(FMatrix1Row a, FMatrix1Row c)
        {
            for (int i = 0; i < a.numRows; i++)
            {
                int indexC1 = i * c.numCols + i;
                int indexC2 = indexC1;
                for (int j = i; j < a.numRows; j++, indexC2 += c.numCols)
                {
                    int   indexA = i * a.numCols;
                    int   indexB = j * a.numCols;
                    float sum    = 0;
                    int   end    = indexA + a.numCols;
                    for (; indexA < end; indexA++, indexB++)
                    {
                        sum += a.data[indexA] * a.data[indexB];
                    }
                    c.data[indexC2] = c.data[indexC1++] = sum;
                }
            }
//        for( int i = 0; i < a.numRows; i++ ) {
//            for( int j = 0; j < a.numRows; j++ ) {
//                float sum = 0;
//                for( int k = 0; k < a.numCols; k++ ) {
//                    sum += a.get(i,k)*a.get(j,k);
//                }
//                c.set(i,j,sum);
//            }
//        }
        }
Beispiel #9
0
        public static void invert(LinearSolverDense <FMatrixRMaj> solver, FMatrix1Row A, FMatrixRMaj A_inv)
        {
            if (A.numRows != A_inv.numRows || A.numCols != A_inv.numCols)
            {
                throw new ArgumentException("A and A_inv must have the same dimensions");
            }

            CommonOps_FDRM.setIdentity(A_inv);

            solver.solve(A_inv, A_inv);
        }
Beispiel #10
0
        /**
         * An alternative implementation of {@link #multTransA_small} that performs well on large
         * matrices.  There is a relative performance hit when used on small matrices.
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A Vector that has length m. Not modified.
         * @param C A column vector that has length n. Modified.
         */
        public static void multTransA_reorder(FMatrix1Row A, FMatrixD1 B, FMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numCols)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }
            if (B.numRows == 1)
            {
                if (A.numRows != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numRows != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            if (A.numRows == 0)
            {
                CommonOps_FDRM.fill(C, 0);
                return;
            }

            float B_val = B.get(0);

            for (int i = 0; i < A.numCols; i++)
            {
                C.set(i, A.get(i) * B_val);
            }

            int indexA = A.numCols;

            for (int i = 1; i < A.numRows; i++)
            {
                B_val = B.get(i);
                for (int j = 0; j < A.numCols; j++)
                {
                    C.plus(j, A.get(indexA++) * B_val);
                }
            }
        }
Beispiel #11
0
        /**
         * Computes the product of the diagonal elements.  For a diagonal or triangular
         * matrix this is the determinant.
         *
         * @param T A matrix.
         * @return product of the diagonal elements.
         */
        public static float diagProd(FMatrix1Row T)
        {
            float prod = 1.0f;
            int   N    = Math.Min(T.numRows, T.numCols);

            for (int i = 0; i < N; i++)
            {
                prod *= T.unsafe_get(i, i);
            }

            return(prod);
        }
Beispiel #12
0
        /**
         * <p>
         * Performs a matrix vector multiply.<br>
         * <br>
         * c = A * b <br>
         * and<br>
         * c = A * b<sup>T</sup> <br>
         * <br>
         * c<sub>i</sub> = Sum{ j=1:n, a<sub>ij</sub> * b<sub>j</sub>}<br>
         * <br>
         * where A is a matrix, b is a column or transposed row vector, and c is a column vector.
         * </p>
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A vector that has length n. Not modified.
         * @param C A column vector that has length m. Modified.
         */
        public static void mult(FMatrix1Row A, FMatrixD1 B, FMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numRows)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }

            if (B.numRows == 1)
            {
                if (A.numCols != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numCols != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            if (A.numCols == 0)
            {
                CommonOps_FDRM.fill(C, 0);
                return;
            }

            int   indexA = 0;
            int   cIndex = 0;
            float b0     = B.get(0);

            for (int i = 0; i < A.numRows; i++)
            {
                float total = A.get(indexA++) * b0;

                for (int j = 1; j < A.numCols; j++)
                {
                    total += A.get(indexA++) * B.get(j);
                }

                C.set(cIndex++, total);
            }
        }
Beispiel #13
0
 public static void setSubMatrix(FMatrix1Row src, FMatrix1Row dst,
                                 int srcRow, int srcCol, int dstRow, int dstCol,
                                 int numSubRows, int numSubCols)
 {
     for (int i = 0; i < numSubRows; i++)
     {
         for (int j = 0; j < numSubCols; j++)
         {
             float val = src.get(i + srcRow, j + srcCol);
             dst.set(i + dstRow, j + dstCol, val);
         }
     }
 }
Beispiel #14
0
        /**
         * A straight forward transpose.  Good for small non-square matrices.
         *
         * @param A Original matrix.  Not modified.
         * @param A_tran Transposed matrix.  Modified.
         */
        public static void standard(FMatrix1Row A, FMatrix1Row A_tran)
        {
            int index = 0;

            for (int i = 0; i < A_tran.numRows; i++)
            {
                int index2 = i;

                int end = index + A_tran.numCols;
                while (index < end)
                {
                    A_tran.data[index++] = A.data[index2];
                    index2 += A.numCols;
                }
            }
        }
        /**
         * <p>
         * Sets A &isin; &real; <sup>m &times; n</sup> equal to an outer product multiplication of the two
         * vectors.  This is also known as a rank-1 operation.<br>
         * <br>
         * A = x * y'
         * where x &isin; &real; <sup>m</sup> and y &isin; &real; <sup>n</sup> are vectors.
         * </p>
         * <p>
         * Which is equivalent to: A<sub>ij</sub> = x<sub>i</sub>*y<sub>j</sub>
         * </p>
         *
         * <p>
         * These functions are often used inside of highly optimized code and therefor sanity checks are
         * kept to a minimum.  It is not recommended that any of these functions be used directly.
         * </p>
         *
         * @param x A vector with m elements. Not modified.
         * @param y A vector with n elements. Not modified.
         * @param A A Matrix with m by n elements. Modified.
         */
        public static void outerProd(FMatrixD1 x, FMatrixD1 y, FMatrix1Row A)
        {
            int m = A.numRows;
            int n = A.numCols;

            int index = 0;

            for (int i = 0; i < m; i++)
            {
                float xdat = x.get(i);
                for (int j = 0; j < n; j++)
                {
                    A.set(index++, xdat * y.get(j));
                }
            }
        }
Beispiel #16
0
        /**
         * <p>
         * Creates a reflector from the provided vector.<br>
         * <br>
         * Q = I - &gamma; u u<sup>T</sup><br>
         * &gamma; = 2/||u||<sup>2</sup>
         * </p>
         *
         * <p>
         * In practice {@link VectorVectorMult_FDRM#householder(float, FMatrixD1, FMatrixD1, FMatrixD1)}  multHouseholder}
         * should be used for performance reasons since there is no need to calculate Q explicitly.
         * </p>
         *
         * @param u A vector. Not modified.
         * @return An orthogonal reflector.
         */
        public static FMatrixRMaj createReflector(FMatrix1Row u)
        {
            if (!MatrixFeatures_FDRM.isVector(u))
            {
                throw new ArgumentException("u must be a vector");
            }

            float norm  = NormOps_FDRM.fastNormF(u);
            float gamma = -2.0f / (norm * norm);

            FMatrixRMaj Q = CommonOps_FDRM.identity(u.getNumElements());

            CommonOps_FDRM.multAddTransB(gamma, u, u, Q);

            return(Q);
        }
        public static float det(FMatrix1Row mat)
        {
            switch (mat.numRows)
            {
            case 2: return(det2(mat));

            case 3: return(det3(mat));

            case 4: return(det4(mat));

            case 5: return(det5(mat));

            case 6: return(det6(mat));

            default: throw new ArgumentException("Not supported");
            }
        }
Beispiel #18
0
        /**
         * <p>
         * Performs a matrix vector multiply.<br>
         * <br>
         * C = C + A<sup>T</sup> * B <br>
         * or<br>
         * C = C<sup>T</sup> + A<sup>T</sup> * B<sup>T</sup> <br>
         * <br>
         * c<sub>i</sub> = Sum{ j=1:n, c<sub>i</sub> + a<sub>ji</sub> * b<sub>j</sub>}<br>
         * <br>
         * where A is a matrix, B is a column or transposed row vector, and C is a column vector.
         * </p>
         * <p>
         * This implementation is optimal for small matrices.  There is a huge performance hit when
         * used on large matrices due to CPU cache issues.
         * </p>
         *
         * @param A A matrix that is m by n. Not modified.
         * @param B A vector that has length m. Not modified.
         * @param C A column vector that has length n. Modified.
         */
        public static void multAddTransA_small(FMatrix1Row A, FMatrixD1 B, FMatrixD1 C)
        {
            if (C.numCols != 1)
            {
                throw new MatrixDimensionException("C is not a column vector");
            }
            else if (C.numRows != A.numCols)
            {
                throw new MatrixDimensionException("C is not the expected length");
            }
            if (B.numRows == 1)
            {
                if (A.numRows != B.numCols)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else if (B.numCols == 1)
            {
                if (A.numRows != B.numRows)
                {
                    throw new MatrixDimensionException("A and B are not compatible");
                }
            }
            else
            {
                throw new MatrixDimensionException("B is not a vector");
            }

            int cIndex = 0;

            for (int i = 0; i < A.numCols; i++)
            {
                float total = 0.0f;

                int indexA = i;
                for (int j = 0; j < A.numRows; j++)
                {
                    total  += A.get(indexA) * B.get(j);
                    indexA += A.numCols;
                }

                C.plus(cIndex++, total);
            }
        }
Beispiel #19
0
        public static void inner_reorder(FMatrix1Row a, FMatrix1Row c)
        {
            for (int i = 0; i < a.numCols; i++)
            {
                int   indexC = i * c.numCols + i;
                float valAi  = a.data[i];
                for (int j = i; j < a.numCols; j++)
                {
                    c.data[indexC++] = valAi * a.data[j];
                }

                for (int k = 1; k < a.numRows; k++)
                {
                    indexC = i * c.numCols + i;
                    int indexB = k * a.numCols + i;
                    valAi = a.data[indexB];
                    for (int j = i; j < a.numCols; j++)
                    {
                        c.data[indexC++] += valAi * a.data[indexB++];
                    }
                }

                indexC = i * c.numCols + i;
                int indexC2 = indexC;
                for (int j = i; j < a.numCols; j++, indexC2 += c.numCols)
                {
                    c.data[indexC2] = c.data[indexC++];
                }
            }

//        for( int i = 0; i < a.numCols; i++ ) {
//            for( int j = i; j < a.numCols; j++ ) {
//                c.set(i,j,a.get(0,i)*a.get(0,j));
//            }
//
//            for( int k = 1; k < a.numRows; k++ ) {
//                for( int j = i; j < a.numCols; j++ ) {
//                    c.set(i,j, c.get(i,j)+ a.get(k,i)*a.get(k,j));
//                }
//            }
//            for( int j = i; j < a.numCols; j++ ) {
//                c.set(j,i,c.get(i,j));
//            }
//        }
        }
Beispiel #20
0
        /**
         * In-place transpose for a square matrix.  On most architectures it is faster than the standard transpose
         * algorithm, but on most modern computers it's slower than block transpose.
         *
         * @param mat The matrix that is transposed in-place.  Modified.
         */
        public static void square(FMatrix1Row mat)
        {
            int index    = 1;
            int indexEnd = mat.numCols;

            for (int i = 0;
                 i < mat.numRows;
                 i++, index += i + 1, indexEnd += mat.numCols)
            {
                int indexOther = (i + 1) * mat.numCols + i;
                for (; index < indexEnd; index++, indexOther += mat.numCols)
                {
                    float val = mat.data[index];
                    mat.data[index]      = mat.data[indexOther];
                    mat.data[indexOther] = val;
                }
            }
        }
Beispiel #21
0
 /**
  * <p>
  * Extracts a row or column vector from matrix A.  The first element in the matrix is at element (rowA,colA).
  * The next 'length' elements are extracted along a row or column.  The results are put into vector 'v'
  * start at its element v0.
  * </p>
  *
  * @param A Matrix that the vector is being extracted from.  Not modified.
  * @param rowA Row of the first element that is extracted.
  * @param colA Column of the first element that is extracted.
  * @param length Length of the extracted vector.
  * @param row If true a row vector is extracted, otherwise a column vector is extracted.
  * @param offsetV First element in 'v' where the results are extracted to.
  * @param v Vector where the results are written to. Modified.
  */
 public static void subvector(FMatrix1Row A, int rowA, int colA, int length, bool row, int offsetV,
                              FMatrix1Row v)
 {
     if (row)
     {
         for (int i = 0; i < length; i++)
         {
             v.set(offsetV + i, A.get(rowA, colA + i));
         }
     }
     else
     {
         for (int i = 0; i < length; i++)
         {
             v.set(offsetV + i, A.get(rowA + i, colA));
         }
     }
 }
        private void createMinor(FMatrix1Row mat)
        {
            int w        = minWidth - 1;
            int firstRow = (width - w) * width;

            for (int i = 0; i < numOpen; i++)
            {
                int col      = open[i];
                int srcIndex = firstRow + col;
                int dstIndex = i;

                for (int j = 0; j < w; j++)
                {
                    tempMat.set(dstIndex, mat.get(srcIndex));
                    dstIndex += w;
                    srcIndex += width;
                }
            }
        }
        public static float det3(FMatrix1Row mat)
        {
            float[] m = mat.data;

            float a11 = m[0];
            float a12 = m[1];
            float a13 = m[2];
            float a21 = m[3];
            float a22 = m[4];
            float a23 = m[5];
            float a31 = m[6];
            float a32 = m[7];
            float a33 = m[8];

            float a = a11 * (a22 * a33 - a23 * a32);
            float b = a12 * (a21 * a33 - a23 * a31);
            float c = a13 * (a21 * a32 - a31 * a22);

            return(a - b + c);
        }
Beispiel #24
0
        public static void inner_reorder_upper(FMatrix1Row a, FMatrix1Row c)
        {
            for (int i = 0; i < a.numCols; i++)
            {
                int   indexC = i * c.numCols + i;
                float valAi  = a.data[i];
                for (int j = i; j < a.numCols; j++)
                {
                    c.data[indexC++] = valAi * a.data[j];
                }

                for (int k = 1; k < a.numRows; k++)
                {
                    indexC = i * c.numCols + i;
                    int indexB = k * a.numCols + i;
                    valAi = a.data[indexB];
                    for (int j = i; j < a.numCols; j++)
                    {
                        c.data[indexC++] += valAi * a.data[indexB++];
                    }
                }
            }
        }
        public static float det2(FMatrix1Row mat)
        {
            float[] m = mat.data;

            return(m[0] * m[3] - m[1] * m[2]);
        }
        public static float det5(FMatrix1Row mat)
        {
            float[] data = mat.data;

            float a11 = data[6];
            float a12 = data[7];
            float a13 = data[8];
            float a14 = data[9];
            float a21 = data[11];
            float a22 = data[12];
            float a23 = data[13];
            float a24 = data[14];
            float a31 = data[16];
            float a32 = data[17];
            float a33 = data[18];
            float a34 = data[19];
            float a41 = data[21];
            float a42 = data[22];
            float a43 = data[23];
            float a44 = data[24];

            float ret = 0;

            ret += data[0] *
                   (+a11 * (+a22 * (a33 * a44 - a34 * a43) - a23 * (a32 * a44 - a34 * a42) +
                            a24 * (a32 * a43 - a33 * a42)) -
                    a12 * (+a21 * (a33 * a44 - a34 * a43) - a23 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a43 - a33 * a41)) +
                    a13 * (+a21 * (a32 * a44 - a34 * a42) - a22 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a42 - a32 * a41)) -
                    a14 * (+a21 * (a32 * a43 - a33 * a42) - a22 * (a31 * a43 - a33 * a41) +
                           a23 * (a31 * a42 - a32 * a41)));
            a11  = data[5];
            a21  = data[10];
            a31  = data[15];
            a41  = data[20];
            ret -= data[1] *
                   (+a11 * (+a22 * (a33 * a44 - a34 * a43) - a23 * (a32 * a44 - a34 * a42) +
                            a24 * (a32 * a43 - a33 * a42)) -
                    a12 * (+a21 * (a33 * a44 - a34 * a43) - a23 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a43 - a33 * a41)) +
                    a13 * (+a21 * (a32 * a44 - a34 * a42) - a22 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a42 - a32 * a41)) -
                    a14 * (+a21 * (a32 * a43 - a33 * a42) - a22 * (a31 * a43 - a33 * a41) +
                           a23 * (a31 * a42 - a32 * a41)));
            a12  = data[6];
            a22  = data[11];
            a32  = data[16];
            a42  = data[21];
            ret += data[2] *
                   (+a11 * (+a22 * (a33 * a44 - a34 * a43) - a23 * (a32 * a44 - a34 * a42) +
                            a24 * (a32 * a43 - a33 * a42)) -
                    a12 * (+a21 * (a33 * a44 - a34 * a43) - a23 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a43 - a33 * a41)) +
                    a13 * (+a21 * (a32 * a44 - a34 * a42) - a22 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a42 - a32 * a41)) -
                    a14 * (+a21 * (a32 * a43 - a33 * a42) - a22 * (a31 * a43 - a33 * a41) +
                           a23 * (a31 * a42 - a32 * a41)));
            a13  = data[7];
            a23  = data[12];
            a33  = data[17];
            a43  = data[22];
            ret -= data[3] *
                   (+a11 * (+a22 * (a33 * a44 - a34 * a43) - a23 * (a32 * a44 - a34 * a42) +
                            a24 * (a32 * a43 - a33 * a42)) -
                    a12 * (+a21 * (a33 * a44 - a34 * a43) - a23 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a43 - a33 * a41)) +
                    a13 * (+a21 * (a32 * a44 - a34 * a42) - a22 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a42 - a32 * a41)) -
                    a14 * (+a21 * (a32 * a43 - a33 * a42) - a22 * (a31 * a43 - a33 * a41) +
                           a23 * (a31 * a42 - a32 * a41)));
            a14  = data[8];
            a24  = data[13];
            a34  = data[18];
            a44  = data[23];
            ret += data[4] *
                   (+a11 * (+a22 * (a33 * a44 - a34 * a43) - a23 * (a32 * a44 - a34 * a42) +
                            a24 * (a32 * a43 - a33 * a42)) -
                    a12 * (+a21 * (a33 * a44 - a34 * a43) - a23 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a43 - a33 * a41)) +
                    a13 * (+a21 * (a32 * a44 - a34 * a42) - a22 * (a31 * a44 - a34 * a41) +
                           a24 * (a31 * a42 - a32 * a41)) -
                    a14 * (+a21 * (a32 * a43 - a33 * a42) - a22 * (a31 * a43 - a33 * a41) +
                           a23 * (a31 * a42 - a32 * a41)));
            return(ret);
        }
        /**
         * Computes the determinant for the specified matrix.  It must be square and have
         * the same width and height as what was specified in the constructor.
         *
         * @param mat The matrix whose determinant is to be computed.
         * @return The determinant.
         */
        public float compute(FMatrix1Row mat)
        {
            if (width != mat.numCols || width != mat.numRows)
            {
                throw new InvalidOperationException("Unexpected matrix dimension");
            }

            // make sure everything is in the proper state before it starts
            initStructures();

//        Array.Copy(mat.data,0,minorMatrix[0],0,mat.data.Length);

            int level = 0;

            while (true)
            {
                int levelWidth = width - level;
                int levelIndex = levelIndexes[level];

                if (levelIndex == levelWidth)
                {
                    if (level == 0)
                    {
                        return(levelResults[0]);
                    }
                    int prevLevelIndex = levelIndexes[level - 1]++;

                    float val = mat.get((level - 1) * width + levelRemoved[level - 1]);
                    if (prevLevelIndex % 2 == 0)
                    {
                        levelResults[level - 1] += val * levelResults[level];
                    }
                    else
                    {
                        levelResults[level - 1] -= val * levelResults[level];
                    }

                    putIntoOpen(level - 1);

                    levelResults[level] = 0;
                    levelIndexes[level] = 0;
                    level--;
                }
                else
                {
                    int excluded = openRemove(levelIndex);

                    levelRemoved[level] = excluded;

                    if (levelWidth == minWidth)
                    {
                        createMinor(mat);
                        float subresult = mat.get(level * width + levelRemoved[level]);

                        subresult *= UnrolledDeterminantFromMinor_FDRM.det(tempMat);

                        if (levelIndex % 2 == 0)
                        {
                            levelResults[level] += subresult;
                        }
                        else
                        {
                            levelResults[level] -= subresult;
                        }

                        // put it back into the list
                        putIntoOpen(level);
                        levelIndexes[level]++;
                    }
                    else
                    {
                        level++;
                    }
                }
            }
        }
        public static float det6(FMatrix1Row mat)
        {
            float[] data = mat.data;

            float a11 = data[7];
            float a12 = data[8];
            float a13 = data[9];
            float a14 = data[10];
            float a15 = data[11];
            float a21 = data[13];
            float a22 = data[14];
            float a23 = data[15];
            float a24 = data[16];
            float a25 = data[17];
            float a31 = data[19];
            float a32 = data[20];
            float a33 = data[21];
            float a34 = data[22];
            float a35 = data[23];
            float a41 = data[25];
            float a42 = data[26];
            float a43 = data[27];
            float a44 = data[28];
            float a45 = data[29];
            float a51 = data[31];
            float a52 = data[32];
            float a53 = data[33];
            float a54 = data[34];
            float a55 = data[35];

            float ret = 0;

            ret += data[0] *
                   (
                +a11 *
                (+a22 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a54 - a44 * a52)) +
                 a24 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a53 - a43 * a52)) -
                 a25 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                        a34 * (a42 * a53 - a43 * a52))) -
                a12 *
                (+a21 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) -
                 a25 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51))) +
                a13 *
                (+a21 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a54 - a44 * a52)) -
                 a22 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51))) -
                a14 *
                (+a21 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))) + a15 *
                (+a21 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                         a34 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51)) -
                 a24 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))));
            a11  = data[6];
            a21  = data[12];
            a31  = data[18];
            a41  = data[24];
            a51  = data[30];
            ret -= data[1] *
                   (
                +a11 *
                (+a22 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a54 - a44 * a52)) +
                 a24 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a53 - a43 * a52)) -
                 a25 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                        a34 * (a42 * a53 - a43 * a52))) -
                a12 *
                (+a21 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) -
                 a25 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51))) +
                a13 *
                (+a21 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a54 - a44 * a52)) -
                 a22 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51))) -
                a14 *
                (+a21 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))) + a15 *
                (+a21 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                         a34 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51)) -
                 a24 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))));
            a12  = data[7];
            a22  = data[13];
            a32  = data[19];
            a42  = data[25];
            a52  = data[31];
            ret += data[2] *
                   (
                +a11 *
                (+a22 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a54 - a44 * a52)) +
                 a24 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a53 - a43 * a52)) -
                 a25 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                        a34 * (a42 * a53 - a43 * a52))) -
                a12 *
                (+a21 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) -
                 a25 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51))) +
                a13 *
                (+a21 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a54 - a44 * a52)) -
                 a22 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51))) -
                a14 *
                (+a21 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))) + a15 *
                (+a21 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                         a34 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51)) -
                 a24 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))));
            a13  = data[8];
            a23  = data[14];
            a33  = data[20];
            a43  = data[26];
            a53  = data[32];
            ret -= data[3] *
                   (
                +a11 *
                (+a22 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a54 - a44 * a52)) +
                 a24 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a53 - a43 * a52)) -
                 a25 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                        a34 * (a42 * a53 - a43 * a52))) -
                a12 *
                (+a21 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) -
                 a25 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51))) +
                a13 *
                (+a21 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a54 - a44 * a52)) -
                 a22 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51))) -
                a14 *
                (+a21 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))) + a15 *
                (+a21 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                         a34 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51)) -
                 a24 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))));
            a14  = data[9];
            a24  = data[15];
            a34  = data[21];
            a44  = data[27];
            a54  = data[33];
            ret += data[4] *
                   (
                +a11 *
                (+a22 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a54 - a44 * a52)) +
                 a24 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a53 - a43 * a52)) -
                 a25 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                        a34 * (a42 * a53 - a43 * a52))) -
                a12 *
                (+a21 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) -
                 a25 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51))) +
                a13 *
                (+a21 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a54 - a44 * a52)) -
                 a22 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51))) -
                a14 *
                (+a21 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))) + a15 *
                (+a21 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                         a34 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51)) -
                 a24 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))));
            a15  = data[10];
            a25  = data[16];
            a35  = data[22];
            a45  = data[28];
            a55  = data[34];
            ret -= data[5] *
                   (
                +a11 *
                (+a22 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a54 - a44 * a52)) +
                 a24 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                        a35 * (a42 * a53 - a43 * a52)) -
                 a25 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                        a34 * (a42 * a53 - a43 * a52))) -
                a12 *
                (+a21 * (+a33 * (a44 * a55 - a45 * a54) - a34 * (a43 * a55 - a45 * a53) +
                         a35 * (a43 * a54 - a44 * a53)) -
                 a23 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) -
                 a25 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51))) +
                a13 *
                (+a21 * (+a32 * (a44 * a55 - a45 * a54) - a34 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a54 - a44 * a52)) -
                 a22 * (+a31 * (a44 * a55 - a45 * a54) - a34 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a54 - a44 * a51)) +
                 a24 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51))) -
                a14 *
                (+a21 * (+a32 * (a43 * a55 - a45 * a53) - a33 * (a42 * a55 - a45 * a52) +
                         a35 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a55 - a45 * a53) - a33 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a55 - a45 * a52) - a32 * (a41 * a55 - a45 * a51) +
                        a35 * (a41 * a52 - a42 * a51)) -
                 a25 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))) + a15 *
                (+a21 * (+a32 * (a43 * a54 - a44 * a53) - a33 * (a42 * a54 - a44 * a52) +
                         a34 * (a42 * a53 - a43 * a52)) -
                 a22 * (+a31 * (a43 * a54 - a44 * a53) - a33 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a53 - a43 * a51)) +
                 a23 * (+a31 * (a42 * a54 - a44 * a52) - a32 * (a41 * a54 - a44 * a51) +
                        a34 * (a41 * a52 - a42 * a51)) -
                 a24 * (+a31 * (a42 * a53 - a43 * a52) - a32 * (a41 * a53 - a43 * a51) +
                        a33 * (a41 * a52 - a42 * a51))));
            return(ret);
        }