private void gj_echelonize(final double[][] A) {
		final int n = A.length;
		final int m = A[0].length;
		int i = 0;
		int j = 0;
		while (i < n && j < m) {
			// look for a non-zero entry in col j at or below row i
			int k = i;
			while (k < n && A[k][j] == 0) {
				k++;
			}
			// if such an entry is found at row k
			if (k < n) {
				// if k is not i, then swap row i with row k
				if (k != i) {
					gj_swap(A, i, j);
				}
				// if A[i][j] is not 1, then divide row i by A[i][j]
				if (A[i][j] != 1) {
					gj_divide(A, i, j, m);
				}
				// eliminate all other non-zero entries from col j by
				// subtracting from each
				// row (other than i) an appropriate multiple of row i
				gj_eliminate(A, i, j, n, m);
				i++;
			}
			j++;
		}
	}