diff --git a/include/ceres/dynamic_autodiff_cost_function.h b/include/ceres/dynamic_autodiff_cost_function.h index 7b75150b5..10270643b 100644 --- a/include/ceres/dynamic_autodiff_cost_function.h +++ b/include/ceres/dynamic_autodiff_cost_function.h @@ -151,6 +151,9 @@ class DynamicAutoDiffCostFunction : public DynamicCostFunction { } } + if (num_active_parameters == 0) { + return (*functor_)(parameters, residuals); + } // When `num_active_parameters % Stride != 0` then it can be the case // that `active_parameter_count < Stride` while parameter_cursor is less // than the total number of parameters and with no remaining non-constant diff --git a/internal/ceres/dynamic_autodiff_cost_function_test.cc b/internal/ceres/dynamic_autodiff_cost_function_test.cc index bec31c530..6b57fd39f 100644 --- a/internal/ceres/dynamic_autodiff_cost_function_test.cc +++ b/internal/ceres/dynamic_autodiff_cost_function_test.cc @@ -771,5 +771,51 @@ TEST_F(SixParameterCostFunctorTest, TestSixParameterJacobianVCCVCV) { } } +class ValueError { + public: + explicit ValueError(double target_value) : target_value_(target_value) {} + + template + bool operator()(const T* value, T* residual) const { + *residual = *value - T(target_value_); + return true; + } + + protected: + double target_value_; +}; + +class DynamicValueError { + public: + explicit DynamicValueError(double target_value) + : target_value_(target_value) {} + + template + bool operator()(T const* const* parameters, T* residual) const { + residual[0] = T(target_value_) - parameters[0][0]; + return true; + } + + protected: + double target_value_; +}; + +TEST(DynamicAutoDiffCostFunction, + EvaluateWithEmptyJacobiansArrayComputesResidual) { + const double target_value = 1.0; + double parameter = 0; + ceres::DynamicAutoDiffCostFunction cost_function( + new DynamicValueError(target_value)); + cost_function.AddParameterBlock(1); + cost_function.SetNumResiduals(1); + + double* parameter_blocks[1] = {¶meter}; + double* jacobians[1] = {nullptr}; + double residual; + + EXPECT_TRUE(cost_function.Evaluate(parameter_blocks, &residual, jacobians)); + EXPECT_EQ(residual, target_value); +} + } // namespace internal } // namespace ceres