private void factor() {
        int n = R.numRows();

        // Internal CRS matrix storage
        int[] colind = R.getColumnIndices();
        int[] rowptr = R.getRowPointers();
        double[] data = R.getData();

        // Temporary storage of a dense row
        double[] Rk = new double[n];

        // Find the indices to the diagonal entries
        int[] diagind = findDiagonalIndices(n, colind, rowptr);

        // Go down along the main diagonal
        for (int k = 0; k < n; ++k) {

            // Expand current row to dense storage
            Arrays.fill(Rk, 0);
            for (int i = rowptr[k]; i < rowptr[k + 1]; ++i)
                Rk[colind[i]] = data[i];

            for (int i = 0; i < k; ++i) {

                // Get the current diagonal entry
                double Rii = data[diagind[i]];

                if (Rii == 0)
                    throw new RuntimeException("Zero pivot encountered on row "
                            + (i + 1) + " during ICC process");

                // Elimination factor
                double Rki = Rk[i] / Rii;

                if (Rki == 0)
                    continue;

                // Traverse the sparse row i, reducing on row k
                for (int j = diagind[i] + 1; j < rowptr[i + 1]; ++j)
                    Rk[colind[j]] -= Rki * data[j];
            }

            // Store the row back into the factorisation matrix
            if (Rk[k] == 0)
                throw new RuntimeException(
                        "Zero diagonal entry encountered on row " + (k + 1)
                                + " during ICC process");
            double sqRkk = Math.sqrt(Rk[k]);

            for (int i = diagind[k]; i < rowptr[k + 1]; ++i)
                data[i] = Rk[colind[i]] / sqRkk;
        }

        Rt = new UpperCompRowMatrix(R, diagind);
    }