10ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Ceres Solver - A fast non-linear least squares minimizer 20ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Copyright 2010, 2011, 2012 Google Inc. All rights reserved. 30ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// http://code.google.com/p/ceres-solver/ 40ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 50ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Redistribution and use in source and binary forms, with or without 60ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// modification, are permitted provided that the following conditions are met: 70ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 80ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions of source code must retain the above copyright notice, 90ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// this list of conditions and the following disclaimer. 100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions in binary form must reproduce the above copyright notice, 110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// this list of conditions and the following disclaimer in the documentation 120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// and/or other materials provided with the distribution. 130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Neither the name of Google Inc. nor the names of its contributors may be 140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// used to endorse or promote products derived from this software without 150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// specific prior written permission. 160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// POSSIBILITY OF SUCH DAMAGE. 280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Author: keir@google.com (Keir Mierle) 300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// 310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Based on the templated version in public/numeric_diff_cost_function.h. 320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/runtime_numeric_diff_cost_function.h" 340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <algorithm> 360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <numeric> 370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <vector> 380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "Eigen/Dense" 390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/cost_function.h" 400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/scoped_ptr.h" 410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "glog/logging.h" 420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace ceres { 440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace internal { 450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace { 460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongbool EvaluateJacobianForParameterBlock(const CostFunction* function, 480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong int parameter_block_size, 490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong int parameter_block, 500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong RuntimeNumericDiffMethod method, 510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double relative_step_size, 520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double const* residuals_at_eval_point, 530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double** parameters, 540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double** jacobians) { 550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong using Eigen::Map; 560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong using Eigen::Matrix; 570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong using Eigen::Dynamic; 580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong using Eigen::RowMajor; 590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong typedef Matrix<double, Dynamic, 1> ResidualVector; 610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong typedef Matrix<double, Dynamic, 1> ParameterVector; 620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong typedef Matrix<double, Dynamic, Dynamic, RowMajor> JacobianMatrix; 630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong int num_residuals = function->num_residuals(); 650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Map<JacobianMatrix> parameter_jacobian(jacobians[parameter_block], 670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong num_residuals, 680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong parameter_block_size); 690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Mutate one element at a time and then restore. 710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Map<ParameterVector> x_plus_delta(parameters[parameter_block], 720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong parameter_block_size); 730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong ParameterVector x(x_plus_delta); 740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong ParameterVector step_size = x.array().abs() * relative_step_size; 750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // To handle cases where a paremeter is exactly zero, instead use the mean 770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // step_size for the other dimensions. 780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double fallback_step_size = step_size.sum() / step_size.rows(); 790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (fallback_step_size == 0.0) { 800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // If all the parameters are zero, there's no good answer. Use the given 810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // relative step_size as absolute step_size and hope for the best. 820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong fallback_step_size = relative_step_size; 830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // For each parameter in the parameter block, use finite differences to 860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // compute the derivative for that parameter. 870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong for (int j = 0; j < parameter_block_size; ++j) { 880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (step_size(j) == 0.0) { 890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // The parameter is exactly zero, so compromise and use the mean step_size 900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // from the other parameters. This can break in many cases, but it's hard 910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // to pick a good number without problem specific knowledge. 920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong step_size(j) = fallback_step_size; 930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong x_plus_delta(j) = x(j) + step_size(j); 950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong ResidualVector residuals(num_residuals); 970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (!function->Evaluate(parameters, &residuals[0], NULL)) { 980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Something went wrong; bail. 990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return false; 1000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Compute this column of the jacobian in 3 steps: 1030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // 1. Store residuals for the forward part. 1040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // 2. Subtract residuals for the backward (or 0) part. 1050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // 3. Divide out the run. 1060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong parameter_jacobian.col(j) = residuals; 1070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double one_over_h = 1 / step_size(j); 1090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (method == CENTRAL) { 1100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Compute the function on the other side of x(j). 1110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong x_plus_delta(j) = x(j) - step_size(j); 1120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (!function->Evaluate(parameters, &residuals[0], NULL)) { 1140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Something went wrong; bail. 1150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return false; 1160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong parameter_jacobian.col(j) -= residuals; 1180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong one_over_h /= 2; 1190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } else { 1200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Forward difference only; reuse existing residuals evaluation. 1210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong parameter_jacobian.col(j) -= 1220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong Map<const ResidualVector>(residuals_at_eval_point, num_residuals); 1230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong x_plus_delta(j) = x(j); // Restore x_plus_delta. 1250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Divide out the run to get slope. 1270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong parameter_jacobian.col(j) *= one_over_h; 1280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return true; 1300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 1310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongclass RuntimeNumericDiffCostFunction : public CostFunction { 1330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong public: 1340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong RuntimeNumericDiffCostFunction(const CostFunction* function, 1350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong RuntimeNumericDiffMethod method, 1360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double relative_step_size) 1370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong : function_(function), 1380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong method_(method), 1390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong relative_step_size_(relative_step_size) { 1400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong *mutable_parameter_block_sizes() = function->parameter_block_sizes(); 1410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong set_num_residuals(function->num_residuals()); 1420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong virtual ~RuntimeNumericDiffCostFunction() { } 1450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong virtual bool Evaluate(double const* const* parameters, 1470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double* residuals, 1480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double** jacobians) const { 1490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Get the function value (residuals) at the the point to evaluate. 1500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong bool success = function_->Evaluate(parameters, residuals, NULL); 1510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (!success) { 1520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Something went wrong; ignore the jacobian. 1530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return false; 1540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (!jacobians) { 1560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Nothing to do; just forward. 1570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return true; 1580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const vector<int16>& block_sizes = function_->parameter_block_sizes(); 1610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong CHECK(!block_sizes.empty()); 1620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Create local space for a copy of the parameters which will get mutated. 1640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong int parameters_size = accumulate(block_sizes.begin(), block_sizes.end(), 0); 1650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong vector<double> parameters_copy(parameters_size); 1660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong vector<double*> parameters_references_copy(block_sizes.size()); 1670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong parameters_references_copy[0] = ¶meters_copy[0]; 1680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong for (int block = 1; block < block_sizes.size(); ++block) { 1690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong parameters_references_copy[block] = parameters_references_copy[block - 1] 1700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong + block_sizes[block - 1]; 1710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // Copy the parameters into the local temp space. 1740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong for (int block = 0; block < block_sizes.size(); ++block) { 1750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong memcpy(parameters_references_copy[block], 1760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong parameters[block], 1770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong block_sizes[block] * sizeof(*parameters[block])); 1780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong for (int block = 0; block < block_sizes.size(); ++block) { 1810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (!jacobians[block]) { 1820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong // No jacobian requested for this parameter / residual pair. 1830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong continue; 1840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong if (!EvaluateJacobianForParameterBlock(function_, 1860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong block_sizes[block], 1870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong block, 1880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong method_, 1890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong relative_step_size_, 1900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong residuals, 1910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong ¶meters_references_copy[0], 1920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong jacobians)) { 1930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return false; 1940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return true; 1970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong } 1980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 1990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong private: 2000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const CostFunction* function_; 2010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong RuntimeNumericDiffMethod method_; 2020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double relative_step_size_; 2030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}; 2040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 2050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} // namespace 2060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 2070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongCostFunction* CreateRuntimeNumericDiffCostFunction( 2080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong const CostFunction* cost_function, 2090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong RuntimeNumericDiffMethod method, 2100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong double relative_step_size) { 2110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong return new RuntimeNumericDiffCostFunction(cost_function, 2120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong method, 2130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong relative_step_size); 2140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} 2150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong 2160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} // namespace internal 2170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong} // namespace ceres 218