public static double determinant(double[][] m)
    {
        double res = 1.0;

        /* Row reduce. */
        for (int i = 0; i < m.length; i++)
        {
            /* Find a row with a nonzero entry and swap. */
            for (int j = i; j < m.length; j++)
            {
                if (Math.abs(m[j][i]) > 1e-9)
                {
                    if (i != j)
                    {
                        swapRows(m,i,j);
                        res = -res;
                    }
                    break;
                }
            }

            for (int j = i+1; j < m.length; j++)
                addRow(m, i, j, -m[j][i] / m[i][i]);
        }

        /* Multiply the terms along the diagonal. */
        for(int i = 0; i < m.length; i++)
            res *= m[i][i];

        return res;
    }