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@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 45namespace ceres { 46namespace internal { 47 48TEST(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 61TEST(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 74TEST(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 87TEST(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 100TEST(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 113TEST(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 126TEST(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 139TEST(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 152template<int num_rows, int num_cols> 153class 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. 168TEST(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 187TEST(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