Add cuDSS as sparse Cholesky solver

cuDSS could be used as an alternative for SuiteSparse and EigenSparse
in case if CUDA capable GPU is available.

Change-Id: I7a567093ce91363478118153e181134ed5804573
diff --git a/internal/ceres/generate_bundle_adjustment_tests.py b/internal/ceres/generate_bundle_adjustment_tests.py
index ac83bc3..0359b40 100644
--- a/internal/ceres/generate_bundle_adjustment_tests.py
+++ b/internal/ceres/generate_bundle_adjustment_tests.py
@@ -53,9 +53,11 @@
     ('SPARSE_NORMAL_CHOLESKY', 'SUITE_SPARSE'),
     ('SPARSE_NORMAL_CHOLESKY', 'EIGEN_SPARSE'),
     ('SPARSE_NORMAL_CHOLESKY', 'ACCELERATE_SPARSE'),
+    ('SPARSE_NORMAL_CHOLESKY', 'CUDA_SPARSE'),
     ('SPARSE_SCHUR',           'SUITE_SPARSE'),
     ('SPARSE_SCHUR',           'EIGEN_SPARSE'),
     ('SPARSE_SCHUR',           'ACCELERATE_SPARSE'),
+    ('SPARSE_SCHUR',           'CUDA_SPARSE')
 ]
 
 ITERATIVE_SOLVER_CONFIGS = [
@@ -66,9 +68,11 @@
     ('ITERATIVE_SCHUR',        'SUITE_SPARSE',     'CLUSTER_JACOBI'),
     ('ITERATIVE_SCHUR',        'EIGEN_SPARSE',     'CLUSTER_JACOBI'),
     ('ITERATIVE_SCHUR',        'ACCELERATE_SPARSE','CLUSTER_JACOBI'),
+    ('ITERATIVE_SCHUR',        'CUDA_SPARSE',      'CLUSTER_JACOBI'),
     ('ITERATIVE_SCHUR',        'SUITE_SPARSE',     'CLUSTER_TRIDIAGONAL'),
     ('ITERATIVE_SCHUR',        'EIGEN_SPARSE',     'CLUSTER_TRIDIAGONAL'),
     ('ITERATIVE_SCHUR',        'ACCELERATE_SPARSE','CLUSTER_TRIDIAGONAL'),
+    ('ITERATIVE_SCHUR',        'CUDA_SPARSE',      'CLUSTER_TRIDIAGONAL'),
 ]
 
 FILENAME_SHORTENING_MAP = dict(
@@ -83,6 +87,7 @@
   SUITE_SPARSE='suitesparse',
   EIGEN_SPARSE='eigensparse',
   ACCELERATE_SPARSE='acceleratesparse',
+  CUDA_SPARSE='cudasparse',
   IDENTITY='identity',
   JACOBI='jacobi',
   SCHUR_JACOBI='schurjacobi',
@@ -217,6 +222,14 @@
   elif sparse_backend == 'EIGEN_SPARSE':
     preprocessor_conditions_begin.append('#ifdef CERES_USE_EIGEN_SPARSE')
     preprocessor_conditions_end.insert(0, '#endif  // CERES_USE_EIGEN_SPARSE')
+  elif sparse_backend == 'CUDA_SPARSE':
+    preprocessor_conditions_begin.append('#ifndef CERES_NO_CUDA')
+    preprocessor_conditions_end.insert(0, '#endif  // CERES_NO_CUDA')
+    if linear_solver == 'SPARSE_SCHUR' or linear_solver == 'SPARSE_NORMAL_CHOLESKY' or (
+            linear_solver == 'ITERATIVE_SCHUR' and (
+            preconditioner == 'CLUSTER_JACOBI' or preconditioner == 'CLUSTER_TRIDIAGONAL')):
+      preprocessor_conditions_begin.append('#ifndef CERES_NO_CUDSS')
+      preprocessor_conditions_end.insert(0, '#endif  // CERES_NO_CUDSS')
 
   if dense_backend == "LAPACK":
     preprocessor_conditions_begin.append('#ifndef CERES_NO_LAPACK')