ceres/stringprintf -> absl::strings

Replace ceres::String* with their more modern and performant
absl strings library equivalent and delete our string
manipulation library.

Change-Id: Iecbdba9864e0abf329778f81fdc0708f78f7594f
diff --git a/include/ceres/iteration_callback.h b/include/ceres/iteration_callback.h
index 955e2ad..61dd841 100644
--- a/include/ceres/iteration_callback.h
+++ b/include/ceres/iteration_callback.h
@@ -169,16 +169,16 @@
 //       const char* kReportRowFormat =
 //           "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e "
 //           "rho:% 3.2e mu:% 3.2e eta:% 3.2e li:% 3d";
-//       string output = StringPrintf(kReportRowFormat,
-//                                    summary.iteration,
-//                                    summary.cost,
-//                                    summary.cost_change,
-//                                    summary.gradient_max_norm,
-//                                    summary.step_norm,
-//                                    summary.relative_decrease,
-//                                    summary.trust_region_radius,
-//                                    summary.eta,
-//                                    summary.linear_solver_iterations);
+//       string output = absl::StrFormat(kReportRowFormat,
+//                                       summary.iteration,
+//                                       summary.cost,
+//                                       summary.cost_change,
+//                                       summary.gradient_max_norm,
+//                                       summary.step_norm,
+//                                       summary.relative_decrease,
+//                                       summary.trust_region_radius,
+//                                       summary.eta,
+//                                       summary.linear_solver_iterations);
 //       if (log_to_stdout_) {
 //         cout << output << endl;
 //       } else {
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt
index f8adee1..98d74cf 100644
--- a/internal/ceres/CMakeLists.txt
+++ b/internal/ceres/CMakeLists.txt
@@ -35,7 +35,7 @@
 # Make dependency visible to the parent CMakeLists.txt
 set(Threads_DEPENDENCY "find_dependency (Threads)" PARENT_SCOPE)
 list(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES  $<LINK_LIBRARY:WHOLE_ARCHIVE,absl::log_flags>)
-
+list(APPEND CERES_LIBRARY_PRIVATE_DEPENDENCIES absl::strings)
 
 list(APPEND CERES_LIBRARY_PUBLIC_DEPENDENCIES absl::log)
 list(APPEND CERES_LIBRARY_PUBLIC_DEPENDENCIES absl::check)
@@ -216,7 +216,6 @@
     sparse_cholesky.cc
     sparse_matrix.cc
     sparse_normal_cholesky_solver.cc
-    stringprintf.cc
     subset_preconditioner.cc
     suitesparse.cc
     thread_pool.cc
diff --git a/internal/ceres/accelerate_sparse.cc b/internal/ceres/accelerate_sparse.cc
index 753bf98..498a62c 100644
--- a/internal/ceres/accelerate_sparse.cc
+++ b/internal/ceres/accelerate_sparse.cc
@@ -39,10 +39,10 @@
 #include <vector>
 
 #include "absl/log/check.h"
+#include "absl/strings/str_format.h"
 #include "ceres/accelerate_sparse.h"
 #include "ceres/compressed_col_sparse_matrix_utils.h"
 #include "ceres/compressed_row_sparse_matrix.h"
-#include "ceres/stringprintf.h"
 #include "ceres/triplet_sparse_matrix.h"
 
 #define CASESTR(x) \
@@ -226,7 +226,7 @@
         as_.AnalyzeCholesky(ordering_type_, &as_lhs));
 
     if (symbolic_factor_->status != SparseStatusOK) {
-      *message = StringPrintf(
+      *message = absl::StrFormat(
           "Apple Accelerate Failure : Symbolic factorisation failed: %s",
           SparseStatusToString(symbolic_factor_->status));
       FreeSymbolicFactorization();
@@ -243,7 +243,7 @@
     as_.Cholesky(&as_lhs, numeric_factor_.get());
   }
   if (numeric_factor_->status != SparseStatusOK) {
-    *message = StringPrintf(
+    *message = absl::StrFormat(
         "Apple Accelerate Failure : Numeric factorisation failed: %s",
         SparseStatusToString(numeric_factor_->status));
     FreeNumericFactorization();
diff --git a/internal/ceres/array_utils.cc b/internal/ceres/array_utils.cc
index a962f7f..8ff0ba3 100644
--- a/internal/ceres/array_utils.cc
+++ b/internal/ceres/array_utils.cc
@@ -36,7 +36,7 @@
 #include <string>
 #include <vector>
 
-#include "ceres/stringprintf.h"
+#include "absl/strings/str_format.h"
 #include "ceres/types.h"
 
 namespace ceres::internal {
@@ -79,12 +79,12 @@
                          std::string* result) {
   for (int64_t i = 0; i < size; ++i) {
     if (x == nullptr) {
-      StringAppendF(result, "Not Computed  ");
+      absl::StrAppendFormat(result, "Not Computed  ");
     } else {
       if (x[i] == kImpossibleValue) {
-        StringAppendF(result, "Uninitialized ");
+        absl::StrAppendFormat(result, "Uninitialized ");
       } else {
-        StringAppendF(result, "%12g ", x[i]);
+        absl::StrAppendFormat(result, "%12g ", x[i]);
       }
     }
   }
diff --git a/internal/ceres/block_sparse_matrix.cc b/internal/ceres/block_sparse_matrix.cc
index f42c869..e79d62a 100644
--- a/internal/ceres/block_sparse_matrix.cc
+++ b/internal/ceres/block_sparse_matrix.cc
@@ -39,6 +39,7 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/block_structure.h"
 #include "ceres/crs_matrix.h"
 #include "ceres/internal/eigen.h"
@@ -567,11 +568,11 @@
       int jac_pos = cell.position;
       for (int r = 0; r < row_block_size; ++r) {
         for (int c = 0; c < col_block_size; ++c) {
-          fprintf(file,
-                  "% 10d % 10d %17f\n",
-                  row_block_pos + r,
-                  col_block_pos + c,
-                  values_[jac_pos++]);
+          absl::FPrintF(file,
+                        "% 10d % 10d %17f\n",
+                        row_block_pos + r,
+                        col_block_pos + c,
+                        values_[jac_pos++]);
         }
       }
     }
diff --git a/internal/ceres/callbacks.cc b/internal/ceres/callbacks.cc
index 9412431..f5d83ec 100644
--- a/internal/ceres/callbacks.cc
+++ b/internal/ceres/callbacks.cc
@@ -35,8 +35,8 @@
 #include <string>
 
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/program.h"
-#include "ceres/stringprintf.h"
 
 namespace ceres::internal {
 
@@ -83,7 +83,7 @@
     const IterationSummary& summary) {
   std::string output;
   if (minimizer_type == LINE_SEARCH) {
-    output = StringPrintf(
+    output = absl::StrFormat(
         "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e s:% 3.2e e:% 3d it:% 3.2e "
         "tt:% 3.2e",
         summary.iteration,
@@ -100,19 +100,19 @@
     if (summary.iteration == 0) {
       output = "iter      cost      cost_change  |gradient|   |step|    tr_ratio  tr_radius  ls_iter  iter_time  total_time\n";  // NOLINT
     }
-    output += StringPrintf(
+    absl::StrAppendFormat(&output,
         "% 4d % 8e   % 3.2e   % 3.2e  % 3.2e  % 3.2e % 3.2e     % 4d   % 3.2e   % 3.2e",  // NOLINT
-        // clang-format on
-        summary.iteration,
-        summary.cost,
-        summary.cost_change,
-        summary.gradient_max_norm,
-        summary.step_norm,
-        summary.relative_decrease,
-        summary.trust_region_radius,
-        summary.linear_solver_iterations,
-        summary.iteration_time_in_seconds,
-        summary.cumulative_time_in_seconds);
+                          // clang-format on
+                          summary.iteration,
+                          summary.cost,
+                          summary.cost_change,
+                          summary.gradient_max_norm,
+                          summary.step_norm,
+                          summary.relative_decrease,
+                          summary.trust_region_radius,
+                          summary.linear_solver_iterations,
+                          summary.iteration_time_in_seconds,
+                          summary.cumulative_time_in_seconds);
   } else {
     LOG(FATAL) << "Unknown minimizer type.";
   }
diff --git a/internal/ceres/compressed_row_sparse_matrix.cc b/internal/ceres/compressed_row_sparse_matrix.cc
index 2e4d647..b474cca 100644
--- a/internal/ceres/compressed_row_sparse_matrix.cc
+++ b/internal/ceres/compressed_row_sparse_matrix.cc
@@ -39,6 +39,7 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/context_impl.h"
 #include "ceres/crs_matrix.h"
 #include "ceres/internal/export.h"
@@ -532,7 +533,7 @@
   CHECK(file != nullptr);
   for (int r = 0; r < num_rows_; ++r) {
     for (int idx = rows_[r]; idx < rows_[r + 1]; ++idx) {
-      fprintf(file, "% 10d % 10d %17f\n", r, cols_[idx], values_[idx]);
+      absl::FPrintF(file, "% 10d % 10d %17f\n", r, cols_[idx], values_[idx]);
     }
   }
 }
diff --git a/internal/ceres/conjugate_gradients_solver.h b/internal/ceres/conjugate_gradients_solver.h
index fa06f16..ee0919b 100644
--- a/internal/ceres/conjugate_gradients_solver.h
+++ b/internal/ceres/conjugate_gradients_solver.h
@@ -38,13 +38,13 @@
 #include <cstddef>
 #include <utility>
 
+#include "absl/strings/str_format.h"
 #include "ceres/eigen_vector_ops.h"
 #include "ceres/internal/disable_warnings.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/internal/export.h"
 #include "ceres/linear_operator.h"
 #include "ceres/linear_solver.h"
-#include "ceres/stringprintf.h"
 #include "ceres/types.h"
 
 namespace ceres::internal {
@@ -146,7 +146,7 @@
   if (options.min_num_iterations == 0 && norm_r <= tol_r) {
     summary.termination_type = LinearSolverTerminationType::SUCCESS;
     summary.message =
-        StringPrintf("Convergence. |r| = %e <= %e.", norm_r, tol_r);
+        absl::StrFormat("Convergence. |r| = %e <= %e.", norm_r, tol_r);
     return summary;
   }
 
@@ -166,7 +166,8 @@
     rho = Dot(r, z, options.context, options.num_threads);
     if (IsZeroOrInfinity(rho)) {
       summary.termination_type = LinearSolverTerminationType::FAILURE;
-      summary.message = StringPrintf("Numerical failure. rho = r'z = %e.", rho);
+      summary.message =
+          absl::StrFormat("Numerical failure. rho = r'z = %e.", rho);
       break;
     }
 
@@ -176,7 +177,7 @@
       const double beta = rho / last_rho;
       if (IsZeroOrInfinity(beta)) {
         summary.termination_type = LinearSolverTerminationType::FAILURE;
-        summary.message = StringPrintf(
+        summary.message = absl::StrFormat(
             "Numerical failure. beta = rho_n / rho_{n-1} = %e, "
             "rho_n = %e, rho_{n-1} = %e",
             beta,
@@ -194,7 +195,7 @@
     const double pq = Dot(p, q, options.context, options.num_threads);
     if ((pq <= 0) || std::isinf(pq)) {
       summary.termination_type = LinearSolverTerminationType::NO_CONVERGENCE;
-      summary.message = StringPrintf(
+      summary.message = absl::StrFormat(
           "Matrix is indefinite, no more progress can be made. "
           "p'q = %e. |p| = %e, |q| = %e",
           pq,
@@ -206,7 +207,7 @@
     const double alpha = rho / pq;
     if (std::isinf(alpha)) {
       summary.termination_type = LinearSolverTerminationType::FAILURE;
-      summary.message = StringPrintf(
+      summary.message = absl::StrFormat(
           "Numerical failure. alpha = rho / pq = %e, rho = %e, pq = %e.",
           alpha,
           rho,
@@ -273,11 +274,11 @@
         summary.num_iterations >= options.min_num_iterations) {
       summary.termination_type = LinearSolverTerminationType::SUCCESS;
       summary.message =
-          StringPrintf("Iteration: %d Convergence: zeta = %e < %e. |r| = %e",
-                       summary.num_iterations,
-                       zeta,
-                       options.q_tolerance,
-                       Norm(r, options.context, options.num_threads));
+          absl::StrFormat("Iteration: %d Convergence: zeta = %e < %e. |r| = %e",
+                          summary.num_iterations,
+                          zeta,
+                          options.q_tolerance,
+                          Norm(r, options.context, options.num_threads));
       break;
     }
     Q0 = Q1;
@@ -288,10 +289,10 @@
         summary.num_iterations >= options.min_num_iterations) {
       summary.termination_type = LinearSolverTerminationType::SUCCESS;
       summary.message =
-          StringPrintf("Iteration: %d Convergence. |r| = %e <= %e.",
-                       summary.num_iterations,
-                       norm_r,
-                       tol_r);
+          absl::StrFormat("Iteration: %d Convergence. |r| = %e <= %e.",
+                          summary.num_iterations,
+                          norm_r,
+                          tol_r);
       break;
     }
 
diff --git a/internal/ceres/context_impl.cc b/internal/ceres/context_impl.cc
index fac3281..be4aa29 100644
--- a/internal/ceres/context_impl.cc
+++ b/internal/ceres/context_impl.cc
@@ -34,8 +34,8 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/internal/config.h"
-#include "ceres/stringprintf.h"
 #include "ceres/wall_time.h"
 
 #ifndef CERES_NO_CUDA
@@ -78,7 +78,7 @@
 }
 
 std::string ContextImpl::CudaConfigAsString() const {
-  return ceres::internal::StringPrintf(
+  return absl::StrFormat(
       "======================= CUDA Device Properties ======================\n"
       "Cuda version              : %d.%d\n"
       "Device ID                 : %d\n"
diff --git a/internal/ceres/coordinate_descent_minimizer.cc b/internal/ceres/coordinate_descent_minimizer.cc
index 37cd04c..556d3aa 100644
--- a/internal/ceres/coordinate_descent_minimizer.cc
+++ b/internal/ceres/coordinate_descent_minimizer.cc
@@ -40,6 +40,7 @@
 #include <vector>
 
 #include "absl/log/check.h"
+#include "absl/strings/str_format.h"
 #include "ceres/evaluator.h"
 #include "ceres/linear_solver.h"
 #include "ceres/minimizer.h"
@@ -249,7 +250,7 @@
   // Verify that each group is an independent set
   for (const auto& g_t_e : group_to_elements) {
     if (!program.IsParameterBlockSetIndependent(g_t_e.second)) {
-      *message = StringPrintf(
+      *message = absl::StrFormat(
           "The user-provided parameter_blocks_for_inner_iterations does not "
           "form an independent set. Group Id: %d",
           g_t_e.first);
diff --git a/internal/ceres/dense_cholesky.cc b/internal/ceres/dense_cholesky.cc
index a5edec8..631cfbb 100644
--- a/internal/ceres/dense_cholesky.cc
+++ b/internal/ceres/dense_cholesky.cc
@@ -38,9 +38,9 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/internal/config.h"
 #include "ceres/iterative_refiner.h"
-#include "ceres/stringprintf.h"
 
 #ifndef CERES_NO_CUDA
 #include "ceres/context_impl.h"
@@ -223,7 +223,7 @@
                << "Argument: " << -info << " is invalid.";
   } else if (info > 0) {
     termination_type_ = LinearSolverTerminationType::FAILURE;
-    *message = StringPrintf(
+    *message = absl::StrFormat(
         "LAPACK::dpotrf numerical failure. "
         "The leading minor of order %d is not positive definite.",
         info);
@@ -276,7 +276,7 @@
                << "Argument: " << -info << " is invalid.";
   } else if (info > 0) {
     termination_type_ = LinearSolverTerminationType::FAILURE;
-    *message = StringPrintf(
+    *message = absl::StrFormat(
         "LAPACK::spotrf numerical failure. "
         "The leading minor of order %d is not positive definite.",
         info);
@@ -398,7 +398,7 @@
     // pedantic, since the compiler does not know that.
     return LinearSolverTerminationType::FATAL_ERROR;
   } else if (error > 0) {
-    *message = StringPrintf(
+    *message = absl::StrFormat(
         "cuSolverDN::cusolverDnDpotrf numerical failure. "
         "The leading minor of order %d is not positive definite.",
         error);
@@ -502,7 +502,7 @@
     return LinearSolverTerminationType::FATAL_ERROR;
   }
   if (error > 0) {
-    *message = StringPrintf(
+    *message = absl::StrFormat(
         "cuSolverDN::cusolverDnSpotrf numerical failure. "
         "The leading minor of order %d is not positive definite.",
         error);
diff --git a/internal/ceres/dense_sparse_matrix.cc b/internal/ceres/dense_sparse_matrix.cc
index c33aa45..fda2b24 100644
--- a/internal/ceres/dense_sparse_matrix.cc
+++ b/internal/ceres/dense_sparse_matrix.cc
@@ -34,6 +34,7 @@
 #include <utility>
 
 #include "absl/log/check.h"
+#include "absl/strings/str_format.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/internal/export.h"
 #include "ceres/triplet_sparse_matrix.h"
@@ -108,7 +109,7 @@
   CHECK(file != nullptr);
   for (int r = 0; r < m_.rows(); ++r) {
     for (int c = 0; c < m_.cols(); ++c) {
-      fprintf(file, "% 10d % 10d %17f\n", r, c, m_(r, c));
+      absl::FPrintF(file, "% 10d % 10d %17f\n", r, c, m_(r, c));
     }
   }
 }
diff --git a/internal/ceres/evaluator_test.cc b/internal/ceres/evaluator_test.cc
index 8987d0b..69cea4f 100644
--- a/internal/ceres/evaluator_test.cc
+++ b/internal/ceres/evaluator_test.cc
@@ -38,6 +38,7 @@
 #include <vector>
 
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/casts.h"
 #include "ceres/cost_function.h"
 #include "ceres/crs_matrix.h"
@@ -48,7 +49,6 @@
 #include "ceres/program.h"
 #include "ceres/sized_cost_function.h"
 #include "ceres/sparse_matrix.h"
-#include "ceres/stringprintf.h"
 #include "ceres/types.h"
 #include "gtest/gtest.h"
 
@@ -122,17 +122,15 @@
     program->SetParameterOffsetsAndIndex();
 
     if (VLOG_IS_ON(1)) {
-      std::string report;
-      StringAppendF(&report,
-                    "Creating evaluator with type: %d",
-                    GetParam().linear_solver_type);
+      std::string report = absl::StrFormat("Creating evaluator with type: %d",
+                                           GetParam().linear_solver_type);
       if (GetParam().linear_solver_type == SPARSE_NORMAL_CHOLESKY) {
-        StringAppendF(
+        absl::StrAppendFormat(
             &report, ", dynamic_sparsity: %d", GetParam().dynamic_sparsity);
       }
-      StringAppendF(&report,
-                    " and num_eliminate_blocks: %d",
-                    GetParam().num_eliminate_blocks);
+      absl::StrAppendFormat(&report,
+                            " and num_eliminate_blocks: %d",
+                            GetParam().num_eliminate_blocks);
       VLOG(1) << report;
     }
     Evaluator::Options options;
diff --git a/internal/ceres/function_sample.cc b/internal/ceres/function_sample.cc
index bb4bcff..9770b11 100644
--- a/internal/ceres/function_sample.cc
+++ b/internal/ceres/function_sample.cc
@@ -30,7 +30,7 @@
 
 #include "ceres/function_sample.h"
 
-#include "ceres/stringprintf.h"
+#include "absl/strings/str_format.h"
 
 namespace ceres::internal {
 
@@ -64,7 +64,7 @@
       gradient_is_valid(true) {}
 
 std::string FunctionSample::ToDebugString() const {
-  return StringPrintf(
+  return absl::StrFormat(
       "[x: %.8e, value: %.8e, gradient: %.8e, "
       "value_is_valid: %d, gradient_is_valid: %d]",
       x,
diff --git a/internal/ceres/gradient_checker.cc b/internal/ceres/gradient_checker.cc
index 16eef1b..dffbba2 100644
--- a/internal/ceres/gradient_checker.cc
+++ b/internal/ceres/gradient_checker.cc
@@ -41,15 +41,14 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 #include "ceres/is_close.h"
-#include "ceres/stringprintf.h"
 #include "ceres/types.h"
 
 namespace ceres {
 
 using internal::IsClose;
-using internal::StringAppendF;
-using internal::StringPrintf;
 
 namespace {
 // Evaluate the cost function and transform the returned Jacobians to
@@ -187,9 +186,9 @@
                             &finite_diff_residuals,
                             &numeric_jacobians,
                             &local_numeric_jacobians)) {
-    results->error_log +=
-        "\nFunction evaluation with numerical "
-        "differentiation failed.";
+    absl::StrAppend(&results->error_log,
+                    "\nFunction evaluation with numerical "
+                    "differentiation failed.");
     results->return_value = false;
   }
 
@@ -221,17 +220,18 @@
   // output if there are no bad jacobian components.
   std::string error_log;
   for (int k = 0; k < function_->parameter_block_sizes().size(); k++) {
-    StringAppendF(&error_log,
-                  "========== "
-                  "Jacobian for block %d: (%ld by %ld)) "
-                  "==========\n",
-                  k,
-                  static_cast<long>(local_jacobians[k].rows()),
-                  static_cast<long>(local_jacobians[k].cols()));
+    absl::StrAppendFormat(&error_log,
+                          "========== "
+                          "Jacobian for block %d: (%ld by %ld)) "
+                          "==========\n",
+                          k,
+                          static_cast<long>(local_jacobians[k].rows()),
+                          static_cast<long>(local_jacobians[k].cols()));
     // The funny spacing creates appropriately aligned column headers.
-    error_log +=
+    absl::StrAppend(
+        &error_log,
         " block  row  col        user dx/dy    num diff dx/dy         "
-        "abs error    relative error         parameter          residual\n";
+        "abs error    relative error         parameter          residual\n");
 
     for (int i = 0; i < local_jacobians[k].rows(); i++) {
       for (int j = 0; j < local_jacobians[k].cols(); j++) {
@@ -245,40 +245,42 @@
                                            &absolute_error);
         worst_relative_error = std::max(worst_relative_error, relative_error);
 
-        StringAppendF(&error_log,
-                      "%6d %4d %4d %17g %17g %17g %17g %17g %17g",
-                      k,
-                      i,
-                      j,
-                      term_jacobian,
-                      finite_jacobian,
-                      absolute_error,
-                      relative_error,
-                      parameters[k][j],
-                      results->residuals[i]);
+        absl::StrAppendFormat(&error_log,
+                              "%6d %4d %4d %17g %17g %17g %17g %17g %17g",
+                              k,
+                              i,
+                              j,
+                              term_jacobian,
+                              finite_jacobian,
+                              absolute_error,
+                              relative_error,
+                              parameters[k][j],
+                              results->residuals[i]);
 
         if (bad_jacobian_entry) {
           num_bad_jacobian_components++;
-          StringAppendF(&error_log,
-                        " ------ (%d,%d,%d) Relative error worse than %g",
-                        k,
-                        i,
-                        j,
-                        relative_precision);
+          absl::StrAppendFormat(
+              &error_log,
+              " ------ (%d,%d,%d) Relative error worse than %g",
+              k,
+              i,
+              j,
+              relative_precision);
         }
-        error_log += "\n";
+        absl::StrAppend(&error_log, "\n");
       }
     }
   }
 
   // Since there were some bad errors, dump comprehensive debug info.
   if (num_bad_jacobian_components) {
-    std::string header = StringPrintf(
+    std::string header = absl::StrFormat(
         "\nDetected %d bad Jacobian component(s). "
         "Worst relative error was %g.\n",
         num_bad_jacobian_components,
         worst_relative_error);
-    results->error_log = header + "\n" + error_log;
+
+    results->error_log = absl::StrCat(header, "\n", error_log);
     return false;
   }
   return true;
diff --git a/internal/ceres/gradient_checking_cost_function.cc b/internal/ceres/gradient_checking_cost_function.cc
index 50a6447..3d206cc 100644
--- a/internal/ceres/gradient_checking_cost_function.cc
+++ b/internal/ceres/gradient_checking_cost_function.cc
@@ -42,6 +42,8 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 #include "ceres/dynamic_numeric_diff_cost_function.h"
 #include "ceres/gradient_checker.h"
 #include "ceres/internal/eigen.h"
@@ -50,7 +52,6 @@
 #include "ceres/problem_impl.h"
 #include "ceres/program.h"
 #include "ceres/residual_block.h"
-#include "ceres/stringprintf.h"
 #include "ceres/types.h"
 
 namespace ceres::internal {
@@ -111,9 +112,11 @@
     }
 
     if (!okay) {
-      std::string error_log =
-          "Gradient Error detected!\nExtra info for this residual: " +
-          extra_info_ + "\n" + results.error_log;
+      std::string error_log = absl::StrCat(
+          "Gradient Error detected!\nExtra info for this residual: ",
+          extra_info_,
+          "\n",
+          results.error_log);
       callback_->SetGradientErrorDetected(error_log);
     }
     return true;
@@ -145,7 +148,7 @@
     std::string& error_log) {
   std::lock_guard<std::mutex> l(mutex_);
   gradient_error_detected_ = true;
-  error_log_ += "\n" + error_log;
+  absl::StrAppend(&error_log_, "\n", error_log);
 }
 
 std::unique_ptr<CostFunction> CreateGradientCheckingCostFunction(
@@ -231,7 +234,7 @@
     // ResidualBlock. This is used by the GradientCheckingCostFunction
     // when logging debugging information.
     std::string extra_info =
-        StringPrintf("Residual block id %d; depends on parameters [", i);
+        absl::StrFormat("Residual block id %d; depends on parameters [", i);
     std::vector<double*> parameter_blocks;
     std::vector<const Manifold*> manifolds;
     parameter_blocks.reserve(residual_block->NumParameterBlocks());
@@ -239,8 +242,11 @@
     for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) {
       ParameterBlock* parameter_block = residual_block->parameter_blocks()[j];
       parameter_blocks.push_back(parameter_block->mutable_user_state());
-      StringAppendF(&extra_info, "%p", parameter_block->mutable_user_state());
-      extra_info += (j < residual_block->NumParameterBlocks() - 1) ? ", " : "]";
+      absl::StrAppendFormat(
+          &extra_info, "%p", parameter_block->mutable_user_state());
+      absl::StrAppend(
+          &extra_info,
+          (j < residual_block->NumParameterBlocks() - 1) ? ", " : "]");
       manifolds.push_back(
           problem_impl->GetManifold(parameter_block->mutable_user_state()));
     }
diff --git a/internal/ceres/gradient_problem_solver.cc b/internal/ceres/gradient_problem_solver.cc
index 9275547..535f4c2 100644
--- a/internal/ceres/gradient_problem_solver.cc
+++ b/internal/ceres/gradient_problem_solver.cc
@@ -36,6 +36,8 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 #include "ceres/callbacks.h"
 #include "ceres/gradient_problem.h"
 #include "ceres/gradient_problem_evaluator.h"
@@ -45,14 +47,10 @@
 #include "ceres/minimizer.h"
 #include "ceres/solver.h"
 #include "ceres/solver_utils.h"
-#include "ceres/stringprintf.h"
 #include "ceres/types.h"
 #include "ceres/wall_time.h"
 
 namespace ceres {
-using internal::StringAppendF;
-using internal::StringPrintf;
-
 namespace {
 
 Solver::Options GradientProblemSolverOptionsToSolverOptions(
@@ -207,7 +205,7 @@
 }
 
 std::string GradientProblemSolver::Summary::BriefReport() const {
-  return StringPrintf(
+  return absl::StrFormat(
       "Ceres GradientProblemSolver Report: "
       "Iterations: %d, "
       "Initial cost: %e, "
@@ -220,21 +218,19 @@
 }
 
 std::string GradientProblemSolver::Summary::FullReport() const {
-  using internal::VersionString;
-
-  // NOTE operator+ is not usable for concatenating a string and a string_view.
   std::string report =
-      std::string{"\nSolver Summary (v "}.append(VersionString()) + ")\n\n";
+      absl::StrCat("\nSolver Summary (v ", internal::VersionString(), ")\n\n");
 
-  StringAppendF(&report, "Parameters          % 25d\n", num_parameters);
+  absl::StrAppendFormat(&report, "Parameters          % 25d\n", num_parameters);
   if (num_tangent_parameters != num_parameters) {
-    StringAppendF(
+    absl::StrAppendFormat(
         &report, "Tangent parameters   % 25d\n", num_tangent_parameters);
   }
 
   std::string line_search_direction_string;
   if (line_search_direction_type == LBFGS) {
-    line_search_direction_string = StringPrintf("LBFGS (%d)", max_lbfgs_rank);
+    line_search_direction_string =
+        absl::StrFormat("LBFGS (%d)", max_lbfgs_rank);
   } else if (line_search_direction_type == NONLINEAR_CONJUGATE_GRADIENT) {
     line_search_direction_string = NonlinearConjugateGradientTypeToString(
         nonlinear_conjugate_gradient_type);
@@ -243,49 +239,49 @@
         LineSearchDirectionTypeToString(line_search_direction_type);
   }
 
-  StringAppendF(&report,
-                "Line search direction     %19s\n",
-                line_search_direction_string.c_str());
+  absl::StrAppendFormat(&report,
+                        "Line search direction     %19s\n",
+                        line_search_direction_string);
 
-  const std::string line_search_type_string = StringPrintf(
+  const std::string line_search_type_string = absl::StrFormat(
       "%s %s",
       LineSearchInterpolationTypeToString(line_search_interpolation_type),
       LineSearchTypeToString(line_search_type));
-  StringAppendF(&report,
-                "Line search type          %19s\n",
-                line_search_type_string.c_str());
-  StringAppendF(&report, "\n");
+  absl::StrAppendFormat(
+      &report, "Line search type          %19s\n", line_search_type_string);
+  absl::StrAppendFormat(&report, "\n");
 
-  StringAppendF(&report, "\nCost:\n");
-  StringAppendF(&report, "Initial        % 30e\n", initial_cost);
+  absl::StrAppendFormat(&report, "\nCost:\n");
+  absl::StrAppendFormat(&report, "Initial        % 30e\n", initial_cost);
   if (termination_type != FAILURE && termination_type != USER_FAILURE) {
-    StringAppendF(&report, "Final          % 30e\n", final_cost);
-    StringAppendF(&report, "Change         % 30e\n", initial_cost - final_cost);
+    absl::StrAppendFormat(&report, "Final          % 30e\n", final_cost);
+    absl::StrAppendFormat(
+        &report, "Change         % 30e\n", initial_cost - final_cost);
   }
 
-  StringAppendF(&report,
-                "\nMinimizer iterations         % 16d\n",
-                static_cast<int>(iterations.size()));
+  absl::StrAppendFormat(&report,
+                        "\nMinimizer iterations         % 16d\n",
+                        static_cast<int>(iterations.size()));
 
-  StringAppendF(&report, "\nTime (in seconds):\n");
-  StringAppendF(&report,
-                "\n  Cost evaluation     %23.6f (%d)\n",
-                cost_evaluation_time_in_seconds,
-                num_cost_evaluations);
-  StringAppendF(&report,
-                "  Gradient & cost evaluation %16.6f (%d)\n",
-                gradient_evaluation_time_in_seconds,
-                num_gradient_evaluations);
-  StringAppendF(&report,
-                "  Polynomial minimization   %17.6f\n",
-                line_search_polynomial_minimization_time_in_seconds);
-  StringAppendF(
+  absl::StrAppendFormat(&report, "\nTime (in seconds):\n");
+  absl::StrAppendFormat(&report,
+                        "\n  Cost evaluation     %23.6f (%d)\n",
+                        cost_evaluation_time_in_seconds,
+                        num_cost_evaluations);
+  absl::StrAppendFormat(&report,
+                        "  Gradient & cost evaluation %16.6f (%d)\n",
+                        gradient_evaluation_time_in_seconds,
+                        num_gradient_evaluations);
+  absl::StrAppendFormat(&report,
+                        "  Polynomial minimization   %17.6f\n",
+                        line_search_polynomial_minimization_time_in_seconds);
+  absl::StrAppendFormat(
       &report, "Total               %25.6f\n\n", total_time_in_seconds);
 
-  StringAppendF(&report,
-                "Termination:        %25s (%s)\n",
-                TerminationTypeToString(termination_type),
-                message.c_str());
+  absl::StrAppendFormat(&report,
+                        "Termination:        %25s (%s)\n",
+                        TerminationTypeToString(termination_type),
+                        message);
   return report;
 }
 
diff --git a/internal/ceres/jet_test.cc b/internal/ceres/jet_test.cc
index f94f995..a9de40f 100644
--- a/internal/ceres/jet_test.cc
+++ b/internal/ceres/jet_test.cc
@@ -36,7 +36,6 @@
 #include <cmath>
 
 #include "absl/log/log.h"
-#include "ceres/stringprintf.h"
 #include "ceres/test_util.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
diff --git a/internal/ceres/line_search.cc b/internal/ceres/line_search.cc
index fd33328..644e26e 100644
--- a/internal/ceres/line_search.cc
+++ b/internal/ceres/line_search.cc
@@ -41,12 +41,13 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 #include "ceres/evaluator.h"
 #include "ceres/function_sample.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/map_util.h"
 #include "ceres/polynomial.h"
-#include "ceres/stringprintf.h"
 #include "ceres/wall_time.h"
 
 namespace ceres::internal {
@@ -79,9 +80,9 @@
     case ceres::WOLFE:
       return std::make_unique<WolfeLineSearch>(options);
     default:
-      *error = std::string("Invalid line search algorithm type: ") +
-               LineSearchTypeToString(line_search_type) +
-               std::string(", unable to create line search.");
+      *error = absl::StrCat("Invalid line search algorithm type: ",
+                            LineSearchTypeToString(line_search_type),
+                            ", unable to create line search.");
   }
   return nullptr;
 }
@@ -317,7 +318,7 @@
     // point is not large enough to satisfy the sufficient decrease condition.
     ++summary->num_iterations;
     if (summary->num_iterations >= options().max_num_iterations) {
-      summary->error = StringPrintf(
+      summary->error = absl::StrFormat(
           "Line search failed: Armijo failed to find a point "
           "satisfying the sufficient decrease condition within "
           "specified max_num_iterations: %d.",
@@ -340,7 +341,7 @@
         (WallTimeInSeconds() - polynomial_minimization_start_time);
 
     if (step_size * descent_direction_max_norm < options().min_step_size) {
-      summary->error = StringPrintf(
+      summary->error = absl::StrFormat(
           "Line search failed: step_size too small: %.5e "
           "with descent_direction_max_norm: %.5e.",
           step_size,
@@ -604,7 +605,7 @@
       // Check num iterations bound here so that we always evaluate the
       // max_num_iterations-th iteration against all conditions, and
       // then perform no additional (unused) evaluations.
-      summary->error = StringPrintf(
+      summary->error = absl::StrFormat(
           "Line search failed: Wolfe bracketing phase failed to "
           "find a point satisfying strong Wolfe conditions, or a "
           "bracket containing such a point within specified "
@@ -660,7 +661,7 @@
     summary->polynomial_minimization_time_in_seconds +=
         (WallTimeInSeconds() - polynomial_minimization_start_time);
     if (step_size * descent_direction_max_norm < options().min_step_size) {
-      summary->error = StringPrintf(
+      summary->error = absl::StrFormat(
           "Line search failed: step_size too small: %.5e "
           "with descent_direction_max_norm: %.5e",
           step_size,
@@ -736,7 +737,7 @@
     // returns inconsistent gradient values relative to the function values,
     // we do not CHECK_LT(), but we do stop processing and return an invalid
     // value.
-    summary->error = StringPrintf(
+    summary->error = absl::StrFormat(
         "Line search failed: Wolfe zoom phase passed a bracket "
         "which does not satisfy: bracket_low.gradient * "
         "(bracket_high.x - bracket_low.x) < 0 [%.8e !< 0] "
@@ -744,9 +745,9 @@
         " %s, the most likely cause of which is the cost function "
         "returning inconsistent gradient & function values.",
         bracket_low.gradient * (bracket_high.x - bracket_low.x),
-        initial_position.ToDebugString().c_str(),
-        bracket_low.ToDebugString().c_str(),
-        bracket_high.ToDebugString().c_str());
+        initial_position.ToDebugString(),
+        bracket_low.ToDebugString(),
+        bracket_high.ToDebugString());
     if (!options().is_silent) {
       LOG(WARNING) << summary->error;
     }
@@ -763,7 +764,7 @@
     // not satisfy the Wolfe condition.
     *solution = bracket_low;
     if (summary->num_iterations >= options().max_num_iterations) {
-      summary->error = StringPrintf(
+      summary->error = absl::StrFormat(
           "Line search failed: Wolfe zoom phase failed to "
           "find a point satisfying strong Wolfe conditions "
           "within specified max_num_iterations: %d, "
@@ -779,7 +780,7 @@
         options().min_step_size) {
       // Bracket width has been reduced below tolerance, and no point satisfying
       // the strong Wolfe conditions has been found.
-      summary->error = StringPrintf(
+      summary->error = absl::StrFormat(
           "Line search failed: Wolfe zoom bracket width: %.5e "
           "too small with descent_direction_max_norm: %.5e.",
           fabs(bracket_high.x - bracket_low.x),
@@ -830,7 +831,7 @@
     const bool kEvaluateGradient = true;
     function->Evaluate(step_size, kEvaluateGradient, solution);
     if (!solution->value_is_valid || !solution->gradient_is_valid) {
-      summary->error = StringPrintf(
+      summary->error = absl::StrFormat(
           "Line search failed: Wolfe Zoom phase found "
           "step_size: %.5e, for which function is invalid, "
           "between low_step: %.5e and high_step: %.5e "
diff --git a/internal/ceres/line_search_minimizer.cc b/internal/ceres/line_search_minimizer.cc
index 41ca31a..97e5f3c 100644
--- a/internal/ceres/line_search_minimizer.cc
+++ b/internal/ceres/line_search_minimizer.cc
@@ -50,13 +50,13 @@
 #include "Eigen/Dense"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/array_utils.h"
 #include "ceres/evaluator.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/internal/export.h"
 #include "ceres/line_search.h"
 #include "ceres/line_search_direction.h"
-#include "ceres/stringprintf.h"
 #include "ceres/types.h"
 #include "ceres/wall_time.h"
 
@@ -146,10 +146,10 @@
   iteration_summary.gradient_norm = sqrt(current_state.gradient_squared_norm);
   iteration_summary.gradient_max_norm = current_state.gradient_max_norm;
   if (iteration_summary.gradient_max_norm <= options.gradient_tolerance) {
-    summary->message =
-        StringPrintf("Gradient tolerance reached. Gradient max norm: %e <= %e",
-                     iteration_summary.gradient_max_norm,
-                     options.gradient_tolerance);
+    summary->message = absl::StrFormat(
+        "Gradient tolerance reached. Gradient max norm: %e <= %e",
+        iteration_summary.gradient_max_norm,
+        options.gradient_tolerance);
     summary->termination_type = CONVERGENCE;
     if (is_not_silent) {
       VLOG(1) << "Terminating: " << summary->message;
@@ -253,7 +253,7 @@
       // Line search direction failed to generate a new direction, and we
       // have already reached our specified maximum number of restarts,
       // terminate optimization.
-      summary->message = StringPrintf(
+      summary->message = absl::StrFormat(
           "Line search direction failure: specified "
           "max_num_line_search_direction_restarts: %d reached.",
           options.max_num_line_search_direction_restarts);
@@ -305,7 +305,7 @@
     // direction in a line search, most likely cause for this being violated
     // would be a numerical failure in the line search direction calculation.
     if (initial_step_size < 0.0) {
-      summary->message = StringPrintf(
+      summary->message = absl::StrFormat(
           "Numerical failure in line search, initial_step_size is "
           "negative: %.5e, directional_derivative: %.5e, "
           "(current_cost - previous_cost): %.5e",
@@ -324,7 +324,7 @@
                         current_state.directional_derivative,
                         &line_search_summary);
     if (!line_search_summary.success) {
-      summary->message = StringPrintf(
+      summary->message = absl::StrFormat(
           "Numerical failure in line search, failed to find "
           "a valid step size, (did not run out of iterations) "
           "using initial_step_size: %.5e, initial_cost: %.5e, "
@@ -429,7 +429,7 @@
     const double step_size_tolerance =
         options.parameter_tolerance * (x_norm + options.parameter_tolerance);
     if (iteration_summary.step_norm <= step_size_tolerance) {
-      summary->message = StringPrintf(
+      summary->message = absl::StrFormat(
           "Parameter tolerance reached. "
           "Relative step_norm: %e <= %e.",
           (iteration_summary.step_norm /
@@ -443,7 +443,7 @@
     }
 
     if (iteration_summary.gradient_max_norm <= options.gradient_tolerance) {
-      summary->message = StringPrintf(
+      summary->message = absl::StrFormat(
           "Gradient tolerance reached. "
           "Gradient max norm: %e <= %e",
           iteration_summary.gradient_max_norm,
@@ -459,7 +459,7 @@
         options.function_tolerance * std::abs(previous_state.cost);
     if (std::abs(iteration_summary.cost_change) <=
         absolute_function_tolerance) {
-      summary->message = StringPrintf(
+      summary->message = absl::StrFormat(
           "Function tolerance reached. "
           "|cost_change|/cost: %e <= %e",
           std::abs(iteration_summary.cost_change) / previous_state.cost,
diff --git a/internal/ceres/linear_least_squares_problems.cc b/internal/ceres/linear_least_squares_problems.cc
index 3a525fd..6eedc29 100644
--- a/internal/ceres/linear_least_squares_problems.cc
+++ b/internal/ceres/linear_least_squares_problems.cc
@@ -37,11 +37,11 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/block_sparse_matrix.h"
 #include "ceres/block_structure.h"
 #include "ceres/casts.h"
 #include "ceres/file.h"
-#include "ceres/stringprintf.h"
 #include "ceres/triplet_sparse_matrix.h"
 #include "ceres/types.h"
 
@@ -959,7 +959,7 @@
   FILE* fptr = fopen(filename.c_str(), "w");
   CHECK(fptr != nullptr);
   for (int i = 0; i < size; ++i) {
-    fprintf(fptr, "%17f\n", x[i]);
+    absl::FPrintF(fptr, "%17f\n", x[i]);
   }
   fclose(fptr);
 }
@@ -974,10 +974,10 @@
   LOG(INFO) << "writing to: " << filename_base << "*";
 
   std::string matlab_script;
-  StringAppendF(&matlab_script,
-                "function lsqp = load_trust_region_problem()\n");
-  StringAppendF(&matlab_script, "lsqp.num_rows = %d;\n", A->num_rows());
-  StringAppendF(&matlab_script, "lsqp.num_cols = %d;\n", A->num_cols());
+  absl::StrAppendFormat(&matlab_script,
+                        "function lsqp = load_trust_region_problem()\n");
+  absl::StrAppendFormat(&matlab_script, "lsqp.num_rows = %d;\n", A->num_rows());
+  absl::StrAppendFormat(&matlab_script, "lsqp.num_cols = %d;\n", A->num_cols());
 
   {
     std::string filename = filename_base + "_A.txt";
@@ -985,9 +985,9 @@
     CHECK(fptr != nullptr);
     A->ToTextFile(fptr);
     fclose(fptr);
-    StringAppendF(
-        &matlab_script, "tmp = load('%s', '-ascii');\n", filename.c_str());
-    StringAppendF(
+    absl::StrAppendFormat(
+        &matlab_script, "tmp = load('%s', '-ascii');\n", filename);
+    absl::StrAppendFormat(
         &matlab_script,
         "lsqp.A = sparse(tmp(:, 1) + 1, tmp(:, 2) + 1, tmp(:, 3), %d, %d);\n",
         A->num_rows(),
@@ -997,22 +997,22 @@
   if (D != nullptr) {
     std::string filename = filename_base + "_D.txt";
     WriteArrayToFileOrDie(filename, D, A->num_cols());
-    StringAppendF(
-        &matlab_script, "lsqp.D = load('%s', '-ascii');\n", filename.c_str());
+    absl::StrAppendFormat(
+        &matlab_script, "lsqp.D = load('%s', '-ascii');\n", filename);
   }
 
   if (b != nullptr) {
     std::string filename = filename_base + "_b.txt";
     WriteArrayToFileOrDie(filename, b, A->num_rows());
-    StringAppendF(
-        &matlab_script, "lsqp.b = load('%s', '-ascii');\n", filename.c_str());
+    absl::StrAppendFormat(
+        &matlab_script, "lsqp.b = load('%s', '-ascii');\n", filename);
   }
 
   if (x != nullptr) {
     std::string filename = filename_base + "_x.txt";
     WriteArrayToFileOrDie(filename, x, A->num_cols());
-    StringAppendF(
-        &matlab_script, "lsqp.x = load('%s', '-ascii');\n", filename.c_str());
+    absl::StrAppendFormat(
+        &matlab_script, "lsqp.x = load('%s', '-ascii');\n", filename);
   }
 
   std::string matlab_filename = filename_base + ".m";
diff --git a/internal/ceres/parameter_block.h b/internal/ceres/parameter_block.h
index db4011f..a76192c 100644
--- a/internal/ceres/parameter_block.h
+++ b/internal/ceres/parameter_block.h
@@ -41,12 +41,12 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/array_utils.h"
 #include "ceres/internal/disable_warnings.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/internal/export.h"
 #include "ceres/manifold.h"
-#include "ceres/stringprintf.h"
 
 namespace ceres::internal {
 
@@ -252,7 +252,7 @@
   }
 
   std::string ToString() const {
-    return StringPrintf(
+    return absl::StrFormat(
         "{ this=%p, user_state=%p, state=%p, size=%d, "
         "constant=%d, index=%d, state_offset=%d, "
         "delta_offset=%d }",
diff --git a/internal/ceres/problem_impl.cc b/internal/ceres/problem_impl.cc
index cc86d2c..b60a7cf 100644
--- a/internal/ceres/problem_impl.cc
+++ b/internal/ceres/problem_impl.cc
@@ -44,6 +44,7 @@
 #include "absl/container/fixed_array.h"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/casts.h"
 #include "ceres/compressed_row_jacobian_writer.h"
 #include "ceres/compressed_row_sparse_matrix.h"
@@ -62,7 +63,6 @@
 #include "ceres/residual_block.h"
 #include "ceres/scratch_evaluate_preparer.h"
 #include "ceres/stl_util.h"
-#include "ceres/stringprintf.h"
 
 namespace ceres::internal {
 namespace {
@@ -293,7 +293,7 @@
     if (has_duplicate_items) {
       std::string blocks;
       for (int i = 0; i < num_parameter_blocks; ++i) {
-        blocks += StringPrintf(" %p ", parameter_blocks[i]);
+        absl::StrAppendFormat(&blocks, " %p ", parameter_blocks[i]);
       }
 
       LOG(FATAL) << "Duplicate parameter blocks in a residual parameter "
@@ -407,7 +407,7 @@
   CHECK(residual_block != nullptr);
 
   // Verify that residual_block identifies a residual in the current problem.
-  const std::string residual_not_found_message = StringPrintf(
+  const std::string residual_not_found_message = absl::StrFormat(
       "Residual block to remove: %p not found. This usually means "
       "one of three things have happened:\n"
       " 1) residual_block is uninitialised and points to a random "
diff --git a/internal/ceres/program.cc b/internal/ceres/program.cc
index 26c5cfb..826fdab 100644
--- a/internal/ceres/program.cc
+++ b/internal/ceres/program.cc
@@ -38,6 +38,8 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 #include "ceres/array_utils.h"
 #include "ceres/casts.h"
 #include "ceres/compressed_row_sparse_matrix.h"
@@ -196,7 +198,7 @@
     const int size = parameter_block->Size();
     const int invalid_index = FindInvalidValue(size, array);
     if (invalid_index != size) {
-      *message = StringPrintf(
+      *message = absl::StrFormat(
           "ParameterBlock: %p with size %d has at least one invalid value.\n"
           "First invalid value is at index: %d.\n"
           "Parameter block values: ",
@@ -241,7 +243,7 @@
         const double lower_bound = parameter_block->LowerBoundForParameter(j);
         const double upper_bound = parameter_block->UpperBoundForParameter(j);
         if (parameters[j] < lower_bound || parameters[j] > upper_bound) {
-          *message = StringPrintf(
+          *message = absl::StrFormat(
               "ParameterBlock: %p with size %d has at least one infeasible "
               "value."
               "\nFirst infeasible value is at index: %d."
@@ -265,7 +267,7 @@
         const double lower_bound = parameter_block->LowerBoundForParameter(j);
         const double upper_bound = parameter_block->UpperBoundForParameter(j);
         if (lower_bound >= upper_bound) {
-          *message = StringPrintf(
+          *message = absl::StrFormat(
               "ParameterBlock: %p with size %d has at least one infeasible "
               "bound."
               "\nFirst infeasible bound is at index: %d."
@@ -379,7 +381,7 @@
                                   nullptr,
                                   nullptr,
                                   residual_block_evaluate_scratch.get())) {
-      *error = StringPrintf(
+      *error = absl::StrFormat(
           "Evaluation of the residual %d failed during "
           "removal of fixed residual blocks.",
           i);
@@ -553,12 +555,13 @@
 
 std::string Program::ToString() const {
   std::string ret = "Program dump\n";
-  ret += StringPrintf("Number of parameter blocks: %d\n", NumParameterBlocks());
-  ret += StringPrintf("Number of parameters: %d\n", NumParameters());
-  ret += "Parameters:\n";
+  absl::StrAppendFormat(
+      &ret, "Number of parameter blocks: %d\n", NumParameterBlocks());
+  absl::StrAppendFormat(&ret, "Number of parameters: %d\n", NumParameters());
+  absl::StrAppend(&ret, "Parameters:\n");
   for (int i = 0; i < parameter_blocks_.size(); ++i) {
-    ret +=
-        StringPrintf("%d: %s\n", i, parameter_blocks_[i]->ToString().c_str());
+    absl::StrAppendFormat(
+        &ret, "%d: %s\n", i, parameter_blocks_[i]->ToString());
   }
   return ret;
 }
diff --git a/internal/ceres/reorder_program.cc b/internal/ceres/reorder_program.cc
index dadf851..fdf8119 100644
--- a/internal/ceres/reorder_program.cc
+++ b/internal/ceres/reorder_program.cc
@@ -39,6 +39,7 @@
 #include <vector>
 
 #include "Eigen/SparseCore"
+#include "absl/strings/str_format.h"
 #include "ceres/internal/config.h"
 #include "ceres/internal/export.h"
 #include "ceres/ordered_groups.h"
@@ -218,7 +219,7 @@
                    std::string* error) {
   const int num_parameter_blocks = program->NumParameterBlocks();
   if (ordering.NumElements() != num_parameter_blocks) {
-    *error = StringPrintf(
+    *error = absl::StrFormat(
         "User specified ordering does not have the same "
         "number of parameters as the problem. The problem"
         "has %d blocks while the ordering has %d blocks.",
@@ -239,7 +240,7 @@
     for (double* parameter_block_ptr : group) {
       auto it = parameter_map.find(parameter_block_ptr);
       if (it == parameter_map.end()) {
-        *error = StringPrintf(
+        *error = absl::StrFormat(
             "User specified ordering contains a pointer "
             "to a double that is not a parameter block in "
             "the problem. The invalid double is in group: %d",
@@ -452,7 +453,7 @@
     std::string* error) {
   if (parameter_block_ordering->NumElements() !=
       program->NumParameterBlocks()) {
-    *error = StringPrintf(
+    *error = absl::StrFormat(
         "The program has %d parameter blocks, but the parameter block "
         "ordering has %d parameter blocks.",
         program->NumParameterBlocks(),
@@ -496,7 +497,7 @@
     const std::set<double*>& first_elimination_group =
         parameter_block_ordering->group_to_elements().begin()->second;
     if (!program->IsParameterBlockSetIndependent(first_elimination_group)) {
-      *error = StringPrintf(
+      *error = absl::StrFormat(
           "The first elimination group in the parameter block "
           "ordering of size %zd is not an independent set",
           first_elimination_group.size());
@@ -546,7 +547,7 @@
     Program* program,
     std::string* error) {
   if (parameter_block_ordering.NumElements() != program->NumParameterBlocks()) {
-    *error = StringPrintf(
+    *error = absl::StrFormat(
         "The program has %d parameter blocks, but the parameter block "
         "ordering has %d parameter blocks.",
         program->NumParameterBlocks(),
diff --git a/internal/ceres/residual_block.cc b/internal/ceres/residual_block.cc
index aeb761f..07afd6e 100644
--- a/internal/ceres/residual_block.cc
+++ b/internal/ceres/residual_block.cc
@@ -116,17 +116,17 @@
   }
 
   if (!IsEvaluationValid(*this, parameters.data(), residuals, eval_jacobians)) {
-    // clang-format off
-    std::string message =
-        "\n\n"
-        "Error in evaluating the ResidualBlock.\n\n"
-        "There are two possible reasons. Either the CostFunction did not evaluate and fill all    \n"  // NOLINT
-        "residual and jacobians that were requested or there was a non-finite value (nan/infinite)\n"  // NOLINT
-        "generated during the or jacobian computation. \n\n" +
-        EvaluationToString(
-            *this, parameters.data(), cost, residuals, eval_jacobians);
-    // clang-format on
-    LOG(WARNING) << message;
+    LOG(WARNING)
+        << "\n\n"
+           "Error in evaluating the ResidualBlock.\n\n"
+           "There are two possible reasons. Either the CostFunction did not "
+           "evaluate and fill all    \n"  // NOLINT
+           "residual and jacobians that were requested or there was a "
+           "non-finite "
+           "value (nan/infinite)\n"  // NOLINT
+           "generated during the or jacobian computation. \n\n"
+        << EvaluationToString(
+               *this, parameters.data(), cost, residuals, eval_jacobians);
     return false;
   }
 
diff --git a/internal/ceres/residual_block.h b/internal/ceres/residual_block.h
index 62460c7..82bac14 100644
--- a/internal/ceres/residual_block.h
+++ b/internal/ceres/residual_block.h
@@ -39,10 +39,10 @@
 #include <string>
 #include <vector>
 
+#include "absl/strings/str_format.h"
 #include "ceres/cost_function.h"
 #include "ceres/internal/disable_warnings.h"
 #include "ceres/internal/export.h"
-#include "ceres/stringprintf.h"
 #include "ceres/types.h"
 
 namespace ceres {
@@ -131,7 +131,7 @@
   void set_index(int index) { index_ = index; }
 
   std::string ToString() const {
-    return StringPrintf("{residual block; index=%d}", index_);
+    return absl::StrFormat("{residual block; index=%d}", index_);
   }
 
  private:
diff --git a/internal/ceres/residual_block_utils.cc b/internal/ceres/residual_block_utils.cc
index 54c41fb..9ba463d 100644
--- a/internal/ceres/residual_block_utils.cc
+++ b/internal/ceres/residual_block_utils.cc
@@ -36,12 +36,13 @@
 #include <string>
 
 #include "absl/log/check.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 #include "ceres/array_utils.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/internal/export.h"
 #include "ceres/parameter_block.h"
 #include "ceres/residual_block.h"
-#include "ceres/stringprintf.h"
 
 namespace ceres::internal {
 
@@ -72,34 +73,38 @@
 
   const int num_parameter_blocks = block.NumParameterBlocks();
   const int num_residuals = block.NumResiduals();
-  std::string result = "";
+  std::string result = absl::StrFormat(
+      "Residual Block size: %d parameter blocks x %d residuals\n\n",
+      num_parameter_blocks,
+      num_residuals);
 
   // clang-format off
-  StringAppendF(&result,
-                "Residual Block size: %d parameter blocks x %d residuals\n\n",
-                num_parameter_blocks, num_residuals);
-  result +=
-      "For each parameter block, the value of the parameters are printed in the first column   \n"  // NOLINT
-      "and the value of the jacobian under the corresponding residual. If a ParameterBlock was \n"  // NOLINT
-      "held constant then the corresponding jacobian is printed as 'Not Computed'. If an entry \n"  // NOLINT
-      "of the Jacobian/residual array was requested but was not written to by user code, it is \n"  // NOLINT
-      "indicated by 'Uninitialized'. This is an error. Residuals or Jacobian values evaluating \n"  // NOLINT
-      "to Inf or NaN is also an error.  \n\n"; // NOLINT
+  absl::StrAppend(&result,
+                  "For each parameter block, the value of the parameters are "
+                  "printed in the first column   \n"
+                  "and the value of the jacobian under the corresponding "
+                  "residual. If a ParameterBlock was \n"
+                  "held constant then the corresponding jacobian is printed as "
+                  "'Not Computed'. If an entry \n"
+                  "of the Jacobian/residual array was requested but was not "
+                  "written to by user code, it is \n"
+                  "indicated by 'Uninitialized'. This is an error. Residuals "
+                  "or Jacobian values evaluating \n"
+                  "to Inf or NaN is also an error.  \n\n");
   // clang-format on
 
-  std::string space = "Residuals:     ";
-  result += space;
+  absl::StrAppend(&result, "Residuals:     ");
   AppendArrayToString(num_residuals, residuals, &result);
-  StringAppendF(&result, "\n\n");
+  absl::StrAppend(&result, "\n\n");
 
   for (int i = 0; i < num_parameter_blocks; ++i) {
     const int parameter_block_size = block.parameter_blocks()[i]->Size();
-    StringAppendF(
+    absl::StrAppendFormat(
         &result, "Parameter Block %d, size: %d\n", i, parameter_block_size);
-    StringAppendF(&result, "\n");
+    absl::StrAppend(&result, "\n");
     for (int j = 0; j < parameter_block_size; ++j) {
       AppendArrayToString(1, parameters[i] + j, &result);
-      StringAppendF(&result, "| ");
+      absl::StrAppend(&result, "| ");
       for (int k = 0; k < num_residuals; ++k) {
         AppendArrayToString(1,
                             (jacobians != nullptr && jacobians[i] != nullptr)
@@ -107,11 +112,11 @@
                                 : nullptr,
                             &result);
       }
-      StringAppendF(&result, "\n");
+      absl::StrAppend(&result, "\n");
     }
-    StringAppendF(&result, "\n");
+    absl::StrAppend(&result, "\n");
   }
-  StringAppendF(&result, "\n");
+  absl::StrAppend(&result, "\n");
   return result;
 }
 
diff --git a/internal/ceres/rotation_test.cc b/internal/ceres/rotation_test.cc
index 0b7b385..0dfcf71 100644
--- a/internal/ceres/rotation_test.cc
+++ b/internal/ceres/rotation_test.cc
@@ -39,13 +39,13 @@
 #include <utility>
 
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/constants.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/internal/euler_angles.h"
 #include "ceres/internal/export.h"
 #include "ceres/is_close.h"
 #include "ceres/jet.h"
-#include "ceres/stringprintf.h"
 #include "ceres/test_util.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
@@ -495,11 +495,11 @@
   for (int i = 0; i < 3; ++i) {
     std::string line;
     for (int j = 0; j < 3; ++j) {
-      StringAppendF(&line, "%g ", kMatrix[i][j]);
+      absl::StrAppendFormat(&line, "%g ", kMatrix[i][j]);
     }
     line += "         |        ";
     for (int j = 0; j < 3; ++j) {
-      StringAppendF(&line, "%g ", out_rowmajor[i][j]);
+      absl::StrAppendFormat(&line, "%g ", out_rowmajor[i][j]);
     }
     LOG(INFO) << line;
   }
diff --git a/internal/ceres/solver.cc b/internal/ceres/solver.cc
index 9089aef..9ebee82 100644
--- a/internal/ceres/solver.cc
+++ b/internal/ceres/solver.cc
@@ -40,6 +40,8 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 #include "ceres/casts.h"
 #include "ceres/context.h"
 #include "ceres/context_impl.h"
@@ -55,7 +57,6 @@
 #include "ceres/program.h"
 #include "ceres/schur_templates.h"
 #include "ceres/solver_utils.h"
-#include "ceres/stringprintf.h"
 #include "ceres/suitesparse.h"
 #include "ceres/types.h"
 #include "ceres/wall_time.h"
@@ -63,9 +64,6 @@
 namespace ceres {
 namespace {
 
-using internal::StringAppendF;
-using internal::StringPrintf;
-
 #define OPTION_OP(x, y, OP)                                               \
   if (!(options.x OP y)) {                                                \
     std::stringstream ss;                                                 \
@@ -140,7 +138,7 @@
 
   if (!IsDenseLinearAlgebraLibraryTypeAvailable(
           options.dense_linear_algebra_library_type)) {
-    *error = StringPrintf(kFormat, solver_name, library_name);
+    *error = absl::StrFormat(kFormat, solver_name, library_name);
     return false;
   }
   return true;
@@ -172,7 +170,7 @@
       "sparse_linear_algebra_library_type = %s";
 
   if (options.sparse_linear_algebra_library_type == NO_SPARSE) {
-    *error = StringPrintf(kNoSparseFormat, solver_name, library_name);
+    *error = absl::StrFormat(kNoSparseFormat, solver_name, library_name);
     return false;
   }
 
@@ -180,31 +178,31 @@
           options.sparse_linear_algebra_library_type)) {
     if (options.sparse_linear_algebra_library_type == CUDA_SPARSE) {
 #if defined(CERES_NO_CUDSS)
-      *error = StringPrintf(kNoLibraryFormat, solver_name, library_name);
+      *error = absl::StrFormat(kNoLibraryFormat, solver_name, library_name);
       return false;
 #endif
     }
   } else {
-    *error = StringPrintf(kNoLibraryFormat, solver_name, library_name);
+    *error = absl::StrFormat(kNoLibraryFormat, solver_name, library_name);
     return false;
   }
 
   if (options.linear_solver_ordering_type == ceres::NESDIS &&
       !IsNestedDissectionAvailable(
           options.sparse_linear_algebra_library_type)) {
-    *error = StringPrintf(kNoNesdisFormat, library_name);
+    *error = absl::StrFormat(kNoNesdisFormat, library_name);
     return false;
   }
 
   if (options.use_mixed_precision_solves &&
       options.sparse_linear_algebra_library_type == SUITE_SPARSE) {
-    *error = StringPrintf(kMixedFormat, solver_name, library_name);
+    *error = absl::StrFormat(kMixedFormat, solver_name, library_name);
     return false;
   }
 
   if (options.dynamic_sparsity &&
       options.sparse_linear_algebra_library_type == ACCELERATE_SPARSE) {
-    *error = StringPrintf(kDynamicSparsityFormat, library_name);
+    *error = absl::StrFormat(kDynamicSparsityFormat, library_name);
     return false;
   }
 
@@ -326,9 +324,9 @@
   if (options.preconditioner_type != IDENTITY &&
       options.preconditioner_type != JACOBI &&
       options.preconditioner_type != SUBSET) {
-    *error =
-        StringPrintf("Can't use CGNR with preconditioner_type = %s.",
-                     PreconditionerTypeToString(options.preconditioner_type));
+    *error = absl::StrFormat(
+        "Can't use CGNR with preconditioner_type = %s.",
+        PreconditionerTypeToString(options.preconditioner_type));
     return false;
   }
 
@@ -510,14 +508,14 @@
 
 void StringifyOrdering(const std::vector<int>& ordering, std::string* report) {
   if (ordering.empty()) {
-    internal::StringAppendF(report, "AUTOMATIC");
+    absl::StrAppendFormat(report, "AUTOMATIC");
     return;
   }
 
   for (int i = 0; i < ordering.size() - 1; ++i) {
-    internal::StringAppendF(report, "%d,", ordering[i]);
+    absl::StrAppendFormat(report, "%d,", ordering[i]);
   }
-  internal::StringAppendF(report, "%d", ordering.back());
+  absl::StrAppendFormat(report, "%d", ordering.back());
 }
 
 void SummarizeGivenProgram(const internal::Program& program,
@@ -673,17 +671,17 @@
                                    const int f_block_size) {
   const std::string row = (row_block_size == Eigen::Dynamic)
                               ? "d"
-                              : internal::StringPrintf("%d", row_block_size);
+                              : absl::StrFormat("%d", row_block_size);
 
   const std::string e = (e_block_size == Eigen::Dynamic)
                             ? "d"
-                            : internal::StringPrintf("%d", e_block_size);
+                            : absl::StrFormat("%d", e_block_size);
 
   const std::string f = (f_block_size == Eigen::Dynamic)
                             ? "d"
-                            : internal::StringPrintf("%d", f_block_size);
+                            : absl::StrFormat("%d", f_block_size);
 
-  return internal::StringPrintf("%s,%s,%s", row.c_str(), e.c_str(), f.c_str());
+  return absl::StrFormat("%s,%s,%s", row, e, f);
 }
 
 #ifndef CERES_NO_CUDA
@@ -857,7 +855,7 @@
 }
 
 std::string Solver::Summary::BriefReport() const {
-  return StringPrintf(
+  return absl::StrFormat(
       "Ceres Solver Report: "
       "Iterations: %d, "
       "Initial cost: %e, "
@@ -874,35 +872,35 @@
 
   // NOTE operator+ is not usable for concatenating a string and a string_view.
   std::string report =
-      std::string{"\nSolver Summary (v "}.append(VersionString()) + ")\n\n";
+      absl::StrCat("\nSolver Summary (v ", VersionString(), ")\n\n");
 
-  StringAppendF(&report, "%45s    %21s\n", "Original", "Reduced");
-  StringAppendF(&report,
-                "Parameter blocks    % 25d% 25d\n",
-                num_parameter_blocks,
-                num_parameter_blocks_reduced);
-  StringAppendF(&report,
-                "Parameters          % 25d% 25d\n",
-                num_parameters,
-                num_parameters_reduced);
+  absl::StrAppendFormat(&report, "%45s    %21s\n", "Original", "Reduced");
+  absl::StrAppendFormat(&report,
+                        "Parameter blocks    % 25d% 25d\n",
+                        num_parameter_blocks,
+                        num_parameter_blocks_reduced);
+  absl::StrAppendFormat(&report,
+                        "Parameters          % 25d% 25d\n",
+                        num_parameters,
+                        num_parameters_reduced);
   if (num_effective_parameters_reduced != num_parameters_reduced) {
-    StringAppendF(&report,
-                  "Effective parameters% 25d% 25d\n",
-                  num_effective_parameters,
-                  num_effective_parameters_reduced);
+    absl::StrAppendFormat(&report,
+                          "Effective parameters% 25d% 25d\n",
+                          num_effective_parameters,
+                          num_effective_parameters_reduced);
   }
-  StringAppendF(&report,
-                "Residual blocks     % 25d% 25d\n",
-                num_residual_blocks,
-                num_residual_blocks_reduced);
-  StringAppendF(&report,
-                "Residuals           % 25d% 25d\n",
-                num_residuals,
-                num_residuals_reduced);
+  absl::StrAppendFormat(&report,
+                        "Residual blocks     % 25d% 25d\n",
+                        num_residual_blocks,
+                        num_residual_blocks_reduced);
+  absl::StrAppendFormat(&report,
+                        "Residuals           % 25d% 25d\n",
+                        num_residuals,
+                        num_residuals_reduced);
 
   if (minimizer_type == TRUST_REGION) {
     // TRUST_SEARCH HEADER
-    StringAppendF(
+    absl::StrAppendFormat(
         &report, "\nMinimizer                 %19s\n", "TRUST_REGION");
 
     if (linear_solver_type_used == DENSE_NORMAL_CHOLESKY ||
@@ -910,21 +908,22 @@
         linear_solver_type_used == DENSE_QR) {
       const char* mixed_precision_suffix =
           (mixed_precision_solves_used ? "(Mixed Precision)" : "");
-      StringAppendF(&report,
-                    "\nDense linear algebra library  %15s %s\n",
-                    DenseLinearAlgebraLibraryTypeToString(
-                        dense_linear_algebra_library_type),
-                    mixed_precision_suffix);
+      absl::StrAppendFormat(&report,
+                            "\nDense linear algebra library  %15s %s\n",
+                            DenseLinearAlgebraLibraryTypeToString(
+                                dense_linear_algebra_library_type),
+                            mixed_precision_suffix);
     }
 
-    StringAppendF(&report,
-                  "Trust region strategy     %19s",
-                  TrustRegionStrategyTypeToString(trust_region_strategy_type));
+    absl::StrAppendFormat(
+        &report,
+        "Trust region strategy     %19s",
+        TrustRegionStrategyTypeToString(trust_region_strategy_type));
     if (trust_region_strategy_type == DOGLEG) {
       if (dogleg_type == TRADITIONAL_DOGLEG) {
-        StringAppendF(&report, " (TRADITIONAL)");
+        absl::StrAppendFormat(&report, " (TRADITIONAL)");
       } else {
-        StringAppendF(&report, " (SUBSPACE)");
+        absl::StrAppendFormat(&report, " (SUBSPACE)");
       }
     }
 
@@ -947,7 +946,7 @@
       const char* mixed_precision_suffix =
           (mixed_precision_solves_used ? "(Mixed Precision)" : "");
       if (linear_solver_ordering_required) {
-        StringAppendF(
+        absl::StrAppendFormat(
             &report,
             "\nSparse linear algebra library %15s + %s %s\n",
             SparseLinearAlgebraLibraryTypeToString(
@@ -955,61 +954,60 @@
             LinearSolverOrderingTypeToString(linear_solver_ordering_type),
             mixed_precision_suffix);
       } else {
-        StringAppendF(&report,
-                      "\nSparse linear algebra library %15s %s\n",
-                      SparseLinearAlgebraLibraryTypeToString(
-                          sparse_linear_algebra_library_type),
-                      mixed_precision_suffix);
+        absl::StrAppendFormat(&report,
+                              "\nSparse linear algebra library %15s %s\n",
+                              SparseLinearAlgebraLibraryTypeToString(
+                                  sparse_linear_algebra_library_type),
+                              mixed_precision_suffix);
       }
     }
 
-    StringAppendF(&report, "\n");
-    StringAppendF(&report, "%45s    %21s\n", "Given", "Used");
-    StringAppendF(&report,
-                  "Linear solver       %25s%25s\n",
-                  LinearSolverTypeToString(linear_solver_type_given),
-                  LinearSolverTypeToString(linear_solver_type_used));
+    absl::StrAppendFormat(&report, "\n");
+    absl::StrAppendFormat(&report, "%45s    %21s\n", "Given", "Used");
+    absl::StrAppendFormat(&report,
+                          "Linear solver       %25s%25s\n",
+                          LinearSolverTypeToString(linear_solver_type_given),
+                          LinearSolverTypeToString(linear_solver_type_used));
 
     if (IsIterativeSolver(linear_solver_type_given)) {
-      StringAppendF(&report,
-                    "Preconditioner      %25s%25s\n",
-                    PreconditionerTypeToString(preconditioner_type_given),
-                    PreconditionerTypeToString(preconditioner_type_used));
+      absl::StrAppendFormat(
+          &report,
+          "Preconditioner      %25s%25s\n",
+          PreconditionerTypeToString(preconditioner_type_given),
+          PreconditionerTypeToString(preconditioner_type_used));
     }
 
     if (preconditioner_type_used == CLUSTER_JACOBI ||
         preconditioner_type_used == CLUSTER_TRIDIAGONAL) {
-      StringAppendF(
+      absl::StrAppendFormat(
           &report,
           "Visibility clustering%24s%25s\n",
           VisibilityClusteringTypeToString(visibility_clustering_type),
           VisibilityClusteringTypeToString(visibility_clustering_type));
     }
-    StringAppendF(&report,
-                  "Threads             % 25d% 25d\n",
-                  num_threads_given,
-                  num_threads_used);
+    absl::StrAppendFormat(&report,
+                          "Threads             % 25d% 25d\n",
+                          num_threads_given,
+                          num_threads_used);
 
     std::string given;
     StringifyOrdering(linear_solver_ordering_given, &given);
     std::string used;
     StringifyOrdering(linear_solver_ordering_used, &used);
-    StringAppendF(&report,
-                  "Linear solver ordering %22s %24s\n",
-                  given.c_str(),
-                  used.c_str());
+    absl::StrAppendFormat(
+        &report, "Linear solver ordering %22s %24s\n", given, used);
     if (IsSchurType(linear_solver_type_used)) {
-      StringAppendF(&report,
-                    "Schur structure        %22s %24s\n",
-                    schur_structure_given.c_str(),
-                    schur_structure_used.c_str());
+      absl::StrAppendFormat(&report,
+                            "Schur structure        %22s %24s\n",
+                            schur_structure_given,
+                            schur_structure_used);
     }
 
     if (inner_iterations_given) {
-      StringAppendF(&report,
-                    "Use inner iterations     %20s     %20s\n",
-                    inner_iterations_given ? "True" : "False",
-                    inner_iterations_used ? "True" : "False");
+      absl::StrAppendFormat(&report,
+                            "Use inner iterations     %20s     %20s\n",
+                            inner_iterations_given ? "True" : "False",
+                            inner_iterations_used ? "True" : "False");
     }
 
     if (inner_iterations_used) {
@@ -1017,18 +1015,18 @@
       StringifyOrdering(inner_iteration_ordering_given, &given);
       std::string used;
       StringifyOrdering(inner_iteration_ordering_used, &used);
-      StringAppendF(&report,
-                    "Inner iteration ordering %20s %24s\n",
-                    given.c_str(),
-                    used.c_str());
+      absl::StrAppendFormat(
+          &report, "Inner iteration ordering %20s %24s\n", given, used);
     }
   } else {
     // LINE_SEARCH HEADER
-    StringAppendF(&report, "\nMinimizer                 %19s\n", "LINE_SEARCH");
+    absl::StrAppendFormat(
+        &report, "\nMinimizer                 %19s\n", "LINE_SEARCH");
 
     std::string line_search_direction_string;
     if (line_search_direction_type == LBFGS) {
-      line_search_direction_string = StringPrintf("LBFGS (%d)", max_lbfgs_rank);
+      line_search_direction_string =
+          absl::StrFormat("LBFGS (%d)", max_lbfgs_rank);
     } else if (line_search_direction_type == NONLINEAR_CONJUGATE_GRADIENT) {
       line_search_direction_string = NonlinearConjugateGradientTypeToString(
           nonlinear_conjugate_gradient_type);
@@ -1037,52 +1035,52 @@
           LineSearchDirectionTypeToString(line_search_direction_type);
     }
 
-    StringAppendF(&report,
-                  "Line search direction     %19s\n",
-                  line_search_direction_string.c_str());
+    absl::StrAppendFormat(&report,
+                          "Line search direction     %19s\n",
+                          line_search_direction_string);
 
-    const std::string line_search_type_string = StringPrintf(
+    const std::string line_search_type_string = absl::StrFormat(
         "%s %s",
         LineSearchInterpolationTypeToString(line_search_interpolation_type),
         LineSearchTypeToString(line_search_type));
-    StringAppendF(&report,
-                  "Line search type          %19s\n",
-                  line_search_type_string.c_str());
-    StringAppendF(&report, "\n");
+    absl::StrAppendFormat(
+        &report, "Line search type          %19s\n", line_search_type_string);
+    absl::StrAppendFormat(&report, "\n");
 
-    StringAppendF(&report, "%45s    %21s\n", "Given", "Used");
-    StringAppendF(&report,
-                  "Threads             % 25d% 25d\n",
-                  num_threads_given,
-                  num_threads_used);
+    absl::StrAppendFormat(&report, "%45s    %21s\n", "Given", "Used");
+    absl::StrAppendFormat(&report,
+                          "Threads             % 25d% 25d\n",
+                          num_threads_given,
+                          num_threads_used);
   }
 
-  StringAppendF(&report, "\nCost:\n");
-  StringAppendF(&report, "Initial        % 30e\n", initial_cost);
+  absl::StrAppendFormat(&report, "\nCost:\n");
+  absl::StrAppendFormat(&report, "Initial        % 30e\n", initial_cost);
   if (termination_type != FAILURE && termination_type != USER_FAILURE) {
-    StringAppendF(&report, "Final          % 30e\n", final_cost);
-    StringAppendF(&report, "Change         % 30e\n", initial_cost - final_cost);
+    absl::StrAppendFormat(&report, "Final          % 30e\n", final_cost);
+    absl::StrAppendFormat(
+        &report, "Change         % 30e\n", initial_cost - final_cost);
   }
 
-  StringAppendF(&report,
-                "\nMinimizer iterations         % 16d\n",
-                num_successful_steps + num_unsuccessful_steps);
+  absl::StrAppendFormat(&report,
+                        "\nMinimizer iterations         % 16d\n",
+                        num_successful_steps + num_unsuccessful_steps);
 
   // Successful/Unsuccessful steps only matter in the case of the
   // trust region solver. Line search terminates when it encounters
   // the first unsuccessful step.
   if (minimizer_type == TRUST_REGION) {
-    StringAppendF(&report,
-                  "Successful steps               % 14d\n",
-                  num_successful_steps);
-    StringAppendF(&report,
-                  "Unsuccessful steps             % 14d\n",
-                  num_unsuccessful_steps);
+    absl::StrAppendFormat(&report,
+                          "Successful steps               % 14d\n",
+                          num_successful_steps);
+    absl::StrAppendFormat(&report,
+                          "Unsuccessful steps             % 14d\n",
+                          num_unsuccessful_steps);
   }
   if (inner_iterations_used) {
-    StringAppendF(&report,
-                  "Steps with inner iterations    % 14d\n",
-                  num_inner_iteration_steps);
+    absl::StrAppendFormat(&report,
+                          "Steps with inner iterations    % 14d\n",
+                          num_inner_iteration_steps);
   }
 
   const bool line_search_used =
@@ -1090,66 +1088,66 @@
        (minimizer_type == TRUST_REGION && is_constrained));
 
   if (line_search_used) {
-    StringAppendF(&report,
-                  "Line search steps              % 14d\n",
-                  num_line_search_steps);
+    absl::StrAppendFormat(&report,
+                          "Line search steps              % 14d\n",
+                          num_line_search_steps);
   }
 
-  StringAppendF(&report, "\nTime (in seconds):\n");
-  StringAppendF(
+  absl::StrAppendFormat(&report, "\nTime (in seconds):\n");
+  absl::StrAppendFormat(
       &report, "Preprocessor        %25.6f\n", preprocessor_time_in_seconds);
 
-  StringAppendF(&report,
-                "\n  Residual only evaluation %18.6f (%d)\n",
-                residual_evaluation_time_in_seconds,
-                num_residual_evaluations);
+  absl::StrAppendFormat(&report,
+                        "\n  Residual only evaluation %18.6f (%d)\n",
+                        residual_evaluation_time_in_seconds,
+                        num_residual_evaluations);
   if (line_search_used) {
-    StringAppendF(&report,
-                  "    Line search cost evaluation    %10.6f\n",
-                  line_search_cost_evaluation_time_in_seconds);
+    absl::StrAppendFormat(&report,
+                          "    Line search cost evaluation    %10.6f\n",
+                          line_search_cost_evaluation_time_in_seconds);
   }
-  StringAppendF(&report,
-                "  Jacobian & residual evaluation %12.6f (%d)\n",
-                jacobian_evaluation_time_in_seconds,
-                num_jacobian_evaluations);
+  absl::StrAppendFormat(&report,
+                        "  Jacobian & residual evaluation %12.6f (%d)\n",
+                        jacobian_evaluation_time_in_seconds,
+                        num_jacobian_evaluations);
   if (line_search_used) {
-    StringAppendF(&report,
-                  "    Line search gradient evaluation   %6.6f\n",
-                  line_search_gradient_evaluation_time_in_seconds);
+    absl::StrAppendFormat(&report,
+                          "    Line search gradient evaluation   %6.6f\n",
+                          line_search_gradient_evaluation_time_in_seconds);
   }
 
   if (minimizer_type == TRUST_REGION) {
-    StringAppendF(&report,
-                  "  Linear solver       %23.6f (%d)\n",
-                  linear_solver_time_in_seconds,
-                  num_linear_solves);
+    absl::StrAppendFormat(&report,
+                          "  Linear solver       %23.6f (%d)\n",
+                          linear_solver_time_in_seconds,
+                          num_linear_solves);
   }
 
   if (inner_iterations_used) {
-    StringAppendF(&report,
-                  "  Inner iterations    %23.6f\n",
-                  inner_iteration_time_in_seconds);
+    absl::StrAppendFormat(&report,
+                          "  Inner iterations    %23.6f\n",
+                          inner_iteration_time_in_seconds);
   }
 
   if (line_search_used) {
-    StringAppendF(&report,
-                  "  Line search polynomial minimization  %.6f\n",
-                  line_search_polynomial_minimization_time_in_seconds);
+    absl::StrAppendFormat(&report,
+                          "  Line search polynomial minimization  %.6f\n",
+                          line_search_polynomial_minimization_time_in_seconds);
   }
 
-  StringAppendF(
+  absl::StrAppendFormat(
       &report, "Minimizer           %25.6f\n\n", minimizer_time_in_seconds);
 
-  StringAppendF(
+  absl::StrAppendFormat(
       &report, "Postprocessor        %24.6f\n", postprocessor_time_in_seconds);
 
-  StringAppendF(
+  absl::StrAppendFormat(
       &report, "Total               %25.6f\n\n", total_time_in_seconds);
 
-  StringAppendF(&report,
-                "Termination:        %25s (%s)\n",
-                TerminationTypeToString(termination_type),
-                message.c_str());
+  absl::StrAppendFormat(&report,
+                        "Termination:        %25s (%s)\n",
+                        TerminationTypeToString(termination_type),
+                        message);
   return report;
 }
 
diff --git a/internal/ceres/stringprintf.cc b/internal/ceres/stringprintf.cc
deleted file mode 100644
index 100bbff..0000000
--- a/internal/ceres/stringprintf.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2023 Google Inc. All rights reserved.
-// http://ceres-solver.org/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-//   this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-//   this list of conditions and the following disclaimer in the documentation
-//   and/or other materials provided with the distribution.
-// * Neither the name of Google Inc. nor the names of its contributors may be
-//   used to endorse or promote products derived from this software without
-//   specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: Sanjay Ghemawat
-
-#include "ceres/stringprintf.h"
-
-#include <cerrno>
-#include <cstdarg>  // For va_list and related operations
-#include <cstdio>   // MSVC requires this for _vsnprintf
-#include <string>
-#include <vector>
-
-#include "ceres/internal/export.h"
-
-namespace ceres::internal {
-
-void StringAppendV(std::string* dst, const char* format, va_list ap) {
-  // First try with a small fixed size buffer
-  char space[1024];
-
-  // It's possible for methods that use a va_list to invalidate
-  // the data in it upon use.  The fix is to make a copy
-  // of the structure before using it and use that copy instead.
-  va_list backup_ap;
-  va_copy(backup_ap, ap);
-  int result = vsnprintf(space, sizeof(space), format, backup_ap);
-  va_end(backup_ap);
-
-  if (result < sizeof(space)) {
-    if (result >= 0) {
-      // Normal case -- everything fit.
-      dst->append(space, result);
-      return;
-    }
-
-#if defined(_MSC_VER)
-    // Error or MSVC running out of space.  MSVC 8.0 and higher
-    // can be asked about space needed with the special idiom below:
-    va_copy(backup_ap, ap);
-    result = vsnprintf(nullptr, 0, format, backup_ap);
-    va_end(backup_ap);
-#endif
-
-    if (result < 0) {
-      // Just an error.
-      return;
-    }
-  }
-
-  // Increase the buffer size to the size requested by vsnprintf,
-  // plus one for the closing \0.
-  int length = result + 1;
-  char* buf = new char[length];
-
-  // Restore the va_list before we use it again
-  va_copy(backup_ap, ap);
-  result = vsnprintf(buf, length, format, backup_ap);
-  va_end(backup_ap);
-
-  if (result >= 0 && result < length) {
-    // It fit
-    dst->append(buf, result);
-  }
-  delete[] buf;
-}
-
-std::string StringPrintf(const char* format, ...) {
-  va_list ap;
-  va_start(ap, format);
-  std::string result;
-  StringAppendV(&result, format, ap);
-  va_end(ap);
-  return result;
-}
-
-const std::string& SStringPrintf(std::string* dst, const char* format, ...) {
-  va_list ap;
-  va_start(ap, format);
-  dst->clear();
-  StringAppendV(dst, format, ap);
-  va_end(ap);
-  return *dst;
-}
-
-void StringAppendF(std::string* dst, const char* format, ...) {
-  va_list ap;
-  va_start(ap, format);
-  StringAppendV(dst, format, ap);
-  va_end(ap);
-}
-
-}  // namespace ceres::internal
diff --git a/internal/ceres/stringprintf.h b/internal/ceres/stringprintf.h
deleted file mode 100644
index f761770..0000000
--- a/internal/ceres/stringprintf.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Ceres Solver - A fast non-linear least squares minimizer
-// Copyright 2023 Google Inc. All rights reserved.
-// http://ceres-solver.org/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-//   this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-//   this list of conditions and the following disclaimer in the documentation
-//   and/or other materials provided with the distribution.
-// * Neither the name of Google Inc. nor the names of its contributors may be
-//   used to endorse or promote products derived from this software without
-//   specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: Sanjay Ghemawat
-//
-// Printf variants that place their output in a C++ string.
-//
-// Usage:
-//      string result = StringPrintf("%d %s\n", 10, "hello");
-//      SStringPrintf(&result, "%d %s\n", 10, "hello");
-//      StringAppendF(&result, "%d %s\n", 20, "there");
-
-#ifndef CERES_INTERNAL_STRINGPRINTF_H_
-#define CERES_INTERNAL_STRINGPRINTF_H_
-
-#include <cstdarg>
-#include <string>
-
-#include "ceres/internal/disable_warnings.h"
-#include "ceres/internal/export.h"
-
-namespace ceres::internal {
-
-#if (defined(__GNUC__) || defined(__clang__))
-// Tell the compiler to do printf format string checking if the compiler
-// supports it; see the 'format' attribute in
-// <http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Function-Attributes.html>.
-//
-// N.B.: As the GCC manual states, "[s]ince non-static C++ methods
-// have an implicit 'this' argument, the arguments of such methods
-// should be counted from two, not one."
-#define CERES_PRINTF_ATTRIBUTE(string_index, first_to_check) \
-  __attribute__((__format__(__printf__, string_index, first_to_check)))
-#define CERES_SCANF_ATTRIBUTE(string_index, first_to_check) \
-  __attribute__((__format__(__scanf__, string_index, first_to_check)))
-#else
-#define CERES_PRINTF_ATTRIBUTE(string_index, first_to_check)
-#endif
-
-// Return a C++ string.
-CERES_NO_EXPORT extern std::string StringPrintf(const char* format, ...)
-    // Tell the compiler to do printf format string checking.
-    CERES_PRINTF_ATTRIBUTE(1, 2);
-
-// Store result into a supplied string and return it.
-CERES_NO_EXPORT extern const std::string& SStringPrintf(std::string* dst,
-                                                        const char* format,
-                                                        ...)
-    // Tell the compiler to do printf format string checking.
-    CERES_PRINTF_ATTRIBUTE(2, 3);
-
-// Append result to a supplied string.
-CERES_NO_EXPORT extern void StringAppendF(std::string* dst,
-                                          const char* format,
-                                          ...)
-    // Tell the compiler to do printf format string checking.
-    CERES_PRINTF_ATTRIBUTE(2, 3);
-
-// Lower-level routine that takes a va_list and appends to a specified string.
-// All other routines are just convenience wrappers around it.
-CERES_NO_EXPORT extern void StringAppendV(std::string* dst,
-                                          const char* format,
-                                          va_list ap);
-
-#undef CERES_PRINTF_ATTRIBUTE
-
-}  // namespace ceres::internal
-
-#include "ceres/internal/reenable_warnings.h"
-
-#endif  // CERES_INTERNAL_STRINGPRINTF_H_
diff --git a/internal/ceres/suitesparse.cc b/internal/ceres/suitesparse.cc
index 6f4a8c9..d59de88 100644
--- a/internal/ceres/suitesparse.cc
+++ b/internal/ceres/suitesparse.cc
@@ -39,10 +39,10 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/compressed_col_sparse_matrix_utils.h"
 #include "ceres/compressed_row_sparse_matrix.h"
 #include "ceres/linear_solver.h"
-#include "ceres/stringprintf.h"
 #include "ceres/suitesparse.h"
 #include "ceres/triplet_sparse_matrix.h"
 #include "cholmod.h"
@@ -179,7 +179,7 @@
 
   if (cc_.status != CHOLMOD_OK) {
     *message =
-        StringPrintf("cholmod_analyze failed. error code: %d", cc_.status);
+        absl::StrFormat("cholmod_analyze failed. error code: %d", cc_.status);
     return nullptr;
   }
 
@@ -202,7 +202,7 @@
 
   if (cc_.status != CHOLMOD_OK) {
     *message =
-        StringPrintf("cholmod_analyze failed. error code: %d", cc_.status);
+        absl::StrFormat("cholmod_analyze failed. error code: %d", cc_.status);
     return nullptr;
   }
 
@@ -326,7 +326,7 @@
           "Please report this to ceres-solver@googlegroups.com.";
       return LinearSolverTerminationType::FATAL_ERROR;
     default:
-      *message = StringPrintf(
+      *message = absl::StrFormat(
           "Unknown cholmod return code: %d. "
           "Please report this to ceres-solver@googlegroups.com.",
           cc_.status);
diff --git a/internal/ceres/test_util.cc b/internal/ceres/test_util.cc
index a9d4335..fc73764 100644
--- a/internal/ceres/test_util.cc
+++ b/internal/ceres/test_util.cc
@@ -37,9 +37,9 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/file.h"
 #include "ceres/internal/port.h"
-#include "ceres/stringprintf.h"
 #include "ceres/types.h"
 #include "gtest/gtest.h"
 
@@ -71,11 +71,11 @@
     relative_difference = absolute_difference;
   }
   if (relative_difference > max_abs_relative_difference) {
-    VLOG(1) << StringPrintf("x=%17g y=%17g abs=%17g rel=%17g",
-                            x,
-                            y,
-                            absolute_difference,
-                            relative_difference);
+    VLOG(1) << absl::StrFormat("x=%17g y=%17g abs=%17g rel=%17g",
+                               x,
+                               y,
+                               absolute_difference,
+                               relative_difference);
   }
 
   EXPECT_NEAR(relative_difference, 0.0, max_abs_relative_difference);
@@ -137,13 +137,14 @@
 }
 
 std::string ToString(const Solver::Options& options) {
-  return StringPrintf("(%s, %s, %s, %s, %d)",
-                      LinearSolverTypeToString(options.linear_solver_type),
-                      SparseLinearAlgebraLibraryTypeToString(
-                          options.sparse_linear_algebra_library_type),
-                      options.linear_solver_ordering ? "USER" : "AUTOMATIC",
-                      PreconditionerTypeToString(options.preconditioner_type),
-                      options.num_threads);
+  return absl::StrFormat(
+      "(%s, %s, %s, %s, %d)",
+      LinearSolverTypeToString(options.linear_solver_type),
+      SparseLinearAlgebraLibraryTypeToString(
+          options.sparse_linear_algebra_library_type),
+      options.linear_solver_ordering ? "USER" : "AUTOMATIC",
+      PreconditionerTypeToString(options.preconditioner_type),
+      options.num_threads);
 }
 
 }  // namespace internal
diff --git a/internal/ceres/test_util.h b/internal/ceres/test_util.h
index 32de4e3..dcac9a6 100644
--- a/internal/ceres/test_util.h
+++ b/internal/ceres/test_util.h
@@ -38,7 +38,6 @@
 #include "ceres/internal/export.h"
 #include "ceres/problem.h"
 #include "ceres/solver.h"
-#include "ceres/stringprintf.h"
 #include "gtest/gtest.h"
 
 namespace ceres {
diff --git a/internal/ceres/triplet_sparse_matrix.cc b/internal/ceres/triplet_sparse_matrix.cc
index 554ece9..9b567e5 100644
--- a/internal/ceres/triplet_sparse_matrix.cc
+++ b/internal/ceres/triplet_sparse_matrix.cc
@@ -36,6 +36,7 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/compressed_row_sparse_matrix.h"
 #include "ceres/crs_matrix.h"
 #include "ceres/internal/eigen.h"
@@ -281,7 +282,7 @@
 void TripletSparseMatrix::ToTextFile(FILE* file) const {
   CHECK(file != nullptr);
   for (int i = 0; i < num_nonzeros_; ++i) {
-    fprintf(file, "% 10d % 10d %17f\n", rows_[i], cols_[i], values_[i]);
+    absl::FPrintF(file, "% 10d % 10d %17f\n", rows_[i], cols_[i], values_[i]);
   }
 }
 
diff --git a/internal/ceres/trust_region_minimizer.cc b/internal/ceres/trust_region_minimizer.cc
index dba7842..971fc5b 100644
--- a/internal/ceres/trust_region_minimizer.cc
+++ b/internal/ceres/trust_region_minimizer.cc
@@ -7,7 +7,7 @@
 //
 // * Redistributions of source code must retain the above copyright notice,
 //   this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
+// * Redistributions in binary form must reproduce the ab%ove copyright notice,
 //   this list of conditions and the following disclaimer in the documentation
 //   and/or other materials provided with the distribution.
 // * Neither the name of Google Inc. nor the names of its contributors may be
@@ -42,6 +42,7 @@
 #include "Eigen/Core"
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/array_utils.h"
 #include "ceres/coordinate_descent_minimizer.h"
 #include "ceres/eigen_vector_ops.h"
@@ -49,7 +50,6 @@
 #include "ceres/file.h"
 #include "ceres/line_search.h"
 #include "ceres/parallel_for.h"
-#include "ceres/stringprintf.h"
 #include "ceres/types.h"
 #include "ceres/wall_time.h"
 
@@ -389,8 +389,8 @@
         options_.trust_region_problem_dump_format_type;
     per_solve_options.dump_filename_base =
         JoinPath(options_.trust_region_problem_dump_directory,
-                 StringPrintf("ceres_solver_iteration_%03d",
-                              iteration_summary_.iteration));
+                 absl::StrFormat("ceres_solver_iteration_%03d",
+                                 iteration_summary_.iteration));
   }
 
   TrustRegionStrategy::Summary strategy_summary =
@@ -470,7 +470,7 @@
   // just slightly negative.
   if (++num_consecutive_invalid_steps_ >=
       options_.max_num_consecutive_invalid_steps) {
-    solver_summary_->message = StringPrintf(
+    solver_summary_->message = absl::StrFormat(
         "Number of consecutive invalid steps more "
         "than Solver::Options::max_num_consecutive_invalid_steps: %d",
         options_.max_num_consecutive_invalid_steps);
@@ -643,7 +643,7 @@
     return false;
   }
 
-  solver_summary_->message = StringPrintf(
+  solver_summary_->message = absl::StrFormat(
       "Maximum solver time reached. "
       "Total solver time: %e >= %e.",
       total_solver_time,
@@ -663,7 +663,7 @@
     return false;
   }
 
-  solver_summary_->message = StringPrintf(
+  solver_summary_->message = absl::StrFormat(
       "Maximum number of iterations reached. "
       "Number of iterations: %d.",
       iteration_summary_.iteration);
@@ -683,7 +683,7 @@
     return false;
   }
 
-  solver_summary_->message = StringPrintf(
+  solver_summary_->message = absl::StrFormat(
       "Gradient tolerance reached. "
       "Gradient max norm: %e <= %e",
       iteration_summary_.gradient_max_norm,
@@ -702,7 +702,7 @@
     return false;
   }
 
-  solver_summary_->message = StringPrintf(
+  solver_summary_->message = absl::StrFormat(
       "Minimum trust region radius reached. "
       "Trust region radius: %e <= %e",
       iteration_summary_.trust_region_radius,
@@ -727,7 +727,7 @@
     return false;
   }
 
-  solver_summary_->message = StringPrintf(
+  solver_summary_->message = absl::StrFormat(
       "Parameter tolerance reached. "
       "Relative step_norm: %e <= %e.",
       (iteration_summary_.step_norm / (x_norm + options_.parameter_tolerance)),
@@ -749,7 +749,7 @@
     return false;
   }
 
-  solver_summary_->message = StringPrintf(
+  solver_summary_->message = absl::StrFormat(
       "Function tolerance reached. "
       "|cost_change|/cost: %e <= %e",
       fabs(iteration_summary_.cost_change) / x_cost_,
diff --git a/internal/ceres/trust_region_preprocessor.cc b/internal/ceres/trust_region_preprocessor.cc
index 9f45664..4d20f52 100644
--- a/internal/ceres/trust_region_preprocessor.cc
+++ b/internal/ceres/trust_region_preprocessor.cc
@@ -36,6 +36,7 @@
 
 #include "absl/log/check.h"
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/callbacks.h"
 #include "ceres/context_impl.h"
 #include "ceres/evaluator.h"
@@ -91,17 +92,17 @@
     options->preconditioner_type =
         Preconditioner::PreconditionerForZeroEBlocks(preconditioner_type_given);
 
-    message =
-        StringPrintf("No E blocks. Switching from %s(%s) to %s(%s).",
-                     LinearSolverTypeToString(linear_solver_type_given),
-                     PreconditionerTypeToString(preconditioner_type_given),
-                     LinearSolverTypeToString(options->linear_solver_type),
-                     PreconditionerTypeToString(options->preconditioner_type));
+    message = absl::StrFormat(
+        "No E blocks. Switching from %s(%s) to %s(%s).",
+        LinearSolverTypeToString(linear_solver_type_given),
+        PreconditionerTypeToString(preconditioner_type_given),
+        LinearSolverTypeToString(options->linear_solver_type),
+        PreconditionerTypeToString(options->preconditioner_type));
   } else {
     message =
-        StringPrintf("No E blocks. Switching from %s to %s.",
-                     LinearSolverTypeToString(linear_solver_type_given),
-                     LinearSolverTypeToString(options->linear_solver_type));
+        absl::StrFormat("No E blocks. Switching from %s to %s.",
+                        LinearSolverTypeToString(linear_solver_type_given),
+                        LinearSolverTypeToString(options->linear_solver_type));
   }
   if (options->logging_type != SILENT) {
     VLOG(1) << message;
diff --git a/internal/ceres/visibility_based_preconditioner_test.cc b/internal/ceres/visibility_based_preconditioner_test.cc
index 1cbad17..4558964 100644
--- a/internal/ceres/visibility_based_preconditioner_test.cc
+++ b/internal/ceres/visibility_based_preconditioner_test.cc
@@ -41,7 +41,6 @@
 #include "ceres/internal/eigen.h"
 #include "ceres/linear_least_squares_problems.h"
 #include "ceres/schur_eliminator.h"
-#include "ceres/stringprintf.h"
 #include "ceres/test_util.h"
 #include "ceres/types.h"
 #include "gtest/gtest.h"
diff --git a/internal/ceres/wall_time.cc b/internal/ceres/wall_time.cc
index f42f1ea..fa07470 100644
--- a/internal/ceres/wall_time.cc
+++ b/internal/ceres/wall_time.cc
@@ -33,6 +33,7 @@
 #include <ctime>
 
 #include "absl/log/log.h"
+#include "absl/strings/str_format.h"
 #include "ceres/internal/config.h"
 
 #ifdef _WIN32
@@ -41,8 +42,6 @@
 #include <sys/time.h>
 #endif
 
-#include "ceres/stringprintf.h"
-
 namespace ceres::internal {
 
 double WallTimeInSeconds() {
@@ -67,9 +66,9 @@
 
   start_time_ = WallTimeInSeconds();
   last_event_time_ = start_time_;
-  events_ = StringPrintf(
+  events_ = absl::StrFormat(
       "\n%s\n                                        Delta   Cumulative\n",
-      logger_name.c_str());
+      logger_name);
 }
 
 EventLogger::~EventLogger() {
@@ -90,11 +89,11 @@
   const double absolute_time_delta = current_time - start_time_;
   last_event_time_ = current_time;
 
-  StringAppendF(&events_,
-                "  %30s : %10.5f   %10.5f\n",
-                event_name.c_str(),
-                relative_time_delta,
-                absolute_time_delta);
+  absl::StrAppendFormat(&events_,
+                        "  %30s : %10.5f   %10.5f\n",
+                        event_name,
+                        relative_time_delta,
+                        absolute_time_delta);
 }
 
 }  // namespace ceres::internal