Allow the LossFunction contained in a LossFunctionWrapper to be NULL. This is consistent with how NULL LossFunctions are treated everywhere else. Change-Id: Ic91e39ccb13137fcad7f85e78613a29ecde30d67
diff --git a/include/ceres/loss_function.h b/include/ceres/loss_function.h index 78397f0..44c6b87 100644 --- a/include/ceres/loss_function.h +++ b/include/ceres/loss_function.h
@@ -358,6 +358,9 @@ // whose scale can be mutated after an optimization problem has been // constructed. // +// Since we treat the a NULL Loss function as the Identity loss +// function, rho = NULL is a valid input. +// // Example usage // // Problem problem; @@ -394,8 +397,14 @@ } virtual void Evaluate(double sq_norm, double out[3]) const { - CHECK_NOTNULL(rho_.get()); - rho_->Evaluate(sq_norm, out); + if (rho_.get() == NULL) { + out[0] = sq_norm; + out[1] = 1.0; + out[2] = 0.0; + } + else { + rho_->Evaluate(sq_norm, out); + } } void Reset(LossFunction* rho, Ownership ownership) {
diff --git a/internal/ceres/loss_function_test.cc b/internal/ceres/loss_function_test.cc index d06f69e..406ace7 100644 --- a/internal/ceres/loss_function_test.cc +++ b/internal/ceres/loss_function_test.cc
@@ -228,6 +228,24 @@ for (int i = 0; i < 3; ++i) { EXPECT_NEAR(rho[i], rho_gold[i], 1e-12); } + + // Set to NULL + TrivialLoss loss_function4; + loss_function_wrapper.Reset(NULL, TAKE_OWNERSHIP); + loss_function_wrapper.Evaluate(s, rho); + loss_function4.Evaluate(s, rho_gold); + for (int i = 0; i < 3; ++i) { + EXPECT_NEAR(rho[i], rho_gold[i], 1e-12); + } + + // Set to NULL, not taking ownership + loss_function_wrapper.Reset(NULL, DO_NOT_TAKE_OWNERSHIP); + loss_function_wrapper.Evaluate(s, rho); + loss_function4.Evaluate(s, rho_gold); + for (int i = 0; i < 3; ++i) { + EXPECT_NEAR(rho[i], rho_gold[i], 1e-12); + } + } } // namespace internal