SuiteSparse cleanup.

1. CreateSparseMatrixTransposeView now returns a struct instead
of a pointer.

2. Add AnalyzeCholeskyWithNaturalOrdering.

Change-Id: If27a5502949c3994edd95be0d25ec7a0d1fa1ae1
diff --git a/internal/ceres/sparse_normal_cholesky_solver.cc b/internal/ceres/sparse_normal_cholesky_solver.cc
index aacba86..7ece965 100644
--- a/internal/ceres/sparse_normal_cholesky_solver.cc
+++ b/internal/ceres/sparse_normal_cholesky_solver.cc
@@ -199,9 +199,7 @@
 
   VectorRef(x, num_cols).setZero();
 
-  scoped_ptr<cholmod_sparse> lhs(ss_.CreateSparseMatrixTransposeView(A));
-  CHECK_NOTNULL(lhs.get());
-
+  cholmod_sparse lhs = ss_.CreateSparseMatrixTransposeView(A);
   cholmod_dense* rhs = ss_.CreateDenseVector(Atb.data(), num_cols, num_cols);
   event_logger.AddEvent("Setup");
 
@@ -216,7 +214,7 @@
   }
   event_logger.AddEvent("Analysis");
 
-  cholmod_dense* sol = ss_.SolveCholesky(lhs.get(), factor_, rhs);
+  cholmod_dense* sol = ss_.SolveCholesky(&lhs, factor_, rhs);
   event_logger.AddEvent("Solve");
 
   ss_.Free(rhs);
diff --git a/internal/ceres/suitesparse.cc b/internal/ceres/suitesparse.cc
index 87fae75..9063fa0 100644
--- a/internal/ceres/suitesparse.cc
+++ b/internal/ceres/suitesparse.cc
@@ -87,23 +87,23 @@
   return cholmod_triplet_to_sparse(&triplet, triplet.nnz, &cc_);
 }
 
-cholmod_sparse* SuiteSparse::CreateSparseMatrixTransposeView(
+cholmod_sparse SuiteSparse::CreateSparseMatrixTransposeView(
     CompressedRowSparseMatrix* A) {
-  cholmod_sparse* m = new cholmod_sparse_struct;
-  m->nrow = A->num_cols();
-  m->ncol = A->num_rows();
-  m->nzmax = A->num_nonzeros();
-
-  m->p = reinterpret_cast<void*>(A->mutable_rows());
-  m->i = reinterpret_cast<void*>(A->mutable_cols());
-  m->x = reinterpret_cast<void*>(A->mutable_values());
-
-  m->stype = 0;  // Matrix is not symmetric.
-  m->itype = CHOLMOD_INT;
-  m->xtype = CHOLMOD_REAL;
-  m->dtype = CHOLMOD_DOUBLE;
-  m->sorted = 1;
-  m->packed = 1;
+  cholmod_sparse m;
+  m.nrow = A->num_cols();
+  m.ncol = A->num_rows();
+  m.nzmax = A->num_nonzeros();
+  m.nz = NULL;
+  m.p = reinterpret_cast<void*>(A->mutable_rows());
+  m.i = reinterpret_cast<void*>(A->mutable_cols());
+  m.x = reinterpret_cast<void*>(A->mutable_values());
+  m.z = NULL;
+  m.stype = 0;  // Matrix is not symmetric.
+  m.itype = CHOLMOD_INT;
+  m.xtype = CHOLMOD_REAL;
+  m.dtype = CHOLMOD_DOUBLE;
+  m.sorted = 1;
+  m.packed = 1;
 
   return m;
 }
@@ -172,6 +172,23 @@
   return factor;
 }
 
+cholmod_factor* SuiteSparse::AnalyzeCholeskyWithNaturalOrdering(cholmod_sparse* A) {
+  cc_.nmethods = 1;
+  cc_.method[0].ordering = CHOLMOD_NATURAL;
+  cc_.postorder = 0;
+
+  cholmod_factor* factor  = cholmod_analyze(A, &cc_);
+  CHECK_EQ(cc_.status, CHOLMOD_OK)
+      << "Cholmod symbolic analysis failed " << cc_.status;
+  CHECK_NOTNULL(factor);
+
+  if (VLOG_IS_ON(2)) {
+    cholmod_print_common(const_cast<char*>("Symbolic Analysis"), &cc_);
+  }
+
+  return factor;
+}
+
 bool SuiteSparse::BlockAMDOrdering(const cholmod_sparse* A,
                                    const vector<int>& row_blocks,
                                    const vector<int>& col_blocks,
diff --git a/internal/ceres/suitesparse.h b/internal/ceres/suitesparse.h
index 5a8ef63..131716d 100644
--- a/internal/ceres/suitesparse.h
+++ b/internal/ceres/suitesparse.h
@@ -70,10 +70,8 @@
 
   // Create a cholmod_sparse wrapper around the contents of A. This is
   // a shallow object, which refers to the contents of A and does not
-  // use the SuiteSparse machinery to allocate memory, this object
-  // should be disposed off with a delete and not a call to Free as is
-  // the case for objects returned by CreateSparseMatrixTranspose.
-  cholmod_sparse* CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A);
+  // use the SuiteSparse machinery to allocate memory.
+  cholmod_sparse CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A);
 
   // Given a vector x, build a cholmod_dense vector of size out_size
   // with the first in_size entries copied from x. If x is NULL, then
@@ -135,6 +133,12 @@
   cholmod_factor* AnalyzeCholeskyWithUserOrdering(cholmod_sparse* A,
                                                   const vector<int>& ordering);
 
+  // Perform a symbolic factorization of A without re-ordering A. No
+  // postordering of the elimination tree is performed. This ensures
+  // that the symbolic factor does not introduce an extra permutation
+  // on the matrix. See the documentation for CHOLMOD for more details.
+  cholmod_factor* AnalyzeCholeskyWithNaturalOrdering(cholmod_sparse* A);
+
   // Use the symbolic factorization in L, to find the numerical
   // factorization for the matrix A or AA^T. Return true if
   // successful, false otherwise. L contains the numeric factorization