mirror of
https://github.com/ceres-solver/ceres-solver.git
synced 2026-08-29 16:40:38 +08:00
Add namespaces to generated functions and constants
The generated function names now include the containing namespace. For example: std::abs(...) std::sin(...) ceres::Ternary(...) This patch also fixes the generation of inf/nan compile time constants, using std::numeric_limits. Change-Id: I4a36b09c68dd2adabed49fd4f7f37c8229ab7377
This commit is contained in:
@@ -115,37 +115,37 @@ ExpressionRef operator*(const ExpressionRef& x, const ExpressionRef& y);
|
||||
ExpressionRef operator/(const ExpressionRef& x, const ExpressionRef& y);
|
||||
|
||||
// Functions
|
||||
#define CERES_DEFINE_UNARY_FUNCTION_CALL(name) \
|
||||
inline ExpressionRef name(const ExpressionRef& x) { \
|
||||
return AddExpressionToGraph( \
|
||||
Expression::CreateScalarFunctionCall(#name, {x.id})); \
|
||||
#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(name) \
|
||||
#define CERES_DEFINE_BINARY_FUNCTION_CALL(ns, name) \
|
||||
inline ExpressionRef name(const ExpressionRef& x, const ExpressionRef& y) { \
|
||||
return AddExpressionToGraph( \
|
||||
Expression::CreateScalarFunctionCall(#name, {x.id, y.id})); \
|
||||
Expression::CreateScalarFunctionCall(#ns "::" #name, {x.id, y.id})); \
|
||||
}
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(abs);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(acos);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(asin);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(atan);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(cbrt);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(ceil);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(cos);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(cosh);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(exp);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(exp2);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(floor);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(log);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(log2);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(sin);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(sinh);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(sqrt);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(tan);
|
||||
CERES_DEFINE_UNARY_FUNCTION_CALL(tanh);
|
||||
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(atan2);
|
||||
CERES_DEFINE_BINARY_FUNCTION_CALL(pow);
|
||||
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
|
||||
@@ -198,16 +198,16 @@ ComparisonExpressionRef operator|(const ComparisonExpressionRef& x,
|
||||
const ComparisonExpressionRef& y);
|
||||
ComparisonExpressionRef operator!(const ComparisonExpressionRef& x);
|
||||
|
||||
#define CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL(name) \
|
||||
inline ComparisonExpressionRef name(const ExpressionRef& x) { \
|
||||
return ComparisonExpressionRef(AddExpressionToGraph( \
|
||||
Expression::CreateLogicalFunctionCall(#name, {x.id}))); \
|
||||
#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(isfinite);
|
||||
CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL(isinf);
|
||||
CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL(isnan);
|
||||
CERES_DEFINE_UNARY_LOGICAL_FUNCTION_CALL(isnormal);
|
||||
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
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
// The CERES_CODEGEN macro is defined by the build system only during code
|
||||
// generation.
|
||||
#ifndef CERES_CODEGEN
|
||||
#define CERES_LOCAL_VARIABLE(_template_type, _local_variable) (_local_variable)
|
||||
#define CERES_LOCAL_VARIABLE(type, local_variable) type(local_variable)
|
||||
#define CERES_IF(condition_) if (condition_)
|
||||
#define CERES_ELSE else
|
||||
#define CERES_ENDIF
|
||||
|
||||
@@ -29,10 +29,13 @@
|
||||
// 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 {
|
||||
|
||||
@@ -113,7 +116,23 @@ std::string CodeGenerator::ExpressionToString(ExpressionId id) {
|
||||
// Format: <lhs_id> = <value>;
|
||||
// Example: v_0 = 3.1415;
|
||||
//
|
||||
result << indentation_ << lhs << " = " << value << ";";
|
||||
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: {
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#define CERES_CODEGEN
|
||||
|
||||
#include "ceres/codegen/internal/code_generator.h"
|
||||
|
||||
#include "ceres/codegen/internal/expression_graph.h"
|
||||
#include "ceres/codegen/internal/expression_ref.h"
|
||||
#include "gtest/gtest.h"
|
||||
@@ -65,16 +66,26 @@ TEST(CodeGenerator, COMPILE_TIME_CONSTANT) {
|
||||
T a = T(0);
|
||||
T b = T(123.5);
|
||||
T c = T(1 + 1);
|
||||
T d; // Uninitialized variables should not generate code!
|
||||
T d = T(std::numeric_limits<double>::infinity());
|
||||
T e = T(-std::numeric_limits<double>::infinity());
|
||||
T f = T(std::numeric_limits<double>::quiet_NaN());
|
||||
T g; // Uninitialized variables should not generate code!
|
||||
auto graph = StopRecordingExpressions();
|
||||
std::vector<std::string> expected_code = {"{",
|
||||
" double v_0;",
|
||||
" double v_1;",
|
||||
" double v_2;",
|
||||
" v_0 = 0;",
|
||||
" v_1 = 123.5;",
|
||||
" v_2 = 2;",
|
||||
"}"};
|
||||
std::vector<std::string> expected_code = {
|
||||
"{",
|
||||
" double v_0;",
|
||||
" double v_1;",
|
||||
" double v_2;",
|
||||
" double v_3;",
|
||||
" double v_4;",
|
||||
" double v_5;",
|
||||
" v_0 = 0;",
|
||||
" v_1 = 123.5;",
|
||||
" v_2 = 2;",
|
||||
" v_3 = std::numeric_limits<double>::infinity();",
|
||||
" v_4 = -std::numeric_limits<double>::infinity();",
|
||||
" v_5 = std::numeric_limits<double>::quiet_NaN();",
|
||||
"}"};
|
||||
GenerateAndCheck(graph, expected_code);
|
||||
}
|
||||
|
||||
@@ -352,26 +363,26 @@ TEST(CodeGenerator, FUNCTION_CALL) {
|
||||
" double v_21;",
|
||||
" v_0 = 0;",
|
||||
" v_1 = 1;",
|
||||
" v_2 = abs(v_0);",
|
||||
" v_3 = acos(v_0);",
|
||||
" v_4 = asin(v_0);",
|
||||
" v_5 = atan(v_0);",
|
||||
" v_6 = cbrt(v_0);",
|
||||
" v_7 = ceil(v_0);",
|
||||
" v_8 = cos(v_0);",
|
||||
" v_9 = cosh(v_0);",
|
||||
" v_10 = exp(v_0);",
|
||||
" v_11 = exp2(v_0);",
|
||||
" v_12 = floor(v_0);",
|
||||
" v_13 = log(v_0);",
|
||||
" v_14 = log2(v_0);",
|
||||
" v_15 = sin(v_0);",
|
||||
" v_16 = sinh(v_0);",
|
||||
" v_17 = sqrt(v_0);",
|
||||
" v_18 = tan(v_0);",
|
||||
" v_19 = tanh(v_0);",
|
||||
" v_20 = atan2(v_0, v_1);",
|
||||
" v_21 = pow(v_0, v_1);",
|
||||
" v_2 = std::abs(v_0);",
|
||||
" v_3 = std::acos(v_0);",
|
||||
" v_4 = std::asin(v_0);",
|
||||
" v_5 = std::atan(v_0);",
|
||||
" v_6 = std::cbrt(v_0);",
|
||||
" v_7 = std::ceil(v_0);",
|
||||
" v_8 = std::cos(v_0);",
|
||||
" v_9 = std::cosh(v_0);",
|
||||
" v_10 = std::exp(v_0);",
|
||||
" v_11 = std::exp2(v_0);",
|
||||
" v_12 = std::floor(v_0);",
|
||||
" v_13 = std::log(v_0);",
|
||||
" v_14 = std::log2(v_0);",
|
||||
" v_15 = std::sin(v_0);",
|
||||
" v_16 = std::sinh(v_0);",
|
||||
" v_17 = std::sqrt(v_0);",
|
||||
" v_18 = std::tan(v_0);",
|
||||
" v_19 = std::tanh(v_0);",
|
||||
" v_20 = std::atan2(v_0, v_1);",
|
||||
" v_21 = std::pow(v_0, v_1);",
|
||||
"}"};
|
||||
GenerateAndCheck(graph, expected_code);
|
||||
}
|
||||
@@ -394,10 +405,10 @@ TEST(CodeGenerator, LOGICAL_FUNCTION_CALL) {
|
||||
" bool v_3;",
|
||||
" bool v_4;",
|
||||
" v_0 = 1;",
|
||||
" v_1 = isfinite(v_0);",
|
||||
" v_2 = isinf(v_0);",
|
||||
" v_3 = isnan(v_0);",
|
||||
" v_4 = isnormal(v_0);",
|
||||
" v_1 = std::isfinite(v_0);",
|
||||
" v_2 = std::isinf(v_0);",
|
||||
" v_3 = std::isnan(v_0);",
|
||||
" v_4 = std::isnormal(v_0);",
|
||||
"}"};
|
||||
GenerateAndCheck(graph, expected_code);
|
||||
}
|
||||
|
||||
@@ -284,26 +284,28 @@ TEST(ExpressionRef, SCALAR_FUNCTION_CALL) {
|
||||
ExpressionGraph reference;
|
||||
reference.InsertBack(Expression::CreateCompileTimeConstant(1));
|
||||
reference.InsertBack(Expression::CreateCompileTimeConstant(2));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("abs", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("acos", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("asin", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("atan", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("cbrt", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("ceil", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("cos", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("cosh", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("exp", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("exp2", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("floor", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("log", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("log2", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("sin", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("sinh", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("sqrt", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("tan", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("tanh", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("atan2", {0, 1}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("pow", {0, 1}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::abs", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::acos", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::asin", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::atan", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::cbrt", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::ceil", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::cos", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::cosh", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::exp", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::exp2", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::floor", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::log", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::log2", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::sin", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::sinh", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::sqrt", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::tan", {0}));
|
||||
reference.InsertBack(Expression::CreateScalarFunctionCall("std::tanh", {0}));
|
||||
reference.InsertBack(
|
||||
Expression::CreateScalarFunctionCall("std::atan2", {0, 1}));
|
||||
reference.InsertBack(
|
||||
Expression::CreateScalarFunctionCall("std::pow", {0, 1}));
|
||||
EXPECT_EQ(reference, graph);
|
||||
}
|
||||
|
||||
@@ -318,10 +320,14 @@ TEST(ExpressionRef, LOGICAL_FUNCTION_CALL) {
|
||||
|
||||
ExpressionGraph reference;
|
||||
reference.InsertBack(Expression::CreateCompileTimeConstant(1));
|
||||
reference.InsertBack(Expression::CreateLogicalFunctionCall("isfinite", {0}));
|
||||
reference.InsertBack(Expression::CreateLogicalFunctionCall("isinf", {0}));
|
||||
reference.InsertBack(Expression::CreateLogicalFunctionCall("isnan", {0}));
|
||||
reference.InsertBack(Expression::CreateLogicalFunctionCall("isnormal", {0}));
|
||||
reference.InsertBack(
|
||||
Expression::CreateLogicalFunctionCall("std::isfinite", {0}));
|
||||
reference.InsertBack(
|
||||
Expression::CreateLogicalFunctionCall("std::isinf", {0}));
|
||||
reference.InsertBack(
|
||||
Expression::CreateLogicalFunctionCall("std::isnan", {0}));
|
||||
reference.InsertBack(
|
||||
Expression::CreateLogicalFunctionCall("std::isnormal", {0}));
|
||||
EXPECT_EQ(reference, graph);
|
||||
}
|
||||
|
||||
|
||||
@@ -129,8 +129,8 @@ ExpressionRef operator*(const ExpressionRef& x, const ExpressionRef& y) {
|
||||
ExpressionRef Ternary(const ComparisonExpressionRef& c,
|
||||
const ExpressionRef& x,
|
||||
const ExpressionRef& y) {
|
||||
return AddExpressionToGraph(
|
||||
Expression::CreateScalarFunctionCall("Ternary", {c.id, x.id, y.id}));
|
||||
return AddExpressionToGraph(Expression::CreateScalarFunctionCall(
|
||||
"ceres::Ternary", {c.id, x.id, y.id}));
|
||||
}
|
||||
|
||||
#define CERES_DEFINE_EXPRESSION_COMPARISON_OPERATOR(op) \
|
||||
|
||||
Reference in New Issue
Block a user