1 // Ceres Solver - A fast non-linear least squares minimizer 2 // Copyright 2010, 2011, 2012 Google Inc. All rights reserved. 3 // http://code.google.com/p/ceres-solver/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are met: 7 // 8 // * Redistributions of source code must retain the above copyright notice, 9 // this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above copyright notice, 11 // this list of conditions and the following disclaimer in the documentation 12 // and/or other materials provided with the distribution. 13 // * Neither the name of Google Inc. nor the names of its contributors may be 14 // used to endorse or promote products derived from this software without 15 // specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 // POSSIBILITY OF SUCH DAMAGE. 28 // 29 // Author: keir (at) google.com (Keir Mierle) 30 31 #include "ceres/numeric_diff_cost_function.h" 32 33 #include <algorithm> 34 #include <cmath> 35 #include <string> 36 #include <vector> 37 #include "ceres/internal/macros.h" 38 #include "ceres/internal/scoped_ptr.h" 39 #include "ceres/numeric_diff_test_utils.h" 40 #include "ceres/test_util.h" 41 #include "ceres/types.h" 42 #include "glog/logging.h" 43 #include "gtest/gtest.h" 44 45 namespace ceres { 46 namespace internal { 47 48 TEST(NumericDiffCostFunction, EasyCaseFunctorCentralDifferences) { 49 internal::scoped_ptr<CostFunction> cost_function; 50 cost_function.reset( 51 new NumericDiffCostFunction<EasyFunctor, 52 CENTRAL, 53 3, /* number of residuals */ 54 5, /* size of x1 */ 55 5 /* size of x2 */>( 56 new EasyFunctor)); 57 EasyFunctor functor; 58 functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, CENTRAL); 59 } 60 61 TEST(NumericDiffCostFunction, EasyCaseFunctorForwardDifferences) { 62 internal::scoped_ptr<CostFunction> cost_function; 63 cost_function.reset( 64 new NumericDiffCostFunction<EasyFunctor, 65 FORWARD, 66 3, /* number of residuals */ 67 5, /* size of x1 */ 68 5 /* size of x2 */>( 69 new EasyFunctor)); 70 EasyFunctor functor; 71 functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, FORWARD); 72 } 73 74 TEST(NumericDiffCostFunction, EasyCaseCostFunctionCentralDifferences) { 75 internal::scoped_ptr<CostFunction> cost_function; 76 cost_function.reset( 77 new NumericDiffCostFunction<EasyCostFunction, 78 CENTRAL, 79 3, /* number of residuals */ 80 5, /* size of x1 */ 81 5 /* size of x2 */>( 82 new EasyCostFunction, TAKE_OWNERSHIP)); 83 EasyFunctor functor; 84 functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, CENTRAL); 85 } 86 87 TEST(NumericDiffCostFunction, EasyCaseCostFunctionForwardDifferences) { 88 internal::scoped_ptr<CostFunction> cost_function; 89 cost_function.reset( 90 new NumericDiffCostFunction<EasyCostFunction, 91 FORWARD, 92 3, /* number of residuals */ 93 5, /* size of x1 */ 94 5 /* size of x2 */>( 95 new EasyCostFunction, TAKE_OWNERSHIP)); 96 EasyFunctor functor; 97 functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, FORWARD); 98 } 99 100 TEST(NumericDiffCostFunction, TranscendentalCaseFunctorCentralDifferences) { 101 internal::scoped_ptr<CostFunction> cost_function; 102 cost_function.reset( 103 new NumericDiffCostFunction<TranscendentalFunctor, 104 CENTRAL, 105 2, /* number of residuals */ 106 5, /* size of x1 */ 107 5 /* size of x2 */>( 108 new TranscendentalFunctor)); 109 TranscendentalFunctor functor; 110 functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, CENTRAL); 111 } 112 113 TEST(NumericDiffCostFunction, TranscendentalCaseFunctorForwardDifferences) { 114 internal::scoped_ptr<CostFunction> cost_function; 115 cost_function.reset( 116 new NumericDiffCostFunction<TranscendentalFunctor, 117 FORWARD, 118 2, /* number of residuals */ 119 5, /* size of x1 */ 120 5 /* size of x2 */>( 121 new TranscendentalFunctor)); 122 TranscendentalFunctor functor; 123 functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, FORWARD); 124 } 125 126 TEST(NumericDiffCostFunction, TranscendentalCaseCostFunctionCentralDifferences) { 127 internal::scoped_ptr<CostFunction> cost_function; 128 cost_function.reset( 129 new NumericDiffCostFunction<TranscendentalCostFunction, 130 CENTRAL, 131 2, /* number of residuals */ 132 5, /* size of x1 */ 133 5 /* size of x2 */>( 134 new TranscendentalCostFunction, TAKE_OWNERSHIP)); 135 TranscendentalFunctor functor; 136 functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, CENTRAL); 137 } 138 139 TEST(NumericDiffCostFunction, TranscendentalCaseCostFunctionForwardDifferences) { 140 internal::scoped_ptr<CostFunction> cost_function; 141 cost_function.reset( 142 new NumericDiffCostFunction<TranscendentalCostFunction, 143 FORWARD, 144 2, /* number of residuals */ 145 5, /* size of x1 */ 146 5 /* size of x2 */>( 147 new TranscendentalCostFunction, TAKE_OWNERSHIP)); 148 TranscendentalFunctor functor; 149 functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, FORWARD); 150 } 151 152 template<int num_rows, int num_cols> 153 class SizeTestingCostFunction : public SizedCostFunction<num_rows, num_cols> { 154 public: 155 virtual bool Evaluate(double const* const* parameters, 156 double* residuals, 157 double** jacobians) const { 158 return true; 159 } 160 }; 161 162 // As described in 163 // http://forum.kde.org/viewtopic.php?f=74&t=98536#p210774 164 // Eigen3 has restrictions on the Row/Column major storage of vectors, 165 // depending on their dimensions. This test ensures that the correct 166 // templates are instantiated for various shapes of the Jacobian 167 // matrix. 168 TEST(NumericDiffCostFunction, EigenRowMajorColMajorTest) { 169 scoped_ptr<CostFunction> cost_function; 170 cost_function.reset( 171 new NumericDiffCostFunction<SizeTestingCostFunction<1,1>, CENTRAL, 1, 1>( 172 new SizeTestingCostFunction<1,1>, ceres::TAKE_OWNERSHIP)); 173 174 cost_function.reset( 175 new NumericDiffCostFunction<SizeTestingCostFunction<2,1>, CENTRAL, 2, 1>( 176 new SizeTestingCostFunction<2,1>, ceres::TAKE_OWNERSHIP)); 177 178 cost_function.reset( 179 new NumericDiffCostFunction<SizeTestingCostFunction<1,2>, CENTRAL, 1, 2>( 180 new SizeTestingCostFunction<1,2>, ceres::TAKE_OWNERSHIP)); 181 182 cost_function.reset( 183 new NumericDiffCostFunction<SizeTestingCostFunction<2,2>, CENTRAL, 2, 2>( 184 new SizeTestingCostFunction<2,2>, ceres::TAKE_OWNERSHIP)); 185 } 186 187 TEST(NumericDiffCostFunction, EasyCaseFunctorCentralDifferencesAndDynamicNumResiduals) { 188 internal::scoped_ptr<CostFunction> cost_function; 189 cost_function.reset( 190 new NumericDiffCostFunction<EasyFunctor, 191 CENTRAL, 192 ceres::DYNAMIC, 193 5, /* size of x1 */ 194 5 /* size of x2 */>( 195 new EasyFunctor, TAKE_OWNERSHIP, 3)); 196 EasyFunctor functor; 197 functor.ExpectCostFunctionEvaluationIsNearlyCorrect(*cost_function, CENTRAL); 198 } 199 200 } // namespace internal 201 } // namespace ceres 202