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