Remove AutodiffCodegen - Remove Codegen files - Revert Jet and Rotation Change-Id: I005c5f98f2b6dfa5c7fd88d998b6aa83e47dab60
diff --git a/CMakeLists.txt b/CMakeLists.txt index f11e579..7de7d37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -165,10 +165,6 @@ option(BUILD_BENCHMARKS "Build Ceres benchmarking suite" ON) option(BUILD_SHARED_LIBS "Build Ceres as a shared library." OFF) option(PROVIDE_UNINSTALL_TARGET "Add a custom target to ease removal of installed targets" ON) -option(CODE_GENERATION "Build the code generation module." OFF) -if(CODE_GENERATION) - message(WARNING "The code generation module is still under development. The functionality and API of the current implementation might change in the future.") -endif(CODE_GENERATION) set(SANITIZERS "" CACHE STRING "Semicolon-separated list of sanitizers to use (e.g address, memory, thread)") include(EnableSanitizer) enable_sanitizer(${SANITIZERS}) @@ -670,13 +666,6 @@ file(GLOB CERES_PUBLIC_INTERNAL_HDRS ${Ceres_SOURCE_DIR}/include/ceres/internal/*.h) install(FILES ${CERES_PUBLIC_INTERNAL_HDRS} DESTINATION include/ceres/internal) -# Ceres codegen headers -file(GLOB CERES_PUBLIC_CODEGEN_HDRS ${Ceres_SOURCE_DIR}/include/ceres/codegen/*.h) -install(FILES ${CERES_PUBLIC_CODEGEN_HDRS} DESTINATION include/ceres/codegen) - -file(GLOB CERES_PUBLIC_CODEGEN_INTERNAL_HDRS ${Ceres_SOURCE_DIR}/include/ceres/codegen/internal/*.h) -install(FILES ${CERES_PUBLIC_CODEGEN_INTERNAL_HDRS} DESTINATION include/ceres/codegen/internal) - # Also setup installation of Ceres config.h configured with the current # build options into the installed headers directory. install(FILES ${Ceres_BINARY_DIR}/config/ceres/internal/config.h
diff --git a/include/ceres/codegen/codegen_cost_function.h b/include/ceres/codegen/codegen_cost_function.h deleted file mode 100644 index 57df088..0000000 --- a/include/ceres/codegen/codegen_cost_function.h +++ /dev/null
@@ -1,90 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) -// -#ifndef CERES_PUBLIC_CODEGEN_COST_FUNCTION_H_ -#define CERES_PUBLIC_CODEGEN_COST_FUNCTION_H_ - -#include "ceres/codegen/macros.h" -#include "ceres/sized_cost_function.h" - -namespace ceres { - -// This is the interface for automatically generating cost functor derivative -// code. The template parameters are identical to those of SizedCostFunction<>. -// The behaviour of this class changes between code generation and problem -// solving. -// -// During code generation (when CERES_CODEGEN is defined), this class doesn't do -// anything. The templated operator() from your derived cost functor is used. -// -// After code generation (when CERES_CODEGEN is not defined), this class is a -// SizedCostFunction. The required Evaluate() function was generated and must be -// included into your cost functor. -// -// Usage Example: -// -// #include "ceres/codegen/cost_function.h" -// -// struct HelloWorldCostFunction : public ceres::CodegenCostFunction<1, 1> { -// // A default constructor is required, because the code generator has to -// // create an object of the cost function. -// HelloWorldCostFunction() = default; -// template <typename T> -// bool operator()(const T* x, T* residual) const { -// residual[0] = x[0] * x[0]; -// return true; -// } -// #include "examples/helloworldcostfunction.h" -// }; - -template <int kNumResiduals_, int... Ns> -class CodegenCostFunction -#ifdef CERES_CODEGEN -// During code generation we can't derive from SizedCostFunction. -// The variadic evaluation with Jets would try to call the empty Evaluate() -// instead of the templated functor. -#else - : public SizedCostFunction<kNumResiduals_, Ns...> -#endif -{ - public: - static constexpr int kNumResiduals = kNumResiduals_; - static_assert(kNumResiduals > 0, - "Cost functions must have at least one residual block."); - static_assert(kNumResiduals != DYNAMIC, - "Code generation for dynamic residuals is not yet supported."); - static_assert(internal::StaticParameterDims<Ns...>::kIsValid, - "Invalid parameter block dimension detected. Each parameter " - "block dimension must be bigger than zero."); - using ParameterDims = internal::StaticParameterDims<Ns...>; -}; - -} // namespace ceres -#endif // CERES_PUBLIC_CODEGEN_COST_FUNCTION_H_
diff --git a/include/ceres/codegen/generate_code_for_functor.h b/include/ceres/codegen/generate_code_for_functor.h deleted file mode 100644 index d7ed09e..0000000 --- a/include/ceres/codegen/generate_code_for_functor.h +++ /dev/null
@@ -1,221 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 Google Inc. All rights reserved. -// http://ceres-solver.org/ -// -// 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) -// -#ifndef CERES_PUBLIC_CODEGEN_AUTODIFF_H_ -#define CERES_PUBLIC_CODEGEN_AUTODIFF_H_ - -#include "ceres/codegen/internal/code_generator.h" -#include "ceres/codegen/internal/expression_graph.h" -#include "ceres/codegen/internal/expression_ref.h" -#include "ceres/internal/autodiff.h" -#include "ceres/jet.h" - -namespace ceres { - -struct AutoDiffCodeGenOptions {}; - -// TODO(darius): Documentation -template <typename DerivedCostFunctor> -std::vector<std::string> GenerateCodeForFunctor( - const AutoDiffCodeGenOptions& options) { - // Define some types and shortcuts to make the code below more readable. - using ParameterDims = typename DerivedCostFunctor::ParameterDims; - using Parameters = typename ParameterDims::Parameters; - // Instead of using scalar Jets, we use Jets of ExpressionRef which record - // their own operations during evaluation. - using ExpressionRef = internal::ExpressionRef; - using ExprJet = Jet<ExpressionRef, ParameterDims::kNumParameters>; - constexpr int kNumResiduals = DerivedCostFunctor::kNumResiduals; - constexpr int kNumParameters = ParameterDims::kNumParameters; - constexpr int kNumParameterBlocks = ParameterDims::kNumParameterBlocks; - - // Create the cost functor using the default constructor. - // Code is generated for the CostFunctor and not an instantiation of it. This - // is different to AutoDiffCostFunction, which computes the derivatives for - // a specific object. - static_assert(std::is_default_constructible<DerivedCostFunctor>::value, - "Cost functors used in code generation must have a default " - "constructor. If you are using local variables, make sure to " - "wrap them into the CERES_LOCAL_VARIABLE macro."); - DerivedCostFunctor functor; - - // During recording phase all operations on ExpressionRefs are recorded to an - // internal data structure, the ExpressionGraph. This ExpressionGraph is then - // optimized and converted back into C++ code. - internal::StartRecordingExpressions(); - - // The Jet arrays are defined after StartRecordingExpressions, because Jets - // are zero-initialized in the default constructor. This already creates - // COMPILE_TIME_CONSTANT expressions. - std::array<ExprJet, kNumParameters> all_parameters; - std::array<ExprJet, kNumResiduals> residuals; - std::array<ExprJet*, kNumParameterBlocks> unpacked_parameters = - ParameterDims::GetUnpackedParameters(all_parameters.data()); - - // Create input expressions that convert from the doubles passed from Ceres - // into codegen Expressions. These inputs are assigned to the scalar part "a" - // of the corresponding Jets. - // - // Example code generated by these expressions: - // v_0 = parameters[0][0]; - // v_1 = parameters[0][1]; - // ... - for (int i = 0; i < kNumParameterBlocks; ++i) { - for (int j = 0; j < ParameterDims::GetDim(i); ++j) { - ExprJet& parameter = unpacked_parameters[i][j]; - parameter.a = internal::MakeInputAssignment<ExpressionRef>( - 0.0, - ("parameters[" + std::to_string(i) + "][" + std::to_string(j) + "]") - .c_str()); - } - } - - // During the array initialization above, the derivative part of the Jets is - // set to zero. Here, we set the correct element to 1. - for (int i = 0; i < kNumParameters; ++i) { - all_parameters[i].v(i) = ExpressionRef(1); - } - - // Run the cost functor with Jets of ExpressionRefs. - // Since we are still in recording mode, all operations of the cost functor - // will be added to the graph. - internal::VariadicEvaluate<ParameterDims>( - functor, unpacked_parameters.data(), residuals.data()); - - // At this point the Jets in 'residuals' contain references to the output - // expressions. Here we add new expressions that assign the generated - // temporaries to the actual residual array. - // - // Example code generated by these expressions: - // residuals[0] = v_200; - // residuals[1] = v_201; - // ... - for (int i = 0; i < kNumResiduals; ++i) { - auto& J = residuals[i]; - // Note: MakeOutput automatically adds the expression to the active graph. - internal::MakeOutput(J.a, "residuals[" + std::to_string(i) + "]"); - } - - // Example code generated by these expressions: - // jacobians[0][0] = v_351; - // jacobians[0][1] = v_352; - // ... - for (int i = 0, total_param_id = 0; i < kNumParameterBlocks; - total_param_id += ParameterDims::GetDim(i), ++i) { - for (int r = 0; r < kNumResiduals; ++r) { - for (int j = 0; j < ParameterDims::GetDim(i); ++j) { - internal::MakeOutput( - (residuals[r].v[total_param_id + j]), - "jacobians[" + std::to_string(i) + "][" + - std::to_string(r * ParameterDims::GetDim(i) + j) + "]"); - } - } - } - - // Stop recording and return the current active graph. Performing operations - // of ExpressionRef after this line will result in an error. - auto residual_and_jacobian_graph = internal::StopRecordingExpressions(); - - // TODO(darius): Once the optimizer is in place, call it from - // here to optimize the code before generating. - - // We have the optimized code of the cost functor stored in the - // ExpressionGraphs. Now we generate C++ code for it and place it line-by-line - // in this vector of strings. - std::vector<std::string> output; - - output.emplace_back("// This file is generated with ceres::AutoDiffCodeGen."); - output.emplace_back("// http://ceres-solver.org/"); - output.emplace_back(""); - - { - // Generate C++ code for the EvaluateResidualAndJacobian function and append - // it to the output. - internal::CodeGenerator::Options generator_options; - generator_options.function_name = - "void EvaluateResidualAndJacobian(double const* const* parameters, " - "double* " - "residuals, double** jacobians) const"; - internal::CodeGenerator gen(residual_and_jacobian_graph, generator_options); - std::vector<std::string> code = gen.Generate(); - output.insert(output.end(), code.begin(), code.end()); - } - - output.emplace_back(""); - - // Generate a generic combined function, which calls EvaluateResidual and - // EvaluateResidualAndJacobian. This combined function is compatible to - // CostFunction::Evaluate. Therefore the generated code can be directly used - // in SizedCostFunctions. - output.emplace_back("bool Evaluate(double const* const* parameters,"); - output.emplace_back(" double* residuals,"); - output.emplace_back(" double** jacobians) const {"); - - output.emplace_back(" if (!jacobians) {"); - output.emplace_back(" // Use the input cost functor"); - output.emplace_back(" return (*this)("); - for (int i = 0; i < kNumParameterBlocks; ++i) { - output.emplace_back(" parameters[" + std::to_string(i) + "],"); - } - output.emplace_back(" residuals"); - output.emplace_back(" );"); - output.emplace_back(" }"); - - // Create a tmp array of all jacobians and use it for evaluation if the input - // jacobian is null. The generated code for a <2,3,1,2> cost functor is: - // double jacobians_data[6]; - // double* jacobians_ptrs[] = { - // jacobians[0] ? jacobians[0] : jacobians_data + 0, - // jacobians[1] ? jacobians[1] : jacobians_data + 6, - // jacobians[2] ? jacobians[2] : jacobians_data + 8, - // }; - output.emplace_back(" double jacobians_data[" + - std::to_string(kNumParameters * kNumResiduals) + "];"); - output.emplace_back(" double* jacobians_ptrs[] = {"); - for (int i = 0, total_param_id = 0; i < kNumParameterBlocks; - total_param_id += ParameterDims::GetDim(i), ++i) { - output.emplace_back(" jacobians[" + std::to_string(i) + - "] ? jacobians[" + std::to_string(i) + - "] : jacobians_data + " + - std::to_string(kNumResiduals * total_param_id) + ","); - } - output.emplace_back(" };"); - output.emplace_back( - " EvaluateResidualAndJacobian(parameters, residuals, " - "jacobians_ptrs);"); - - output.emplace_back(" return true;"); - output.emplace_back("}"); - - return output; -} - -} // namespace ceres -#endif // CERES_PUBLIC_CODEGEN_AUTODIFF_H_
diff --git a/include/ceres/codegen/internal/code_generator.h b/include/ceres/codegen/internal/code_generator.h deleted file mode 100644 index 2b98146..0000000 --- a/include/ceres/codegen/internal/code_generator.h +++ /dev/null
@@ -1,120 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) -// -#ifndef CERES_PUBLIC_CODEGEN_INTERNAL_CODE_GENERATOR_H_ -#define CERES_PUBLIC_CODEGEN_INTERNAL_CODE_GENERATOR_H_ - -#include "ceres/codegen/internal/expression.h" -#include "ceres/codegen/internal/expression_graph.h" - -#include <string> -#include <vector> - -namespace ceres { -namespace internal { - -// This class is used to convert an expression graph into a string. The typical -// pipeline is: -// -// 1. Record ExpressionGraph -// 2. Optimize ExpressionGraph -// 3. Generate C++ code (this class here) -// -// The CodeGenerator operates in the following way: -// -// 1. Print Header -// - The header string is defined in the options. -// - This is usually the function name including the parameter list. -// -// 2. Print Declarations -// - Declare all used variables -// - Example: -// double v_0; -// double v_1; -// bool v_3; -// ... -// -// 3. Print Code -// - Convert each expression line by line to a string -// - Example: -// v_2 = v_0 + v_1 -// if (v_5) { -// v_2 = v_0; -// .... -// -class CodeGenerator { - public: - struct Options { - // Name of the function. - // Example: - // bool Evaluate(const double* x, double* res) - std::string function_name = ""; - - // Number of spaces added for each level of indentation. - int indentation_spaces_per_level = 2; - - // The prefix added to each variable name. - std::string variable_prefix = "v_"; - }; - - CodeGenerator(const ExpressionGraph& graph, const Options& options); - - // Generate the C++ code in the steps (1)-(3) described above. - // The result is a vector of strings, where each element is exactly one line - // of code. The order is important and must not be changed. - std::vector<std::string> Generate(); - - private: - // Converts a single expression given by id to a string. - // The format depends on the ExpressionType. - // See ExpressionType in expression.h for more detailed how the different - // lines will look like. - std::string ExpressionToString(ExpressionId id); - - // Helper function to get the name of an expression. - // If the expression does not have a valid name an error is generated. - std::string VariableForExpressionId(ExpressionId id); - - // Adds one level of indentation. Called when an IF expression is encountered. - void PushIndentation(); - - // Removes one level of indentation. Currently only used by ENDIF. - void PopIndentation(); - - const ExpressionGraph& graph_; - const Options options_; - std::string indentation_ = ""; - static constexpr int kFloatingPointPrecision = 25; -}; - -} // namespace internal -} // namespace ceres - -#endif // CERES_PUBLIC_CODEGEN_INTERNAL_CODE_GENERATOR_H_
diff --git a/include/ceres/codegen/internal/eliminate_nops.h b/include/ceres/codegen/internal/eliminate_nops.h deleted file mode 100644 index 864aa0c..0000000 --- a/include/ceres/codegen/internal/eliminate_nops.h +++ /dev/null
@@ -1,67 +0,0 @@ -// 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) -// -#ifndef CERES_PUBLIC_CODEGEN_INTERNAL_ELIMINATE_NOPS_H_ -#define CERES_PUBLIC_CODEGEN_INTERNAL_ELIMINATE_NOPS_H_ - -#include "ceres/codegen/internal/expression_graph.h" -#include "ceres/codegen/internal/optimization_pass_summary.h" - -namespace ceres { -namespace internal { - -// [OptimizationPass] NOP Cleanup -// -// Short Description: -// Removes all expression with type==ExpressionType::NOP. -// -// Description: -// Removing an expression not at the end requires reindexing of all later -// expressions. Therefore, other optimization passes replace expression with -// NOP instead of removing them. This optimization pass removes all NOPs back -// to front. -// The returned value is equal to the number of removed NOPs. -// -// Example: -// v_0 = 1; -// // NOP -// v_2 = 2; -// v_3 = v_0 + v_2 -// Transforms to: -// v_0 = 1; -// v_1 = 2; -// v_2 = v_0 + v_1; - -OptimizationPassSummary EliminateNops(ExpressionGraph* graph); - -} // namespace internal -} // namespace ceres - -#endif // CERES_PUBLIC_CODEGEN_INTERNAL_ELIMINATE_NOPS_H_
diff --git a/include/ceres/codegen/internal/expression.h b/include/ceres/codegen/internal/expression.h deleted file mode 100644 index 5e1ff2c..0000000 --- a/include/ceres/codegen/internal/expression.h +++ /dev/null
@@ -1,405 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) -// -// During code generation, your cost functor is converted into a list of -// expressions stored in an expression graph. For each operator (+,-,=,...), -// function call (sin,cos,...), and special keyword (if,else,...) the -// appropriate ExpressionType is selected. On a high level all ExpressionTypes -// are grouped into two different classes: Arithmetic expressions and control -// expressions. -// -// Part 1: Arithmetic Expressions -// -// Arithmetic expression are the most basic and common types. They are all of -// the following form: -// -// <lhs> = <rhs> -// -// <lhs> is the variable name on the left hand side of the assignment. <rhs> can -// be different depending on the ExpressionType. It must evaluate to a single -// scalar value though. Here are a few examples of arithmetic expressions (the -// ExpressionType is given on the right): -// -// v_0 = 3.1415; // COMPILE_TIME_CONSTANT -// v_1 = v_0; // ASSIGNMENT -// v_2 = v_0 + v_1; // PLUS -// v_3 = v_2 / v_0; // DIVISION -// v_4 = sin(v_3); // FUNCTION_CALL -// v_5 = v_4 < v_3; // BINARY_COMPARISON -// -// As you can see, the right hand side of each expression contains exactly one -// operator/value/function call. If you write long expressions like -// -// T c = a + b - T(3) * a; -// -// it will broken up into the individual expressions like so: -// -// v_0 = a + b; -// v_1 = 3; -// v_2 = v_1 * a; -// c = v_0 - v_2; -// -// All arithmetic expressions are generated by operator and function -// overloading. These overloads are defined in expression_ref.h. -// -// -// -// Part 2: Control Expressions -// -// Control expressions include special instructions that handle the control flow -// of a program. So far, only if/else is supported, but while/for might come in -// the future. -// -// Generating code for conditional jumps (if/else) is more complicated than -// for arithmetic expressions. Let's look at a small example to see the -// problems. After that we explain how these problems are solved in Ceres. -// -// 1 T a = parameters[0][0]; -// 2 T b = 1.0; -// 3 if (a < b) { -// 4 b = 3.0; -// 5 } else { -// 6 b = 4.0; -// 7 } -// 8 b += 1.0; -// 9 residuals[0] = b; -// -// Problem 1. -// We need to generate code for both branches. In C++ there is no way to execute -// both branches of an if, but we need to execute them to generate the code. -// -// Problem 2. -// The comparison a < b in line 3 is not convertible to bool. Since the value of -// a is not known during code generation, the expression a < b can not be -// evaluated. In fact, a < b will return an expression of type -// BINARY_COMPARISON. -// -// Problem 3. -// There is no way to record that an if was executed. "if" is a special operator -// which cannot be overloaded. Therefore we can't generate code that contains -// "if. -// -// Problem 4. -// We have no information about "blocks" or "scopes" during code generation. -// Even if we could overload the if-operator, there is now way to capture which -// expression was executed in which branches of the if. For example, we generate -// code for the else branch. How can we know that the else branch is finished? -// Is line 8 inside the else-block or already outside? -// -// Solution. -// Instead of using the keywords if/else we insert the macros -// CERES_IF, CERES_ELSE and CERES_ENDIF. These macros just map to a function, -// which inserts an expression into the graph. Here is how the example from -// above looks like with the expanded macros: -// -// 1 T a = parameters[0][0]; -// 2 T b = 1.0; -// 3 CreateIf(a < b); { -// 4 b = 3.0; -// 5 } CreateElse(); { -// 6 b = 4.0; -// 7 } CreateEndif(); -// 8 b += 1.0; -// 9 residuals[0] = b; -// -// Problem 1 solved. -// There are no branches during code generation, therefore both blocks are -// evaluated. -// -// Problem 2 solved. -// The function CreateIf(_) does not take a bool as argument, but an -// ComparisonExpression. Later during code generation an actual "if" is created -// with the condition as argument. -// -// Problem 3 solved. -// We replaced "if" by a function call so we can record it now. -// -// Problem 4 solved. -// Expressions are added into the graph in the correct order. That means, after -// seeing a CreateIf() we know that all following expressions until CreateElse() -// belong to the true-branch. Similar, all expression from CreateElse() to -// CreateEndif() belong to the false-branch. This also works recursively with -// nested ifs. -// -// If you want to use the AutoDiff code generation for your cost functors, you -// have to replace all if/else by the CERES_IF, CERES_ELSE and CERES_ENDIF -// macros. The example from above looks like this: -// -// 1 T a = parameters[0][0]; -// 2 T b = 1.0; -// 3 CERES_IF (a < b) { -// 4 b = 3.0; -// 5 } CERES_ELSE { -// 6 b = 4.0; -// 7 } CERES_ENDIF; -// 8 b += 1.0; -// 9 residuals[0] = b; -// -// These macros don't have a negative impact on performance, because they only -// expand to the CreateIf/.. functions in code generation mode. Otherwise they -// expand to the if/else keywords. See expression_ref.h for the exact -// definition. -// -#ifndef CERES_PUBLIC_CODEGEN_INTERNAL_EXPRESSION_H_ -#define CERES_PUBLIC_CODEGEN_INTERNAL_EXPRESSION_H_ - -#include <string> -#include <vector> - -namespace ceres { -namespace internal { - -using ExpressionId = int; -static constexpr ExpressionId kInvalidExpressionId = -1; - -enum class ExpressionType { - // v_0 = 3.1415; - COMPILE_TIME_CONSTANT, - - // Assignment from a user-variable to a generated variable that can be used by - // other expressions. This is used for local variables of cost functors and - // parameters of a functions. - // v_0 = _observed_point_x; - // v_0 = parameters[0][0]; - INPUT_ASSIGNMENT, - - // Assignment from a generated variable to a user-variable. Used to store the - // output of a generated cost functor. - // residual[0] = v_51; - OUTPUT_ASSIGNMENT, - - // Trivial assignment - // v_3 = v_1 - ASSIGNMENT, - - // Binary Arithmetic Operations - // v_2 = v_0 + v_1 - // The operator is stored in Expression::name_. - BINARY_ARITHMETIC, - - // Unary Arithmetic Operation - // v_1 = -(v_0); - // v_2 = +(v_1); - // The operator is stored in Expression::name_. - UNARY_ARITHMETIC, - - // Binary Comparison. (<,>,&&,...) - // This is the only expressions which returns a 'bool'. - // v_2 = v_0 < v_1 - // The operator is stored in Expression::name_. - BINARY_COMPARISON, - - // The !-operator on logical expression. - LOGICAL_NEGATION, - - // General Function Call. - // v_5 = f(v_0,v_1,...) - FUNCTION_CALL, - - // Conditional control expressions if/else/endif. - // These are special expressions, because they don't define a new variable. - IF, - ELSE, - ENDIF, - - // A single comment line. Even though comments are 'unused' expression they - // will not be optimized away. - COMMENT, - - // No Operation. A placeholder for an 'empty' expressions which will be - // optimized out during code generation. - NOP -}; - -enum class ExpressionReturnType { - // The expression returns a scalar value (float or double). Used for most - // arithmetic operations and function calls. - SCALAR, - // The expression returns a boolean value. Used for logical expressions - // v_3 = v_1 < v_2 - // and functions returning a bool - // v_3 = isfinite(v_1); - BOOLEAN, - // The expressions doesn't return a value. Used for the control - // expressions - // and NOP. - VOID, -}; - -std::string ExpressionReturnTypeToString(ExpressionReturnType type); - -// This class contains all data that is required to generate one line of code. -// Each line has the following form: -// -// lhs = rhs; -// -// The left hand side is the variable name given by its own id. The right hand -// side depends on the ExpressionType. For example, a COMPILE_TIME_CONSTANT -// expressions with id 4 generates the following line: -// v_4 = 3.1415; -// -// Objects of this class are created indirectly using the static CreateXX -// methods. During creation, the Expression objects are added to the -// ExpressionGraph (see expression_graph.h). -class Expression { - public: - // Creates a NOP expression. - Expression() = default; - - Expression(ExpressionType type, - ExpressionReturnType return_type = ExpressionReturnType::VOID, - ExpressionId lhs_id = kInvalidExpressionId, - const std::vector<ExpressionId>& arguments = {}, - const std::string& name = "", - double value = 0); - - // Helper 'constructors' that create an Expression with the correct type. You - // can also use the actual constructor from above, but using the create - // functions is less prone to errors. - static Expression CreateCompileTimeConstant(double v); - - static Expression CreateInputAssignment(const std::string& name); - static Expression CreateOutputAssignment(ExpressionId v, - const std::string& name); - static Expression CreateAssignment(ExpressionId dst, ExpressionId src); - static Expression CreateBinaryArithmetic(const std::string& op, - ExpressionId l, - ExpressionId r); - static Expression CreateUnaryArithmetic(const std::string& op, - ExpressionId v); - static Expression CreateBinaryCompare(const std::string& name, - ExpressionId l, - ExpressionId r); - static Expression CreateLogicalNegation(ExpressionId v); - static Expression CreateScalarFunctionCall( - const std::string& name, const std::vector<ExpressionId>& params); - static Expression CreateLogicalFunctionCall( - const std::string& name, const std::vector<ExpressionId>& params); - static Expression CreateIf(ExpressionId condition); - static Expression CreateElse(); - static Expression CreateEndIf(); - static Expression CreateComment(const std::string& comment); - - // Returns true if this is an arithmetic expression. - // Arithmetic expressions must have a valid left hand side. - bool IsArithmeticExpression() const; - - // Returns true if this is a control expression. - bool IsControlExpression() const; - - // If this expression is the compile time constant with the given value. - // Used during optimization to collapse zero/one arithmetic operations. - // b = a + 0; -> b = a; - bool IsCompileTimeConstantAndEqualTo(double constant) const; - - // Checks if "other" is identical to "this" so that one of the epxressions can - // be replaced by a trivial assignment. Used during common subexpression - // elimination. - bool IsReplaceableBy(const Expression& other) const; - - // Replace this expression by 'other'. - // The current id will be not replaced. That means other experssions - // referencing this one stay valid. - void Replace(const Expression& other); - - // If this expression has 'other' as an argument. - bool DirectlyDependsOn(ExpressionId other) const; - - // Converts this expression into a NOP - void MakeNop(); - - // Returns true if this expression has a valid lhs. - bool HasValidLhs() const { return lhs_id_ != kInvalidExpressionId; } - - // Compares all members with the == operator. If this function succeeds, - // IsSemanticallyEquivalentTo will also return true. - bool operator==(const Expression& other) const; - bool operator!=(const Expression& other) const { return !(*this == other); } - - // Semantically equivalent expressions are similar in a way, that the type(), - // value(), name(), number of arguments is identical. The lhs_id() and the - // argument_ids can differ. For example, the following groups of expressions - // are semantically equivalent: - // - // v_0 = v_1 + v_2; - // v_0 = v_1 + v_3; - // v_1 = v_1 + v_2; - // - // v_0 = sin(v_1); - // v_3 = sin(v_2); - bool IsSemanticallyEquivalentTo(const Expression& other) const; - - ExpressionType type() const { return type_; } - ExpressionReturnType return_type() const { return return_type_; } - ExpressionId lhs_id() const { return lhs_id_; } - double value() const { return value_; } - const std::string& name() const { return name_; } - const std::vector<ExpressionId>& arguments() const { return arguments_; } - - void set_lhs_id(ExpressionId new_lhs_id) { lhs_id_ = new_lhs_id; } - std::vector<ExpressionId>* mutable_arguments() { return &arguments_; } - - private: - ExpressionType type_ = ExpressionType::NOP; - ExpressionReturnType return_type_ = ExpressionReturnType::VOID; - - // If lhs_id_ >= 0, then this expression is assigned to v_<lhs_id>. - // For example: - // v_1 = v_0 + v_0 (Type = PLUS) - // v_3 = sin(v_1) (Type = FUNCTION_CALL) - // ^ - // lhs_id_ - // - // If lhs_id_ == kInvalidExpressionId, then the expression type is not - // arithmetic. Currently, only the following types have lhs_id = invalid: - // IF,ELSE,ENDIF,NOP - ExpressionId lhs_id_ = kInvalidExpressionId; - - // Expressions have different number of arguments. For example a binary "+" - // has 2 parameters and a function call to "sin" has 1 parameter. Here, a - // reference to these paratmers is stored. Note: The order matters! - std::vector<ExpressionId> arguments_; - - // Depending on the type this name is one of the following: - // (type == FUNCTION_CALL) -> the function name - // (type == PARAMETER) -> the parameter name - // (type == OUTPUT_ASSIGN) -> the output variable name - // (type == BINARY_COMPARE)-> the comparison symbol "<","&&",... - // else -> unused - std::string name_; - - // Only valid if type == COMPILE_TIME_CONSTANT - double value_ = 0; -}; - -} // namespace internal -} // namespace ceres - -#endif // CERES_PUBLIC_CODEGEN_INTERNAL_EXPRESSION_H_
diff --git a/include/ceres/codegen/internal/expression_graph.h b/include/ceres/codegen/internal/expression_graph.h deleted file mode 100644 index 7c5df80..0000000 --- a/include/ceres/codegen/internal/expression_graph.h +++ /dev/null
@@ -1,140 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) - -#ifndef CERES_PUBLIC_CODEGEN_INTERNAL_EXPRESSION_GRAPH_H_ -#define CERES_PUBLIC_CODEGEN_INTERNAL_EXPRESSION_GRAPH_H_ - -#include <vector> - -#include "expression.h" - -namespace ceres { -namespace internal { - -// A directed, acyclic, unconnected graph containing all expressions of a -// program. -// -// The expression graph is stored linear in the expressions_ array. The order is -// identical to the execution order. Each expression can have multiple children -// and multiple parents. -// A is child of B <=> B has A as a parameter <=> B.DirectlyDependsOn(A) -// A is parent of B <=> A has B as a parameter <=> A.DirectlyDependsOn(B) -class ExpressionGraph { - public: - // Checks if A depends on B. - // -> B is a descendant of A - bool DependsOn(ExpressionId A, ExpressionId B) const; - - bool operator==(const ExpressionGraph& other) const; - bool operator!=(const ExpressionGraph& other) const { - return !(*this == other); - } - - Expression& ExpressionForId(ExpressionId id) { return expressions_[id]; } - const Expression& ExpressionForId(ExpressionId id) const { - return expressions_[id]; - } - - int Size() const { return expressions_.size(); } - - // Erases the expression at "location". All expression after "location" are - // moved by one element to the front. References to moved expressions are - // updated. Removing an expression that is still referenced somewhere is - // undefined behaviour. - void Erase(ExpressionId location); - - // Insert a new expression at "location" into the graph. All expression - // after "location" are moved by one element to the back. References to - // moved expressions are updated. - void Insert(ExpressionId location, const Expression& expression); - - // Adds an Expression to the end of the expression list and creates a new - // variable for the result. The id of the result variable is returned so it - // can be used for further operations. - ExpressionId InsertBack(const Expression& expression); - - // Finds the closing ENDIF expression for a given IF expression. Calling this - // method is only valid on IF expressions. If no suitable ENDIF is found, - // kInvalidExpressionId is returned. Example: - // <id> <expr> FindMatchingEndif(id) - // 0 IF 7 - // 1 IF 3 - // 2 ELSE - - // 3 ENDIF - - // 4 ELSE - - // 5 IF 6 - // 6 ENDIF - - // 7 ENDIF - - ExpressionId FindMatchingEndif(ExpressionId id) const; - - // Similar to FindMatchingEndif, but returns the matching ELSE expression. If - // no suitable ELSE is found, kInvalidExpressionId is returned. - // FindMatchingElse does not throw an error is this case, because IF without - // ELSE is allowed. - // <id> <expr> FindMatchingEndif(id) - // 0 IF 4 - // 1 IF 2 - // 2 ELSE - - // 3 ENDIF - - // 4 ELSE - - // 5 IF kInvalidEpressionId - // 6 ENDIF - - // 7 ENDIF - - ExpressionId FindMatchingElse(ExpressionId id) const; - - private: - // All Expressions are referenced by an ExpressionId. The ExpressionId is - // the index into this array. Each expression has a list of ExpressionId as - // arguments. These references form the graph. - std::vector<Expression> expressions_; -}; - -// After calling this method, all operations on 'ExpressionRef' objects will -// be recorded into an ExpressionGraph. You can obtain this graph by calling -// StopRecordingExpressions. -// -// Performing expression operations before calling StartRecordingExpressions -// or calling StartRecodring. twice is an error. -void StartRecordingExpressions(); - -// Stops recording and returns all expressions that have been executed since -// the call to StartRecordingExpressions. The internal ExpressionGraph will be -// invalidated and a second consecutive call to this method results in an -// error. -ExpressionGraph StopRecordingExpressions(); - -// Returns a pointer to the active expression tree. -// Normal users should not use this functions. -ExpressionGraph* GetCurrentExpressionGraph(); - -} // namespace internal -} // namespace ceres - -#endif // CERES_PUBLIC_CODEGEN_INTERNAL_EXPRESSION_GRAPH_H_
diff --git a/include/ceres/codegen/internal/expression_ref.h b/include/ceres/codegen/internal/expression_ref.h deleted file mode 100644 index 5499930..0000000 --- a/include/ceres/codegen/internal/expression_ref.h +++ /dev/null
@@ -1,248 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) -// -// TODO: Documentation -#ifndef CERES_PUBLIC_EXPRESSION_REF_H_ -#define CERES_PUBLIC_EXPRESSION_REF_H_ - -#include <string> - -#include "ceres/codegen/internal/expression.h" -#include "ceres/codegen/internal/types.h" - -namespace ceres { -namespace internal { - -// This class represents a scalar value that creates new expressions during -// evaluation. ExpressionRef can be used as template parameter for cost functors -// and Jets. -// -// ExpressionRef should be passed by value. -struct ExpressionRef { - ExpressionRef() : ExpressionRef(0.0) {} - - // Create a compile time constant expression directly from a double value. - // This is important so that we can write T(3.14) in our code and - // it's automatically converted to the correct expression. - // - // This constructor is implicit, because the line - // T a(0); - // must work for T = Jet<ExpressionRef>. - ExpressionRef(double compile_time_constant); - - // Adds the expression to the active graph and initializes this ExpressionRef - // accordingly. - ExpressionRef(const Expression& expression); - - // By adding this deleted constructor we can detect invalid usage of - // ExpressionRef. ExpressionRef must only be created from constexpr doubles. - // - // If you get a compile error here, you have probably written something like: - // T x = local_variable_; - // Change this into: - // T x = CERES_LOCAL_VARIABLE(local_variable_); - ExpressionRef(double&) = delete; - - // Copy construction/assignment creates an ASSIGNMENT expression from - // 'other' to 'this'. - // - // For example: - // a = b; // With a.id = 5 and b.id = 3 - // will generate the following assignment: - // v_5 = v_3; - // - // If 'this' ExpressionRef is currently not pointing to a variable - // (id==invalid), then an assignment to a new variable is generated. Example: - // T a = 5; - // T b; - // b = a; // During the assignment 'b' is invalid - // - // The right hand side of the assignment (= the argument 'other') must be - // valid in every case. The following code will result in an error. - // T a; - // T b = a; // Error: Uninitialized assignment - ExpressionRef(const ExpressionRef& other); - ExpressionRef& operator=(const ExpressionRef& other); - - // Compound operators - ExpressionRef& operator+=(const ExpressionRef& x); - ExpressionRef& operator-=(const ExpressionRef& x); - ExpressionRef& operator*=(const ExpressionRef& x); - ExpressionRef& operator/=(const ExpressionRef& x); - - bool IsInitialized() const { return id != kInvalidExpressionId; } - - // The index into the ExpressionGraph data array. - ExpressionId id = kInvalidExpressionId; -}; - -// A helper function which calls 'InsertBack' on the currently active graph. -// This wrapper also checks if StartRecordingExpressions was called. See -// ExpressionGraph::InsertBack for more information. -ExpressionRef AddExpressionToGraph(const Expression& expression); - -// Arithmetic Operators -ExpressionRef operator-(const ExpressionRef& x); -ExpressionRef operator+(const ExpressionRef& x); -ExpressionRef operator+(const ExpressionRef& x, const ExpressionRef& y); -ExpressionRef operator-(const ExpressionRef& x, const ExpressionRef& y); -ExpressionRef operator*(const ExpressionRef& x, const ExpressionRef& y); -ExpressionRef operator/(const ExpressionRef& x, const ExpressionRef& y); - -// Functions -#define CERES_DEFINE_UNARY_FUNCTION_CALL(ns, name) \ - inline ExpressionRef name(const ExpressionRef& x) { \ - return AddExpressionToGraph( \ - Expression::CreateScalarFunctionCall(#ns "::" #name, {x.id})); \ - } -#define CERES_DEFINE_BINARY_FUNCTION_CALL(ns, name) \ - inline ExpressionRef name(const ExpressionRef& x, const ExpressionRef& y) { \ - return AddExpressionToGraph( \ - Expression::CreateScalarFunctionCall(#ns "::" #name, {x.id, y.id})); \ - } -CERES_DEFINE_UNARY_FUNCTION_CALL(std, abs); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, acos); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, asin); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, atan); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, cbrt); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, ceil); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, cos); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, cosh); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, exp); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, exp2); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, floor); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, log); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, log2); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, sin); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, sinh); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, sqrt); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, tan); -CERES_DEFINE_UNARY_FUNCTION_CALL(std, tanh); - -CERES_DEFINE_BINARY_FUNCTION_CALL(std, atan2); -CERES_DEFINE_BINARY_FUNCTION_CALL(std, pow); - -#undef CERES_DEFINE_UNARY_FUNCTION_CALL -#undef CERES_DEFINE_BINARY_FUNCTION_CALL - -// This additonal type is required, so that we can detect invalid conditions -// during compile time. For example, the following should create a compile time -// error: -// -// ExpressionRef a(5); -// CERES_IF(a){ // Error: Invalid conversion -// ... -// -// Following will work: -// -// ExpressionRef a(5), b(7); -// ComparisonExpressionRef c = a < b; -// CERES_IF(c){ -// ... -struct ComparisonExpressionRef { - ExpressionId id; - explicit ComparisonExpressionRef(const ExpressionRef& ref) : id(ref.id) {} -}; - -ExpressionRef Ternary(const ComparisonExpressionRef& c, - const ExpressionRef& x, - const ExpressionRef& y); - -// Comparison operators -ComparisonExpressionRef operator<(const ExpressionRef& x, - const ExpressionRef& y); -ComparisonExpressionRef operator<=(const ExpressionRef& x, - const ExpressionRef& y); -ComparisonExpressionRef operator>(const ExpressionRef& x, - const ExpressionRef& y); -ComparisonExpressionRef operator>=(const ExpressionRef& x, - const ExpressionRef& y); -ComparisonExpressionRef operator==(const ExpressionRef& x, - const ExpressionRef& y); -ComparisonExpressionRef operator!=(const ExpressionRef& x, - const ExpressionRef& y); - -// Logical Operators -ComparisonExpressionRef operator&&(const ComparisonExpressionRef& x, - const ComparisonExpressionRef& y); -ComparisonExpressionRef operator||(const ComparisonExpressionRef& x, - const ComparisonExpressionRef& y); -ComparisonExpressionRef operator&(const ComparisonExpressionRef& x, - const ComparisonExpressionRef& y); -ComparisonExpressionRef operator|(const ComparisonExpressionRef& x, - const ComparisonExpressionRef& y); -ComparisonExpressionRef operator!(const ComparisonExpressionRef& x); - -#define CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL(ns, name) \ - inline ComparisonExpressionRef name(const ExpressionRef& x) { \ - return ComparisonExpressionRef(AddExpressionToGraph( \ - Expression::CreateLogicalFunctionCall(#ns "::" #name, {x.id}))); \ - } - -CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL(std, isfinite); -CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL(std, isinf); -CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL(std, isnan); -CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL(std, isnormal); - -#undef CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL - -template <> -struct InputAssignment<ExpressionRef> { - using ReturnType = ExpressionRef; - static inline ReturnType Get(double /* unused */, const char* name) { - // Note: The scalar value of v will be thrown away, because we don't need it - // during code generation. - return AddExpressionToGraph(Expression::CreateInputAssignment(name)); - } -}; - -template <typename T> -inline typename InputAssignment<T>::ReturnType MakeInputAssignment( - double v, const char* name) { - return InputAssignment<T>::Get(v, name); -} - -inline ExpressionRef MakeParameter(const std::string& name) { - return AddExpressionToGraph(Expression::CreateInputAssignment(name)); -} -inline ExpressionRef MakeOutput(const ExpressionRef& v, - const std::string& name) { - return AddExpressionToGraph(Expression::CreateOutputAssignment(v.id, name)); -} - -} // namespace internal - -template <> -struct ComparisonReturnType<internal::ExpressionRef> { - using type = internal::ComparisonExpressionRef; -}; - -} // namespace ceres -#endif
diff --git a/include/ceres/codegen/internal/optimization_pass_summary.h b/include/ceres/codegen/internal/optimization_pass_summary.h deleted file mode 100644 index 1e376af..0000000 --- a/include/ceres/codegen/internal/optimization_pass_summary.h +++ /dev/null
@@ -1,51 +0,0 @@ -// 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) -// -#ifndef CERES_PUBLIC_CODEGEN_INTERNAL_OPTIMIZATION_PASS_SUMMARY_H_ -#define CERES_PUBLIC_CODEGEN_INTERNAL_OPTIMIZATION_PASS_SUMMARY_H_ - -#include <string> - -namespace ceres { -namespace internal { - -struct OptimizationPassSummary { - bool expression_graph_changed = false; - std::string optimization_pass_name; - int num_expressions_replaced_by_nop = 0; - int num_expressions_removed = 0; - int num_expressions_inserted = 0; - int num_expressions_modified = 0; -}; - -} // namespace internal -} // namespace ceres - -#endif // CERES_PUBLIC_CODEGEN_INTERNAL_OPTIMIZATION_PASS_SUMMARY_H_
diff --git a/include/ceres/codegen/internal/optimize_expression_graph.h b/include/ceres/codegen/internal/optimize_expression_graph.h deleted file mode 100644 index 8e06e8b..0000000 --- a/include/ceres/codegen/internal/optimize_expression_graph.h +++ /dev/null
@@ -1,74 +0,0 @@ -// 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) -// -#ifndef CERES_PUBLIC_CODEGEN_INTERNAL_OPTIMIZE_EXPRESSION_GRAPH_H_ -#define CERES_PUBLIC_CODEGEN_INTERNAL_OPTIMIZE_EXPRESSION_GRAPH_H_ - -#include <memory> -#include <vector> - -#include "ceres/codegen/internal/expression_graph.h" -#include "ceres/codegen/internal/optimization_pass_summary.h" - -namespace ceres { -namespace internal { - -struct OptimizeExpressionGraphOptions { - int max_num_iterations = 100; - bool eliminate_nops = true; -}; - -struct OptimizeExpressionGraphSummary { - int num_iterations; - std::vector<OptimizationPassSummary> summaries; -}; - -// Optimize the given ExpressionGraph in-place according to the defined -// OptimizeExpressionGraphOptions. This will change the ExpressionGraph, but the -// generated code will output the same numerical values. -// -// The Optimization iteratively applies all OptimizationPasses until the graph -// does not change anymore or max_num_iterations is reached. Pseudo Code: -// -// for(int it = 0; it < max_num_iterations; ++it) { -// graph.hasChanged = false; -// for each pass in OptimizationPasses -// pass.applyTo(graph) -// if(!graph.hasChanged) -// break; -// } -// -OptimizeExpressionGraphSummary OptimizeExpressionGraph( - const OptimizeExpressionGraphOptions& options, ExpressionGraph* graph); - -} // namespace internal -} // namespace ceres - -#endif // CERES_PUBLIC_CODEGEN_INTERNAL_OPTIMIZE_EXPRESSION_GRAPH_H_
diff --git a/include/ceres/codegen/internal/types.h b/include/ceres/codegen/internal/types.h deleted file mode 100644 index 5d32d5b..0000000 --- a/include/ceres/codegen/internal/types.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) -// -#ifndef CERES_PUBLIC_CODEGEN_INTERNAL_TYPES_H_ -#define CERES_PUBLIC_CODEGEN_INTERNAL_TYPES_H_ - -#include "ceres/codegen/macros.h" - -namespace ceres { -// The return type of a comparison, for example from <, &&, ==. -// -// In the context of traditional Ceres Jet operations, this would -// always be a bool. However, in the autodiff code generation context, -// the return is always an expression, and so a different type must be -// used as a return from comparisons. -// -// In the autodiff codegen context, this function is overloaded so that 'type' -// is one of the autodiff code generation expression types. -template <typename T> -struct ComparisonReturnType { - using type = bool; -}; - -namespace internal { -// The InputAssignment struct is used to implement the CERES_LOCAL_VARIABLE -// macro defined in macros.h. The input is a double variable and the -// corresponding name as a string. During execution mode (T==double or -// T==Jet<double>) the variable name is unused and this function only returns -// the value. During code generation (T==ExpressionRef) the value is unused and -// an assignment expression is created. For example: -// v_0 = observed_x; -template <typename T> -struct InputAssignment { - static inline T Get(double v, const char* /* unused */) { return v; } -}; - -} // namespace internal -} // namespace ceres - -#endif // CERES_PUBLIC_CODEGEN_INTERNAL_TYPES_H_
diff --git a/include/ceres/codegen/macros.h b/include/ceres/codegen/macros.h deleted file mode 100644 index d3a43a6..0000000 --- a/include/ceres/codegen/macros.h +++ /dev/null
@@ -1,129 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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 defines the required macros to use local variables and if-else -// branches in the AutoDiffCodeGen system. This is also the only file that -// should be included by a user-defined cost functor. -// -// To generate code for your cost functor the following steps have to be -// implemented (see below for a full example): -// -// 1. Include this file -// 2. Wrap accesses to local variables in the CERES_LOCAL_VARIABLE macro. -// 3. Replace if, else by CERES_IF, CERES_ELSE and add CERES_ENDIF -// 4. Add a default constructor -// -// Example - my_cost_functor.h -// ======================================================== -// #include "ceres/rotation.h" -// #include "ceres/autodiff_codegen_macros.h" -// -// struct MyReprojectionError { -// MyReprojectionError(double observed_x, double observed_y) -// : observed_x(observed_x), observed_y(observed_y) {} -// -// // The cost functor must be default constructible! -// MyReprojectionError() = default; -// -// template <typename T> -// bool operator()(const T* const camera, -// const T* const point, -// T* residuals) const { -// T p[3]; -// AngleAxisRotatePoint(camera, point, p); -// p[0] += camera[3]; -// p[1] += camera[4]; -// p[2] += camera[5]; -// -// // The if block is written using the macros! -// CERES_IF(p[2] < T(0)) { -// p[0] = -p[0]; -// p[1] = -p[1]; -// p[2] = -p[2]; -// } CERES_ELSE { -// p[0] += T(1.0); -// }CERES_ENDIF; -// -// const T& focal = camera[6]; -// const T predicted_x = focal * p[0]; -// const T predicted_y = focal * p[1]; -// -// // The read-access to the local variables observed_x and observed_y are -// // wrapped in the CERES_LOCAL_VARIABLE macro! -// residuals[0] = predicted_x - CERES_LOCAL_VARIABLE(T, observed_x); -// residuals[1] = predicted_y - CERES_LOCAL_VARIABLE(T, observed_y); -// return true; -// } -// double observed_x; -// double observed_y; -// }; -// -// ======================================================== -// -// This file defines the following macros: -// -// CERES_LOCAL_VARIABLE -// CERES_IF -// CERES_ELSE -// CERES_ENDIF -// -#ifndef CERES_PUBLIC_CODEGEN_MACROS_H_ -#define CERES_PUBLIC_CODEGEN_MACROS_H_ - -// The CERES_CODEGEN macro is defined by the build system only during code -// generation. -#ifndef CERES_CODEGEN -#define CERES_LOCAL_VARIABLE(type, local_variable) type(local_variable) -#define CERES_IF(condition_) if (condition_) -#define CERES_ELSE else -#define CERES_ENDIF -#define CERES_COMMENT(comment_) -#else -#define CERES_LOCAL_VARIABLE(_template_type, _local_variable) \ - ceres::internal::InputAssignment<_template_type>::Get(_local_variable, \ - #_local_variable) -#define CERES_IF(condition_) \ - AddExpressionToGraph(ceres::internal::Expression::CreateIf((condition_).id)); -#define CERES_ELSE \ - AddExpressionToGraph(ceres::internal::Expression::CreateElse()); -#define CERES_ENDIF \ - AddExpressionToGraph(ceres::internal::Expression::CreateEndIf()); -#define CERES_COMMENT(comment_) \ - AddExpressionToGraph(ceres::internal::Expression::CreateComment(comment_)) -#endif - -namespace ceres { -// A function equivalent to the ternary ?-operator. -// This function is required, because in the context of code generation a -// comparison returns an expression type which is not convertible to bool. -inline double Ternary(bool c, double a, double b) { return c ? a : b; } -} // namespace ceres - -#endif // CERES_PUBLIC_CODEGEN_MACROS_H_
diff --git a/include/ceres/jet.h b/include/ceres/jet.h index 1f81743..966e1b8 100644 --- a/include/ceres/jet.h +++ b/include/ceres/jet.h
@@ -164,7 +164,6 @@ #include <string> #include "Eigen/Core" -#include "ceres/codegen/internal/types.h" #include "ceres/internal/port.h" namespace ceres { @@ -354,21 +353,18 @@ } // Binary comparison operators for both scalars and jets. -#define CERES_DEFINE_JET_COMPARISON_OPERATOR(op) \ - template <typename T, int N> \ - inline typename ComparisonReturnType<T>::type operator op( \ - const Jet<T, N>& f, const Jet<T, N>& g) { \ - return f.a op g.a; \ - } \ - template <typename T, int N> \ - inline typename ComparisonReturnType<T>::type operator op( \ - const T& s, const Jet<T, N>& g) { \ - return s op g.a; \ - } \ - template <typename T, int N> \ - inline typename ComparisonReturnType<T>::type operator op( \ - const Jet<T, N>& f, const T& s) { \ - return f.a op s; \ +#define CERES_DEFINE_JET_COMPARISON_OPERATOR(op) \ + template <typename T, int N> \ + inline bool operator op(const Jet<T, N>& f, const Jet<T, N>& g) { \ + return f.a op g.a; \ + } \ + template <typename T, int N> \ + inline bool operator op(const T& s, const Jet<T, N>& g) { \ + return s op g.a; \ + } \ + template <typename T, int N> \ + inline bool operator op(const Jet<T, N>& f, const T& s) { \ + return f.a op s; \ } CERES_DEFINE_JET_COMPARISON_OPERATOR(<) // NOLINT CERES_DEFINE_JET_COMPARISON_OPERATOR(<=) // NOLINT @@ -378,18 +374,6 @@ CERES_DEFINE_JET_COMPARISON_OPERATOR(!=) // NOLINT #undef CERES_DEFINE_JET_COMPARISON_OPERATOR -template <typename T, int N> -inline Jet<T, N> Ternary(typename ComparisonReturnType<T>::type c, - const Jet<T, N>& f, - const Jet<T, N>& g) { - Jet<T, N> r; - r.a = Ternary(c, f.a, g.a); - for (int i = 0; i < N; ++i) { - r.v[i] = Ternary(c, f.v[i], g.v[i]); - } - return r; -} - // Pull some functions from namespace std. // // This is necessary because we want to use the same name (e.g. 'sqrt') for @@ -436,7 +420,7 @@ // abs(x + h) ~= x + h or -(x + h) template <typename T, int N> inline Jet<T, N> abs(const Jet<T, N>& f) { - return Ternary(f.a < T(0.0), -f, f); + return (f.a < T(0.0) ? -f : f); } // log(a + h) ~= log(a) + h / a @@ -581,12 +565,12 @@ template <typename T, int N> inline Jet<T, N> fmax(const Jet<T, N>& x, const Jet<T, N>& y) { - return Ternary(x < y, y, x); + return x < y ? y : x; } template <typename T, int N> inline Jet<T, N> fmin(const Jet<T, N>& x, const Jet<T, N>& y) { - return Ternary(y < x, y, x); + return y < x ? y : x; } // Bessel functions of the first kind with integer order equal to 0, 1, n. @@ -659,7 +643,7 @@ // The jet is finite if all parts of the jet are finite. template <typename T, int N> -inline typename ComparisonReturnType<T>::type isfinite(const Jet<T, N>& f) { +inline bool isfinite(const Jet<T, N>& f) { // Branchless implementation. This is more efficient for the false-case and // works with the codegen system. auto result = isfinite(f.a); @@ -671,7 +655,7 @@ // The jet is infinite if any part of the Jet is infinite. template <typename T, int N> -inline typename ComparisonReturnType<T>::type isinf(const Jet<T, N>& f) { +inline bool isinf(const Jet<T, N>& f) { auto result = isinf(f.a); for (int i = 0; i < N; ++i) { result = result | isinf(f.v[i]); @@ -681,7 +665,7 @@ // The jet is NaN if any part of the jet is NaN. template <typename T, int N> -inline typename ComparisonReturnType<T>::type isnan(const Jet<T, N>& f) { +inline bool isnan(const Jet<T, N>& f) { auto result = isnan(f.a); for (int i = 0; i < N; ++i) { result = result | isnan(f.v[i]); @@ -691,7 +675,7 @@ // The jet is normal if all parts of the jet are normal. template <typename T, int N> -inline typename ComparisonReturnType<T>::type isnormal(const Jet<T, N>& f) { +inline bool isnormal(const Jet<T, N>& f) { auto result = isnormal(f.a); for (int i = 0; i < N; ++i) { result = result & isnormal(f.v[i]); @@ -701,23 +685,23 @@ // Legacy functions from the pre-C++11 days. template <typename T, int N> -inline typename ComparisonReturnType<T>::type IsFinite(const Jet<T, N>& f) { +inline bool IsFinite(const Jet<T, N>& f) { return isfinite(f); } template <typename T, int N> -inline typename ComparisonReturnType<T>::type IsNaN(const Jet<T, N>& f) { +inline bool IsNaN(const Jet<T, N>& f) { return isnan(f); } template <typename T, int N> -inline typename ComparisonReturnType<T>::type IsNormal(const Jet<T, N>& f) { +inline bool IsNormal(const Jet<T, N>& f) { return isnormal(f); } // The jet is infinite if any part of the jet is infinite. template <typename T, int N> -inline typename ComparisonReturnType<T>::type IsInfinite(const Jet<T, N>& f) { +inline bool IsInfinite(const Jet<T, N>& f) { return isinf(f); } @@ -759,29 +743,25 @@ inline Jet<T, N> pow(T f, const Jet<T, N>& g) { Jet<T, N> result; - CERES_IF(f == T(0) && g.a > T(0)) { + if (f == T(0) && g.a > T(0)) { // Handle case 2. result = Jet<T, N>(T(0.0)); - } - CERES_ELSE { - CERES_IF(f < 0 && g.a == floor(g.a)) { // Handle case 3. + } else { + if (f < 0 && g.a == floor(g.a)) { // Handle case 3. result = Jet<T, N>(pow(f, g.a)); for (int i = 0; i < N; i++) { - CERES_IF(g.v[i] != T(0.0)) { + if (g.v[i] != T(0.0)) { // Return a NaN when g.v != 0. result.v[i] = std::numeric_limits<T>::quiet_NaN(); } - CERES_ENDIF } - } - CERES_ELSE { + } else { // Handle case 1. T const tmp = pow(f, g.a); result = Jet<T, N>(tmp, log(f) * tmp * g.v); } - CERES_ENDIF; } - CERES_ENDIF + return result; } @@ -825,26 +805,26 @@ inline Jet<T, N> pow(const Jet<T, N>& f, const Jet<T, N>& g) { Jet<T, N> result; - CERES_IF(f.a == T(0) && g.a >= T(1)) { + if (f.a == T(0) && g.a >= T(1)) { // Handle cases 2 and 3. - CERES_IF(g.a > T(1)) { result = Jet<T, N>(T(0.0)); } - CERES_ELSE { result = f; } - CERES_ENDIF; - } - CERES_ELSE { - CERES_IF(f.a < T(0) && g.a == floor(g.a)) { + if (g.a > T(1)) { + result = Jet<T, N>(T(0.0)); + } else { + result = f; + } + + } else { + if (f.a < T(0) && g.a == floor(g.a)) { // Handle cases 7 and 8. T const tmp = g.a * pow(f.a, g.a - T(1.0)); result = Jet<T, N>(pow(f.a, g.a), tmp * f.v); for (int i = 0; i < N; i++) { - CERES_IF(g.v[i] != T(0.0)) { + if (g.v[i] != T(0.0)) { // Return a NaN when g.v != 0. result.v[i] = T(std::numeric_limits<double>::quiet_NaN()); } - CERES_ENDIF; } - } - CERES_ELSE { + } else { // Handle the remaining cases. For cases 4,5,6,9 we allow the log() // function to generate -HUGE_VAL or NaN, since those cases result in a // nonfinite derivative. @@ -853,9 +833,8 @@ T const tmp3 = tmp1 * log(f.a); result = Jet<T, N>(tmp1, tmp2 * f.v + tmp3 * g.v); } - CERES_ENDIF; } - CERES_ENDIF; + return result; } @@ -874,19 +853,6 @@ s << "]"; return s; } - -namespace internal { -// In the context of AutoDiffCodeGen, local variables can be added using the -// CERES_LOCAL_VARIABLE macro defined in ceres/codegen/macros.h. This partial -// specialization defined how local variables of type double are converted to -// Jet<T>. -template <typename T, int N> -struct InputAssignment<Jet<T, N>> { - static inline Jet<T, N> Get(double v, const char* name) { - return Jet<T, N>(InputAssignment<T>::Get(v, name)); - } -}; -} // namespace internal } // namespace ceres namespace Eigen {
diff --git a/include/ceres/rotation.h b/include/ceres/rotation.h index ce06a2c..7d5c8ef 100644 --- a/include/ceres/rotation.h +++ b/include/ceres/rotation.h
@@ -48,7 +48,7 @@ #include <algorithm> #include <cmath> #include <limits> -#include "codegen/macros.h" + #include "glog/logging.h" namespace ceres { @@ -253,7 +253,7 @@ const T theta_squared = a0 * a0 + a1 * a1 + a2 * a2; // For points not at the origin, the full conversion is numerically stable. - CERES_IF(theta_squared > T(0.0)) { + if (theta_squared > T(0.0)) { const T theta = sqrt(theta_squared); const T half_theta = theta * T(0.5); const T k = sin(half_theta) / theta; @@ -261,8 +261,7 @@ quaternion[1] = a0 * k; quaternion[2] = a1 * k; quaternion[3] = a2 * k; - } - CERES_ELSE { + } else { // At the origin, sqrt() will produce NaN in the derivative since // the argument is zero. By approximating with a Taylor series, // and truncating at one term, the value and first derivatives will be @@ -273,7 +272,6 @@ quaternion[2] = a1 * k; quaternion[3] = a2 * k; } - CERES_ENDIF; } template <typename T> @@ -285,7 +283,7 @@ // For quaternions representing non-zero rotation, the conversion // is numerically stable. - CERES_IF(sin_squared_theta > T(0.0)) { + if (sin_squared_theta > T(0.0)) { const T sin_theta = sqrt(sin_squared_theta); const T& cos_theta = quaternion[0]; @@ -302,15 +300,14 @@ // theta - pi = atan(sin(theta - pi), cos(theta - pi)) // = atan(-sin(theta), -cos(theta)) // - const T two_theta = T(2.0) * Ternary((cos_theta < T(0.0)), - atan2(-sin_theta, -cos_theta), - atan2(sin_theta, cos_theta)); + const T two_theta = + T(2.0) * ((cos_theta < T(0.0)) ? atan2(-sin_theta, -cos_theta) + : atan2(sin_theta, cos_theta)); const T k = two_theta / sin_theta; angle_axis[0] = q1 * k; angle_axis[1] = q2 * k; angle_axis[2] = q3 * k; - } - CERES_ELSE { + } else { // For zero rotation, sqrt() will produce NaN in the derivative since // the argument is zero. By approximating with a Taylor series, // and truncating at one term, the value and first derivatives will be @@ -320,7 +317,6 @@ angle_axis[1] = q2 * k; angle_axis[2] = q3 * k; } - CERES_ENDIF; } template <typename T> @@ -391,7 +387,7 @@ const T* angle_axis, const MatrixAdapter<T, row_stride, col_stride>& R) { static const T kOne = T(1.0); const T theta2 = DotProduct(angle_axis, angle_axis); - CERES_IF(theta2 > T(std::numeric_limits<double>::epsilon())) { + if (theta2 > T(std::numeric_limits<double>::epsilon())) { // We want to be careful to only evaluate the square root if the // norm of the angle_axis vector is greater than zero. Otherwise // we get a division by zero. @@ -414,8 +410,7 @@ R(1, 2) = -wx*sintheta + wy*wz*(kOne - costheta); R(2, 2) = costheta + wz*wz*(kOne - costheta); // clang-format on - } - CERES_ELSE { + } else { // Near zero, we switch to using the first order Taylor expansion. R(0, 0) = kOne; R(1, 0) = angle_axis[2]; @@ -427,7 +422,6 @@ R(1, 2) = -angle_axis[0]; R(2, 2) = kOne; } - CERES_ENDIF; } template <typename T> @@ -597,7 +591,7 @@ DCHECK_NE(pt, result) << "Inplace rotation is not supported."; const T theta2 = DotProduct(angle_axis, angle_axis); - CERES_IF(theta2 > T(std::numeric_limits<double>::epsilon())) { + if (theta2 > T(std::numeric_limits<double>::epsilon())) { // Away from zero, use the rodriguez formula // // result = pt costheta + @@ -628,8 +622,7 @@ result[0] = pt[0] * costheta + w_cross_pt[0] * sintheta + w[0] * tmp; result[1] = pt[1] * costheta + w_cross_pt[1] * sintheta + w[1] * tmp; result[2] = pt[2] * costheta + w_cross_pt[2] * sintheta + w[2] * tmp; - } - CERES_ELSE { + } else { // Near zero, the first order Taylor approximation of the rotation // matrix R corresponding to a vector w and angle w is // @@ -655,7 +648,6 @@ result[1] = pt[1] + w_cross_pt[1]; result[2] = pt[2] + w_cross_pt[2]; } - CERES_ENDIF; } } // namespace ceres
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index 95579da..3711222 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -148,18 +148,6 @@ wall_time.cc ) -if(CODE_GENERATION) - set(CERES_CODEGEN_SRC - codegen/code_generator.cc - codegen/expression.cc - codegen/expression_graph.cc - codegen/expression_ref.cc - codegen/optimize_expression_graph.cc - codegen/eliminate_nops.cc - ) - list(APPEND CERES_INTERNAL_SRC ${CERES_CODEGEN_SRC}) -endif(CODE_GENERATION) - # Also depend on the header files so that they appear in IDEs. file(GLOB CERES_INTERNAL_HDRS *.h) if (MINIGLOG)
diff --git a/internal/ceres/autodiff_benchmarks/snavely_reprojection_error.h b/internal/ceres/autodiff_benchmarks/snavely_reprojection_error.h index b1b5081..8da8bea 100644 --- a/internal/ceres/autodiff_benchmarks/snavely_reprojection_error.h +++ b/internal/ceres/autodiff_benchmarks/snavely_reprojection_error.h
@@ -36,7 +36,7 @@ namespace ceres { -struct SnavelyReprojectionError { +struct SnavelyReprojectionError { SnavelyReprojectionError(double observed_x, double observed_y) : observed_x(observed_x), observed_y(observed_y) {} @@ -45,8 +45,8 @@ bool operator()(const T* const camera, const T* const point, T* residuals) const { - T ox = CERES_LOCAL_VARIABLE(T, observed_x); - T oy = CERES_LOCAL_VARIABLE(T, observed_y); + T ox = T(observed_x); + T oy = T(observed_y); // camera[0,1,2] are the angle-axis rotation. T p[3];
diff --git a/internal/ceres/codegen/code_generator.cc b/internal/ceres/codegen/code_generator.cc deleted file mode 100644 index 7b5fd61..0000000 --- a/internal/ceres/codegen/code_generator.cc +++ /dev/null
@@ -1,292 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) - -#include "ceres/codegen/internal/code_generator.h" - -#include <cmath> -#include <limits> -#include <sstream> - -#include "assert.h" -#include "glog/logging.h" -namespace ceres { -namespace internal { - -CodeGenerator::CodeGenerator(const ExpressionGraph& graph, - const Options& options) - : graph_(graph), options_(options) {} - -std::vector<std::string> CodeGenerator::Generate() { - std::vector<std::string> code; - - // 1. Print the header - if (!options_.function_name.empty()) { - code.emplace_back(options_.function_name); - } - - code.emplace_back("{"); - PushIndentation(); - - // 2. Print declarations - for (ExpressionId id = 0; id < graph_.Size(); ++id) { - // By definition of the lhs_id, an expression defines a new variable only if - // the current_id is identical to the lhs_id. - const auto& expr = graph_.ExpressionForId(id); - if (id != expr.lhs_id()) { - continue; - } - // - // Format: <type> <id>; - // Example: double v_0; - // - const std::string declaration_string = - indentation_ + ExpressionReturnTypeToString(expr.return_type()) + " " + - VariableForExpressionId(id) + ";"; - code.emplace_back(declaration_string); - } - - // 3. Print code - for (ExpressionId id = 0; id < graph_.Size(); ++id) { - code.emplace_back(ExpressionToString(id)); - } - - PopIndentation(); - CHECK(indentation_.empty()) << "IF - ENDIF missmatch detected."; - code.emplace_back("}"); - - return code; -} - -std::string CodeGenerator::ExpressionToString(ExpressionId id) { - // An expression is converted into a string, by first adding the required - // indentation spaces and then adding a ExpressionType-specific string. The - // following list shows the exact output format for each ExpressionType. The - // placeholders <value>, <name>,... stand for the respective members value_, - // name_, ... of the current expression. ExpressionIds such as lhs_id and - // arguments are converted to the corresponding variable name (7 -> "v_7"). - - auto& expr = graph_.ExpressionForId(id); - - std::stringstream result; - result.precision(kFloatingPointPrecision); - - // Convert the variable names of lhs and arguments to string. This makes the - // big switch/case below more readable. - std::string lhs; - if (expr.HasValidLhs()) { - lhs = VariableForExpressionId(expr.lhs_id()); - } - std::vector<std::string> args; - for (ExpressionId id : expr.arguments()) { - args.push_back(VariableForExpressionId(id)); - } - auto value = expr.value(); - const auto& name = expr.name(); - - switch (expr.type()) { - case ExpressionType::COMPILE_TIME_CONSTANT: { - // - // Format: <lhs_id> = <value>; - // Example: v_0 = 3.1415; - // - result << indentation_ << lhs << " = "; - - // Putting an inf or nan double into std::stringstream will just print the - // strings "inf" and "nan". This is not valid C++ code so we have to check - // for this here. - if (std::isinf(value)) { - if (value > 0) { - result << "std::numeric_limits<double>::infinity()"; - } else { - result << "-std::numeric_limits<double>::infinity()"; - } - } else if (std::isnan(value)) { - result << "std::numeric_limits<double>::quiet_NaN()"; - } else { - result << value; - } - result << ";"; - break; - } - case ExpressionType::INPUT_ASSIGNMENT: { - // - // Format: <lhs_id> = <name>; - // Example: v_0 = _observed_point_x; - // - result << indentation_ << lhs << " = " << name << ";"; - break; - } - case ExpressionType::OUTPUT_ASSIGNMENT: { - // - // Format: <name> = <arguments[0]>; - // Example: residual[0] = v_51; - // - result << indentation_ << name << " = " << args[0] << ";"; - break; - } - case ExpressionType::ASSIGNMENT: { - // - // Format: <lhs_id> = <arguments[0]>; - // Example: v_1 = v_0; - // - result << indentation_ << lhs << " = " << args[0] << ";"; - break; - } - case ExpressionType::BINARY_ARITHMETIC: { - // - // Format: <lhs_id> = <arguments[0]> <name> <arguments[1]>; - // Example: v_2 = v_0 + v_1; - // - result << indentation_ << lhs << " = " << args[0] << " " << name << " " - << args[1] << ";"; - break; - } - case ExpressionType::UNARY_ARITHMETIC: { - // - // Format: <lhs_id> = <name><arguments[0]>; - // Example: v_1 = -v_0; - // - result << indentation_ << lhs << " = " << name << args[0] << ";"; - break; - } - case ExpressionType::BINARY_COMPARISON: { - // - // Format: <lhs_id> = <arguments[0]> <name> <arguments[1]>; - // Example: v_2 = v_0 < v_1; - // - result << indentation_ << lhs << " = " << args[0] << " " << name << " " - << args[1] << ";"; - break; - } - case ExpressionType::LOGICAL_NEGATION: { - // - // Format: <lhs_id> = !<arguments[0]>; - // Example: v_1 = !v_0; - // - result << indentation_ << lhs << " = !" << args[0] << ";"; - break; - } - case ExpressionType::FUNCTION_CALL: { - // - // Format: <lhs_id> = <name>(<arguments[0]>, <arguments[1]>, ...); - // Example: v_1 = sin(v_0); - // - result << indentation_ << lhs << " = " << name << "("; - result << (args.size() ? args[0] : ""); - for (int i = 1; i < args.size(); ++i) { - result << ", " << args[i]; - } - result << ");"; - break; - } - case ExpressionType::IF: { - // - // Format: if (<arguments[0]>) { - // Example: if (v_0) { - // Special: Adds 1 level of indentation for all following - // expressions. - // - result << indentation_ << "if (" << args[0] << ") {"; - PushIndentation(); - break; - } - case ExpressionType::ELSE: { - // - // Format: } else { - // Example: } else { - // Special: This expression is printed with one less level of - // indentation. - // - PopIndentation(); - result << indentation_ << "} else {"; - PushIndentation(); - break; - } - case ExpressionType::ENDIF: { - // - // Format: } - // Example: } - // Special: Removes 1 level of indentation for this and all - // following expressions. - // - PopIndentation(); - result << indentation_ << "}"; - break; - } - case ExpressionType::COMMENT: { - // - // Format: // <name> - // Example: // this is a comment - // - result << indentation_ << "// " + name; - break; - } - case ExpressionType::NOP: { - // - // Format: // <NOP> - // Example: // <NOP> - // - result << indentation_ << "// <NOP>"; - break; - } - default: - CHECK(false) << "CodeGenerator::ToString for ExpressionType " - << static_cast<int>(expr.type()) << " not implemented!"; - } - return result.str(); -} - -std::string CodeGenerator::VariableForExpressionId(ExpressionId id) { - // - // Format: <variable_prefix><id> - // Example: v_42 - // - auto& expr = graph_.ExpressionForId(id); - CHECK(expr.lhs_id() == id) - << "ExpressionId " << id - << " does not have a name (it has not been declared)."; - return options_.variable_prefix + std::to_string(expr.lhs_id()); -} - -void CodeGenerator::PushIndentation() { - for (int i = 0; i < options_.indentation_spaces_per_level; ++i) { - indentation_.push_back(' '); - } -} - -void CodeGenerator::PopIndentation() { - for (int i = 0; i < options_.indentation_spaces_per_level; ++i) { - CHECK(!indentation_.empty()) << "IF - ENDIF missmatch detected."; - indentation_.pop_back(); - } -} - -} // namespace internal -} // namespace ceres
diff --git a/internal/ceres/codegen/eliminate_nops.cc b/internal/ceres/codegen/eliminate_nops.cc deleted file mode 100644 index f94a873..0000000 --- a/internal/ceres/codegen/eliminate_nops.cc +++ /dev/null
@@ -1,55 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) - -#include "ceres/codegen/internal/eliminate_nops.h" - -#include "glog/logging.h" - -namespace ceres { -namespace internal { - -OptimizationPassSummary EliminateNops(ExpressionGraph* graph) { - OptimizationPassSummary summary; - - for (ExpressionId id = 0; id < graph->Size(); ++id) { - Expression& expr = graph->ExpressionForId(id); - - if (expr.type() == ExpressionType::NOP) { - graph->Erase(id); - id--; - summary.expression_graph_changed = true; - summary.num_expressions_removed++; - } - } - return summary; -} - -} // namespace internal -} // namespace ceres
diff --git a/internal/ceres/codegen/expression.cc b/internal/ceres/codegen/expression.cc deleted file mode 100644 index 1a475b3..0000000 --- a/internal/ceres/codegen/expression.cc +++ /dev/null
@@ -1,225 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) - -#include "ceres/codegen/internal/expression.h" -#include <algorithm> -#include "glog/logging.h" - -namespace ceres { -namespace internal { - -std::string ExpressionReturnTypeToString(ExpressionReturnType type) { - switch (type) { - case ExpressionReturnType::SCALAR: - return "double"; - case ExpressionReturnType::BOOLEAN: - return "bool"; - case ExpressionReturnType::VOID: - return "void"; - default: - CHECK(false) << "Unknown ExpressionReturnType."; - return ""; - } -} - -Expression::Expression(ExpressionType type, - ExpressionReturnType return_type, - ExpressionId lhs_id, - const std::vector<ExpressionId>& arguments, - const std::string& name, - double value) - : type_(type), - return_type_(return_type), - lhs_id_(lhs_id), - arguments_(arguments), - name_(name), - value_(value) {} - -Expression Expression::CreateCompileTimeConstant(double v) { - return Expression(ExpressionType::COMPILE_TIME_CONSTANT, - ExpressionReturnType::SCALAR, - kInvalidExpressionId, - {}, - "", - v); -} - -Expression Expression::CreateInputAssignment(const std::string& name) { - return Expression(ExpressionType::INPUT_ASSIGNMENT, - ExpressionReturnType::SCALAR, - kInvalidExpressionId, - {}, - name); -} - -Expression Expression::CreateOutputAssignment(ExpressionId v, - const std::string& name) { - return Expression(ExpressionType::OUTPUT_ASSIGNMENT, - ExpressionReturnType::SCALAR, - kInvalidExpressionId, - {v}, - name); -} - -Expression Expression::CreateAssignment(ExpressionId dst, ExpressionId src) { - return Expression( - ExpressionType::ASSIGNMENT, ExpressionReturnType::SCALAR, dst, {src}); -} - -Expression Expression::CreateBinaryArithmetic(const std::string& op, - ExpressionId l, - ExpressionId r) { - return Expression(ExpressionType::BINARY_ARITHMETIC, - ExpressionReturnType::SCALAR, - kInvalidExpressionId, - {l, r}, - op); -} - -Expression Expression::CreateUnaryArithmetic(const std::string& op, - ExpressionId v) { - return Expression(ExpressionType::UNARY_ARITHMETIC, - ExpressionReturnType::SCALAR, - kInvalidExpressionId, - {v}, - op); -} - -Expression Expression::CreateBinaryCompare(const std::string& name, - ExpressionId l, - ExpressionId r) { - return Expression(ExpressionType::BINARY_COMPARISON, - ExpressionReturnType::BOOLEAN, - kInvalidExpressionId, - {l, r}, - name); -} - -Expression Expression::CreateLogicalNegation(ExpressionId v) { - return Expression(ExpressionType::LOGICAL_NEGATION, - ExpressionReturnType::BOOLEAN, - kInvalidExpressionId, - {v}); -} - -Expression Expression::CreateScalarFunctionCall( - const std::string& name, const std::vector<ExpressionId>& params) { - return Expression(ExpressionType::FUNCTION_CALL, - ExpressionReturnType::SCALAR, - kInvalidExpressionId, - params, - name); -} - -Expression Expression::CreateLogicalFunctionCall( - const std::string& name, const std::vector<ExpressionId>& params) { - return Expression(ExpressionType::FUNCTION_CALL, - ExpressionReturnType::BOOLEAN, - kInvalidExpressionId, - params, - name); -} - -Expression Expression::CreateIf(ExpressionId condition) { - return Expression(ExpressionType::IF, - ExpressionReturnType::VOID, - kInvalidExpressionId, - {condition}); -} - -Expression Expression::CreateElse() { return Expression(ExpressionType::ELSE); } - -Expression Expression::CreateEndIf() { - return Expression(ExpressionType::ENDIF); -} - -Expression Expression::CreateComment(const std::string& comment) { - return Expression(ExpressionType::COMMENT, - ExpressionReturnType::VOID, - kInvalidExpressionId, - {}, - comment); -} - -bool Expression::IsArithmeticExpression() const { - return !IsControlExpression(); -} - -bool Expression::IsControlExpression() const { - return type_ == ExpressionType::IF || type_ == ExpressionType::ELSE || - type_ == ExpressionType::ENDIF || type_ == ExpressionType::NOP || - type_ == ExpressionType::COMMENT; -} - -bool Expression::IsReplaceableBy(const Expression& other) const { - // Check everything except the id. - return (type_ == other.type_ && name_ == other.name_ && - value_ == other.value_ && arguments_ == other.arguments_); -} - -void Expression::Replace(const Expression& other) { - if (other.lhs_id_ == lhs_id_) { - return; - } - - type_ = other.type_; - arguments_ = other.arguments_; - name_ = other.name_; - value_ = other.value_; -} - -bool Expression::DirectlyDependsOn(ExpressionId other) const { - return (std::find(arguments_.begin(), arguments_.end(), other) != - arguments_.end()); -} - -bool Expression::IsCompileTimeConstantAndEqualTo(double constant) const { - return type_ == ExpressionType::COMPILE_TIME_CONSTANT && value_ == constant; -} - -void Expression::MakeNop() { - // The default constructor creates a NOP expression! - *this = Expression(); -} - -bool Expression::operator==(const Expression& other) const { - return type() == other.type() && return_type() == other.return_type() && - name() == other.name() && value() == other.value() && - lhs_id() == other.lhs_id() && arguments() == other.arguments(); -} - -bool Expression::IsSemanticallyEquivalentTo(const Expression& other) const { - return type() == other.type() && name() == other.name() && - value() == other.value() && - arguments().size() == other.arguments().size(); -} - -} // namespace internal -} // namespace ceres
diff --git a/internal/ceres/codegen/expression_graph.cc b/internal/ceres/codegen/expression_graph.cc deleted file mode 100644 index 59f20ea..0000000 --- a/internal/ceres/codegen/expression_graph.cc +++ /dev/null
@@ -1,227 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) - -#include "ceres/codegen/internal/expression_graph.h" - -#include "glog/logging.h" -namespace ceres { -namespace internal { - -static ExpressionGraph* expression_pool = nullptr; - -void StartRecordingExpressions() { - CHECK(expression_pool == nullptr) - << "Expression recording must be stopped before calling " - "StartRecordingExpressions again."; - expression_pool = new ExpressionGraph; -} - -ExpressionGraph StopRecordingExpressions() { - CHECK(expression_pool) - << "Expression recording hasn't started yet or you tried " - "to stop it twice."; - ExpressionGraph result = std::move(*expression_pool); - delete expression_pool; - expression_pool = nullptr; - return result; -} - -ExpressionGraph* GetCurrentExpressionGraph() { return expression_pool; } - -bool ExpressionGraph::DependsOn(ExpressionId A, ExpressionId B) const { - // Depth first search on the expression graph - // Equivalent Recursive Implementation: - // if (A.DirectlyDependsOn(B)) return true; - // for (auto p : A.params_) { - // if (pool[p.id].DependsOn(B, pool)) return true; - // } - std::vector<ExpressionId> stack = ExpressionForId(A).arguments(); - while (!stack.empty()) { - auto top = stack.back(); - stack.pop_back(); - if (top == B) { - return true; - } - auto& expr = ExpressionForId(top); - stack.insert(stack.end(), expr.arguments().begin(), expr.arguments().end()); - } - return false; -} - -bool ExpressionGraph::operator==(const ExpressionGraph& other) const { - if (Size() != other.Size()) { - return false; - } - for (ExpressionId id = 0; id < Size(); ++id) { - if (!(ExpressionForId(id) == other.ExpressionForId(id))) { - return false; - } - } - return true; -} - -void ExpressionGraph::Erase(ExpressionId location) { - CHECK_GE(location, 0); - CHECK_LT(location, Size()); - // Move everything after id to the front and update references - for (ExpressionId id = location + 1; id < Size(); ++id) { - expressions_[id - 1] = expressions_[id]; - auto& expression = expressions_[id - 1]; - // Decrement reference if it points to a shifted variable. - if (expression.lhs_id() >= location) { - expression.set_lhs_id(expression.lhs_id() - 1); - } - for (auto& arg : *expression.mutable_arguments()) { - if (arg >= location) { - arg--; - } - } - } - expressions_.resize(Size() - 1); -} - -void ExpressionGraph::Insert(ExpressionId location, - const Expression& expression) { - CHECK_GE(location, 0); - CHECK_LE(location, Size()); - ExpressionId last_expression_id = Size() - 1; - // Increase size by adding a dummy expression. - expressions_.push_back(Expression()); - - // Move everything after id back and update references - for (ExpressionId id = last_expression_id; id >= location; --id) { - auto& expression = expressions_[id]; - // Increment reference if it points to a shifted variable. - if (expression.lhs_id() >= location) { - expression.set_lhs_id(expression.lhs_id() + 1); - } - for (auto& arg : *expression.mutable_arguments()) { - if (arg >= location) { - arg++; - } - } - expressions_[id + 1] = expression; - } - - if (expression.IsControlExpression() || - expression.lhs_id() != kInvalidExpressionId) { - // Insert new expression at the correct place - expressions_[location] = expression; - } else { - // Arithmetic expression with invalid lhs - // -> Set lhs to location - Expression copy = expression; - copy.set_lhs_id(location); - expressions_[location] = copy; - } -} - -ExpressionId ExpressionGraph::InsertBack(const Expression& expression) { - if (expression.IsControlExpression()) { - // Control expression are just added to the list. We do not return a - // reference to them. - CHECK(expression.lhs_id() == kInvalidExpressionId) - << "Control expressions must have an invalid lhs."; - expressions_.push_back(expression); - return kInvalidExpressionId; - } - - if (expression.lhs_id() == kInvalidExpressionId) { - // Create a new variable name for this expression and set it as the lhs - Expression copy = expression; - copy.set_lhs_id(static_cast<ExpressionId>(expressions_.size())); - expressions_.push_back(copy); - } else { - // The expressions writes to a variable declared in the past - // -> Just add it to the list - CHECK_LE(expression.lhs_id(), expressions_.size()) - << "The left hand side must reference a variable in the past."; - expressions_.push_back(expression); - } - - return Size() - 1; -} - -ExpressionId ExpressionGraph::FindMatchingEndif(ExpressionId id) const { - CHECK(ExpressionForId(id).type() == ExpressionType::IF) - << "FindClosingControlExpression is only valid on IF " - "expressions."; - - // Traverse downwards - for (ExpressionId i = id + 1; i < Size(); ++i) { - const auto& expr = ExpressionForId(i); - if (expr.type() == ExpressionType::ENDIF) { - return i; - - } else if (expr.type() == ExpressionType::IF) { - // Found a nested IF. - // -> Jump over the block and continue behind it. - auto matching_endif = FindMatchingEndif(i); - if (matching_endif == kInvalidExpressionId) { - return kInvalidExpressionId; - } - i = matching_endif; - continue; - } - } - return kInvalidExpressionId; -} - -ExpressionId ExpressionGraph::FindMatchingElse(ExpressionId id) const { - CHECK(ExpressionForId(id).type() == ExpressionType::IF) - << "FindClosingControlExpression is only valid on IF " - "expressions."; - - // Traverse downwards - for (ExpressionId i = id + 1; i < Size(); ++i) { - const auto& expr = ExpressionForId(i); - if (expr.type() == ExpressionType::ELSE) { - // Found it! - return i; - } else if (expr.type() == ExpressionType::ENDIF) { - // Found an endif even though we were looking for an ELSE. - // -> Return invalidId - return kInvalidExpressionId; - } else if (expr.type() == ExpressionType::IF) { - // Found a nested IF. - // -> Jump over the block and continue behind it. - auto matching_endif = FindMatchingEndif(i); - if (matching_endif == kInvalidExpressionId) { - return kInvalidExpressionId; - } - i = matching_endif; - continue; - } - } - return kInvalidExpressionId; -} - -} // namespace internal -} // namespace ceres
diff --git a/internal/ceres/codegen/expression_ref.cc b/internal/ceres/codegen/expression_ref.cc deleted file mode 100644 index 369aec4..0000000 --- a/internal/ceres/codegen/expression_ref.cc +++ /dev/null
@@ -1,165 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) - -#include "ceres/codegen/internal/expression_ref.h" - -#include "ceres/codegen/internal/expression_graph.h" -#include "glog/logging.h" - -namespace ceres { -namespace internal { - -ExpressionRef AddExpressionToGraph(const Expression& expression) { - return ExpressionRef(expression); -} - -ExpressionRef::ExpressionRef(double compile_time_constant) - : ExpressionRef( - Expression::CreateCompileTimeConstant(compile_time_constant)) {} - -ExpressionRef::ExpressionRef(const Expression& expression) { - ExpressionGraph* graph = GetCurrentExpressionGraph(); - CHECK(graph) - << "The ExpressionGraph has to be created before using Expressions. This " - "is achieved by calling ceres::StartRecordingExpressions."; - id = graph->InsertBack(expression); -} - -ExpressionRef::ExpressionRef(const ExpressionRef& other) { *this = other; } - -ExpressionRef& ExpressionRef::operator=(const ExpressionRef& other) { - // Assigning an uninitialized variable to another variable is an error. - CHECK(other.IsInitialized()) << "Uninitialized Assignment."; - if (IsInitialized()) { - // Create assignment from other -> this - AddExpressionToGraph(Expression::CreateAssignment(this->id, other.id)); - } else { - // Create a new variable and - // Create assignment from other -> this - // Passing kInvalidExpressionId to CreateAssignment generates a new - // variable name which we store in the id. - id = AddExpressionToGraph( - Expression::CreateAssignment(kInvalidExpressionId, other.id)) - .id; - } - return *this; -} - -// Compound operators -ExpressionRef& ExpressionRef::operator+=(const ExpressionRef& x) { - *this = *this + x; - return *this; -} - -ExpressionRef& ExpressionRef::operator-=(const ExpressionRef& x) { - *this = *this - x; - return *this; -} - -ExpressionRef& ExpressionRef::operator*=(const ExpressionRef& x) { - *this = *this * x; - return *this; -} - -ExpressionRef& ExpressionRef::operator/=(const ExpressionRef& x) { - *this = *this / x; - return *this; -} - -// Arith. Operators -ExpressionRef operator-(const ExpressionRef& x) { - return AddExpressionToGraph(Expression::CreateUnaryArithmetic("-", x.id)); -} - -ExpressionRef operator+(const ExpressionRef& x) { - return AddExpressionToGraph(Expression::CreateUnaryArithmetic("+", x.id)); -} - -ExpressionRef operator+(const ExpressionRef& x, const ExpressionRef& y) { - return AddExpressionToGraph( - Expression::CreateBinaryArithmetic("+", x.id, y.id)); -} - -ExpressionRef operator-(const ExpressionRef& x, const ExpressionRef& y) { - return AddExpressionToGraph( - Expression::CreateBinaryArithmetic("-", x.id, y.id)); -} - -ExpressionRef operator/(const ExpressionRef& x, const ExpressionRef& y) { - return AddExpressionToGraph( - Expression::CreateBinaryArithmetic("/", x.id, y.id)); -} - -ExpressionRef operator*(const ExpressionRef& x, const ExpressionRef& y) { - return AddExpressionToGraph( - Expression::CreateBinaryArithmetic("*", x.id, y.id)); -} - -ExpressionRef Ternary(const ComparisonExpressionRef& c, - const ExpressionRef& x, - const ExpressionRef& y) { - return AddExpressionToGraph(Expression::CreateScalarFunctionCall( - "ceres::Ternary", {c.id, x.id, y.id})); -} - -#define CERES_DEFINE_EXPRESSION_COMPARISON_OPERATOR(op) \ - ComparisonExpressionRef operator op(const ExpressionRef& x, \ - const ExpressionRef& y) { \ - return ComparisonExpressionRef(AddExpressionToGraph( \ - Expression::CreateBinaryCompare(#op, x.id, y.id))); \ - } - -#define CERES_DEFINE_EXPRESSION_LOGICAL_OPERATOR(op) \ - ComparisonExpressionRef operator op(const ComparisonExpressionRef& x, \ - const ComparisonExpressionRef& y) { \ - return ComparisonExpressionRef(AddExpressionToGraph( \ - Expression::CreateBinaryCompare(#op, x.id, y.id))); \ - } - -CERES_DEFINE_EXPRESSION_COMPARISON_OPERATOR(<) -CERES_DEFINE_EXPRESSION_COMPARISON_OPERATOR(<=) -CERES_DEFINE_EXPRESSION_COMPARISON_OPERATOR(>) -CERES_DEFINE_EXPRESSION_COMPARISON_OPERATOR(>=) -CERES_DEFINE_EXPRESSION_COMPARISON_OPERATOR(==) -CERES_DEFINE_EXPRESSION_COMPARISON_OPERATOR(!=) -CERES_DEFINE_EXPRESSION_LOGICAL_OPERATOR(&&) -CERES_DEFINE_EXPRESSION_LOGICAL_OPERATOR(||) -CERES_DEFINE_EXPRESSION_LOGICAL_OPERATOR(&) -CERES_DEFINE_EXPRESSION_LOGICAL_OPERATOR(|) -#undef CERES_DEFINE_EXPRESSION_COMPARISON_OPERATOR -#undef CERES_DEFINE_EXPRESSION_LOGICAL_OPERATOR - -ComparisonExpressionRef operator!(const ComparisonExpressionRef& x) { - return ComparisonExpressionRef( - AddExpressionToGraph(Expression::CreateLogicalNegation(x.id))); -} - -} // namespace internal -} // namespace ceres
diff --git a/internal/ceres/codegen/optimize_expression_graph.cc b/internal/ceres/codegen/optimize_expression_graph.cc deleted file mode 100644 index 5414dc6..0000000 --- a/internal/ceres/codegen/optimize_expression_graph.cc +++ /dev/null
@@ -1,60 +0,0 @@ -// Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 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) - -#include "ceres/codegen/internal/optimize_expression_graph.h" - -#include "ceres/codegen/internal/eliminate_nops.h" -#include "glog/logging.h" -namespace ceres { -namespace internal { - -OptimizeExpressionGraphSummary OptimizeExpressionGraph( - const OptimizeExpressionGraphOptions& options, ExpressionGraph* graph) { - OptimizeExpressionGraphSummary summary; - summary.num_iterations = 0; - while (summary.num_iterations < options.max_num_iterations) { - summary.num_iterations++; - bool changed = false; - - if (options.eliminate_nops) { - auto pass_summary = EliminateNops(graph); - changed |= pass_summary.expression_graph_changed; - summary.summaries.push_back(pass_summary); - } - - if (!changed) { - break; - } - } - return summary; -} - -} // namespace internal -} // namespace ceres