Numerically robust computation of model_cost_change.

Change-Id: I421df17bab3bfdf782d95285cf352ed37675d835
diff --git a/examples/bundle_adjuster.cc b/examples/bundle_adjuster.cc
index e5f9100..3e13c86 100644
--- a/examples/bundle_adjuster.cc
+++ b/examples/bundle_adjuster.cc
@@ -270,8 +270,8 @@
   Solver::Options options;
   SetSolverOptionsFromFlags(&bal_problem, &options);
   options.solver_log = FLAGS_solver_log;
-  options.gradient_tolerance *= 1e-3;
-
+  options.gradient_tolerance = 1e-12;
+  options.function_tolerance = 1e-12;
   Solver::Summary summary;
   Solve(options, &problem, &summary);
   std::cout << summary.FullReport() << "\n";
diff --git a/examples/nist.cc b/examples/nist.cc
index 0f5951f..4fce3e7 100644
--- a/examples/nist.cc
+++ b/examples/nist.cc
@@ -374,16 +374,18 @@
           -std::log10(fabs(summary.final_cost - certified_cost) / certified_cost);
     }
 
+    std::cerr << "start " << start + 1 << " " ;
     if (num_matching_digits <= kMinNumMatchingDigits) {
-      std::cerr << "start " << start + 1 << " " ;
       std::cerr <<  "FAILURE";
-      std::cerr << " summary: "
-                << summary.BriefReport()
-                << " Certified cost: " << certified_cost
-                << std::endl;
     } else {
+      std::cerr <<  "SUCCESS";
       ++num_success;
     }
+    std::cerr << " summary: "
+              << summary.BriefReport()
+              << " Certified cost: " << certified_cost
+              << std::endl;
+
   }
 
   return num_success;
diff --git a/internal/ceres/trust_region_minimizer.cc b/internal/ceres/trust_region_minimizer.cc
index 194d54e..d848a17 100644
--- a/internal/ceres/trust_region_minimizer.cc
+++ b/internal/ceres/trust_region_minimizer.cc
@@ -270,23 +270,24 @@
                  << options.lsqp_dump_directory << "but failed.";
     }
 
-    double new_model_cost = 0.0;
+    double model_cost_change = 0.0;
     if (strategy_summary.termination_type != FAILURE) {
-      // new_model_cost = 1/2 |f + J * step|^2
-      model_residuals = residuals;
+      // new_model_cost
+      //  = 1/2 [f + J * step]^2
+      //  = 1/2 [ f'f + 2f'J * step + step' * J' * J * step ]
+      // model_cost_change
+      //  = cost - new_model_cost
+      //  = f'f/2  - 1/2 [ f'f + 2f'J * step + step' * J' * J * step]
+      //  = -f'J * step - step' * J' * J * step / 2
+      model_residuals.setZero();
       jacobian->RightMultiply(trust_region_step.data(), model_residuals.data());
-      new_model_cost = model_residuals.squaredNorm() / 2.0;
+      model_cost_change = -(residuals.dot(model_residuals) +
+                            model_residuals.squaredNorm() / 2.0);
 
-      // In exact arithmetic, this would never be the case. But poorly
-      // conditioned matrices can give rise to situations where the
-      // new_model_cost can actually be larger than half the squared
-      // norm of the residual vector. We allow for small tolerance
-      // around cost and beyond that declare the step to be invalid.
-      if ((1.0 - new_model_cost / cost) < -kEpsilon) {
+      if (model_cost_change < 0.0) {
         VLOG(1) << "Invalid step: current_cost: " << cost
-                << " new_model_cost " << new_model_cost
-                << " absolute difference " << (cost - new_model_cost)
-                << " relative difference " << (1.0 - new_model_cost/cost);
+                << " absolute difference " << model_cost_change
+                << " relative difference " << (model_cost_change / cost);
       } else {
         iteration_summary.step_is_valid = true;
       }
@@ -322,25 +323,6 @@
       // The step is numerically valid, so now we can judge its quality.
       num_consecutive_invalid_steps = 0;
 
-      // We allow some slop around 0, and clamp the model_cost_change
-      // at kEpsilon * min(1.0, cost) from below.
-      //
-      // In exact arithmetic this should never be needed, as we are
-      // guaranteed to new_model_cost <= cost. However, due to various
-      // numerical issues, it is possible that new_model_cost is
-      // nearly equal to cost, and the difference is a small negative
-      // number. To make sure that the relative_decrease computation
-      // remains sane, as clamp the difference (cost - new_model_cost)
-      // from below at a small positive number.
-      //
-      // This number is the minimum of kEpsilon * (cost, 1.0), which
-      // ensures that it will never get too large in absolute value,
-      // while scaling down proportionally with the magnitude of the
-      // cost. This is important for problems where the minimum of the
-      // objective function is near zero.
-      const double model_cost_change =
-          max(kEpsilon * min(1.0, cost), cost - new_model_cost);
-
       // Undo the Jacobian column scaling.
       delta = (trust_region_step.array() * scale.array()).matrix();
       iteration_summary.step_norm = delta.norm();