| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 | // Ceres Solver - A fast non-linear least squares minimizer// Copyright 2020 Google Inc. All rights reserved.// http://code.google.com/p/ceres-solver///// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met://// * Redistributions of source code must retain the above copyright notice,//   this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above copyright notice,//   this list of conditions and the following disclaimer in the documentation//   and/or other materials provided with the distribution.// * Neither the name of Google Inc. nor the names of its contributors may be//   used to endorse or promote products derived from this software without//   specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE// POSSIBILITY OF SUCH DAMAGE.//// Author: darius.rueckert@fau.de (Darius Rueckert)//// This file includes unit test functors for every supported expression type.// This is similar to expression_ref_test and codegeneration_test, but for the// complete pipeline including automatic differentation. For each of the structs// below, the Evaluate function is generated using GenerateCodeForFunctor. After// that this function is executed with random parameters. The result of the// residuals and jacobians is then compared to AutoDiff (without code// generation). Of course, the correctness of this module depends on the// correctness of autodiff.//#include <cmath>#include <limits>#include "ceres/codegen/codegen_cost_function.h"namespace test {struct InputOutputAssignment : public ceres::CodegenCostFunction<7, 4, 2, 1> {  template <typename T>  bool operator()(const T* x0, const T* x1, const T* x2, T* y) const {    y[0] = x0[0];    y[1] = x0[1];    y[2] = x0[2];    y[3] = x0[3];    y[4] = x1[0];    y[5] = x1[1];    y[6] = x2[0];    return true;  }#include "tests/inputoutputassignment.h"};struct CompileTimeConstants : public ceres::CodegenCostFunction<7, 1> {  template <typename T>  bool operator()(const T* x0, T* y) const {    y[0] = T(0);    y[1] = T(1);    y[2] = T(-1);    y[3] = T(1e-10);    y[4] = T(1e10);    y[5] = T(std::numeric_limits<double>::infinity());    y[6] = T(std::numeric_limits<double>::quiet_NaN());    return true;  }#include "tests/compiletimeconstants.h"};struct Assignments : public ceres::CodegenCostFunction<8, 2> {  template <typename T>  bool operator()(const T* x0, T* y) const {    T a = x0[0];    T b = x0[1];    y[0] = a;    y[1] = b;    y[2] = y[3] = a;    T c = a;    y[4] = c;    T d(b);    y[5] = d;    y[6] = std::move(c);    y[7] = std::move(T(T(std::move(T(a)))));    return true;  }#include "tests/assignments.h"};struct BinaryArithmetic : public ceres::CodegenCostFunction<9, 2> {  template <typename T>  bool operator()(const T* x0, T* y) const {    T a = x0[0];    T b = x0[1];    y[0] = a + b;    y[1] = a - b;    y[2] = a * b;    y[3] = a / b;    y[4] = a;    y[4] += b;    y[5] = a;    y[5] -= b;    y[6] = a;    y[6] *= b;    y[7] = a;    y[7] /= b;    y[8] = a + b * a / a - b + b / a;    return true;  }#include "tests/binaryarithmetic.h"};struct UnaryArithmetic : public ceres::CodegenCostFunction<3, 1> {  template <typename T>  bool operator()(const T* x0, T* y) const {    T a = x0[0];    y[0] = -a;    y[1] = +a;    y[2] = a;    return true;  }#include "tests/unaryarithmetic.h"};struct BinaryComparison : public ceres::CodegenCostFunction<12, 2> {  template <typename T>  bool operator()(const T* x0, T* y) const {    T a = x0[0];    T b = x0[1];    // For each operator we swap the inputs so both branches are evaluated once.    CERES_IF(a < b) { y[0] = T(0); }    CERES_ELSE { y[0] = T(1); }    CERES_ENDIF    CERES_IF(b < a) { y[1] = T(0); }    CERES_ELSE { y[1] = T(1); }    CERES_ENDIF    CERES_IF(a > b) { y[2] = T(0); }    CERES_ELSE { y[2] = T(1); }    CERES_ENDIF    CERES_IF(b > a) { y[3] = T(0); }    CERES_ELSE { y[3] = T(1); }    CERES_ENDIF    CERES_IF(a <= b) { y[4] = T(0); }    CERES_ELSE { y[4] = T(1); }    CERES_ENDIF    CERES_IF(b <= a) { y[5] = T(0); }    CERES_ELSE { y[5] = T(1); }    CERES_ENDIF    CERES_IF(a >= b) { y[6] = T(0); }    CERES_ELSE { y[6] = T(1); }    CERES_ENDIF    CERES_IF(b >= a) { y[7] = T(0); }    CERES_ELSE { y[7] = T(1); }    CERES_ENDIF    CERES_IF(a == b) { y[8] = T(0); }    CERES_ELSE { y[8] = T(1); }    CERES_ENDIF    CERES_IF(b == a) { y[9] = T(0); }    CERES_ELSE { y[9] = T(1); }    CERES_ENDIF    CERES_IF(a != b) { y[10] = T(0); }    CERES_ELSE { y[10] = T(1); }    CERES_ENDIF    CERES_IF(b != a) { y[11] = T(0); }    CERES_ELSE { y[11] = T(1); }    CERES_ENDIF    return true;  }#include "tests/binarycomparison.h"};struct LogicalOperators : public ceres::CodegenCostFunction<8, 3> {  template <typename T>  bool operator()(const T* x0, T* y) const {    T a = x0[0];    T b = x0[1];    T c = x0[2];    auto r1 = a < b;    auto r2 = a < c;    CERES_IF(r1) { y[0] = T(0); }    CERES_ELSE { y[0] = T(1); }    CERES_ENDIF    CERES_IF(r2) { y[1] = T(0); }    CERES_ELSE { y[1] = T(1); }    CERES_ENDIF    CERES_IF(!r1) { y[2] = T(0); }    CERES_ELSE { y[2] = T(1); }    CERES_ENDIF    CERES_IF(!r2) { y[3] = T(0); }    CERES_ELSE { y[3] = T(1); }    CERES_ENDIF    CERES_IF(r1 && r2) { y[4] = T(0); }    CERES_ELSE { y[4] = T(1); }    CERES_ENDIF    CERES_IF(!r1 && !r2) { y[5] = T(0); }    CERES_ELSE { y[5] = T(1); }    CERES_ENDIF    CERES_IF(r1 || r2) { y[6] = T(0); }    CERES_ELSE { y[6] = T(1); }    CERES_ENDIF    CERES_IF(!r1 || !r2) { y[7] = T(0); }    CERES_ELSE { y[7] = T(1); }    CERES_ENDIF    return true;  }#include "tests/logicaloperators.h"};struct ScalarFunctions : public ceres::CodegenCostFunction<20, 22> {  template <typename T>  bool operator()(const T* x0, T* y) const {    y[0] = abs(x0[0]);    y[1] = acos(x0[1]);    y[2] = asin(x0[2]);    y[3] = atan(x0[3]);    y[4] = cbrt(x0[4]);    y[5] = ceil(x0[5]);    y[6] = cos(x0[6]);    y[7] = cosh(x0[7]);    y[8] = exp(x0[8]);    y[9] = exp2(x0[9]);    y[10] = floor(x0[10]);    y[11] = log(x0[11]);    y[12] = log2(x0[12]);    y[13] = sin(x0[13]);    y[14] = sinh(x0[14]);    y[15] = sqrt(x0[15]);    y[16] = tan(x0[16]);    y[17] = tanh(x0[17]);    y[18] = atan2(x0[18], x0[19]);    y[19] = pow(x0[20], x0[21]);    return true;  }#include "tests/scalarfunctions.h"};struct LogicalFunctions : public ceres::CodegenCostFunction<4, 4> {  template <typename T>  bool operator()(const T* x0, T* y) const {    using std::isfinite;    using std::isinf;    using std::isnan;    using std::isnormal;    T a = x0[0];    auto r1 = isfinite(a);    auto r2 = isinf(a);    auto r3 = isnan(a);    auto r4 = isnormal(a);    CERES_IF(r1) { y[0] = T(0); }    CERES_ELSE { y[0] = T(1); }    CERES_ENDIF    CERES_IF(r2) { y[1] = T(0); }    CERES_ELSE { y[1] = T(1); }    CERES_ENDIF    CERES_IF(r3) { y[2] = T(0); }    CERES_ELSE { y[2] = T(1); }    CERES_ENDIF    CERES_IF(r4) { y[3] = T(0); }    CERES_ELSE { y[3] = T(1); }    CERES_ENDIF    return true;  }#include "tests/logicalfunctions.h"};struct Branches : public ceres::CodegenCostFunction<4, 3> {  template <typename T>  bool operator()(const T* x0, T* y) const {    T a = x0[0];    T b = x0[1];    T c = x0[2];    auto r1 = a < b;    auto r2 = a < c;    auto r3 = b < c;    // If without else    y[0] = T(0);    CERES_IF(r1) { y[0] += T(1); }    CERES_ENDIF    // If else    y[1] = T(0);    CERES_IF(r1) { y[1] += T(-1); }    CERES_ELSE { y[1] += T(1); }    CERES_ENDIF    // Nested if    y[2] = T(0);    CERES_IF(r1) {      y[2] += T(1);      CERES_IF(r2) {        y[2] += T(4);        CERES_IF(r2) { y[2] += T(8); }        CERES_ENDIF      }      CERES_ENDIF    }    CERES_ENDIF    // Nested if-else    y[3] = T(0);    CERES_IF(r1) {      y[3] += T(1);      CERES_IF(r2) {        y[3] += T(2);        CERES_IF(r3) { y[3] += T(4); }        CERES_ELSE { y[3] += T(8); }        CERES_ENDIF      }      CERES_ELSE {        y[3] += T(16);        CERES_IF(r3) { y[3] += T(32); }        CERES_ELSE { y[3] += T(64); }        CERES_ENDIF      }      CERES_ENDIF    }    CERES_ELSE {      y[3] += T(128);      CERES_IF(r2) { y[3] += T(256); }      CERES_ELSE { y[3] += T(512); }      CERES_ENDIF    }    CERES_ENDIF    return true;  }#include "tests/branches.h"};}  // namespace test
 |