|  | @@ -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_
 |