Fix a variadic evaluation bug in AutoDiff.

Thanks to Julien Michot for reporting.

Change-Id: I322cd177e85c18ba3fbee56149696d4140f79c68
This commit is contained in:
Sameer Agarwal
2012-11-28 12:00:34 -08:00
parent 9895a4f50c
commit 86f6ea68b8
2 changed files with 271 additions and 1 deletions
+1 -1
View File
@@ -390,7 +390,7 @@ struct AutoDiff {
x.get() + jet8,
x.get() + jet9,
};
JetT *output = x.get() + jet6;
JetT* output = x.get() + jet9;
#define CERES_MAKE_1ST_ORDER_PERTURBATION(i) \
if (N ## i) { \
+270
View File
@@ -377,6 +377,276 @@ TEST(AutoDiff, VaryingNumberOfResidualsForOneCostFunctorType) {
}
}
struct Residual1Param {
template <typename T>
bool operator()(const T* x0, T* y) const {
y[0] = *x0;
return true;
}
};
struct Residual2Param {
template <typename T>
bool operator()(const T* x0, const T* x1, T* y) const {
y[0] = *x0 + pow(*x1, 2);
return true;
}
};
struct Residual3Param {
template <typename T>
bool operator()(const T* x0, const T* x1, const T* x2, T* y) const {
y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3);
return true;
}
};
struct Residual4Param {
template <typename T>
bool operator()(const T* x0,
const T* x1,
const T* x2,
const T* x3,
T* y) const {
y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4);
return true;
}
};
struct Residual5Param {
template <typename T>
bool operator()(const T* x0,
const T* x1,
const T* x2,
const T* x3,
const T* x4,
T* y) const {
y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5);
return true;
}
};
struct Residual6Param {
template <typename T>
bool operator()(const T* x0,
const T* x1,
const T* x2,
const T* x3,
const T* x4,
const T* x5,
T* y) const {
y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
pow(*x5, 6);
return true;
}
};
struct Residual7Param {
template <typename T>
bool operator()(const T* x0,
const T* x1,
const T* x2,
const T* x3,
const T* x4,
const T* x5,
const T* x6,
T* y) const {
y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
pow(*x5, 6) + pow(*x6, 7);
return true;
}
};
struct Residual8Param {
template <typename T>
bool operator()(const T* x0,
const T* x1,
const T* x2,
const T* x3,
const T* x4,
const T* x5,
const T* x6,
const T* x7,
T* y) const {
y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
pow(*x5, 6) + pow(*x6, 7) + pow(*x7, 8);
return true;
}
};
struct Residual9Param {
template <typename T>
bool operator()(const T* x0,
const T* x1,
const T* x2,
const T* x3,
const T* x4,
const T* x5,
const T* x6,
const T* x7,
const T* x8,
T* y) const {
y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
pow(*x5, 6) + pow(*x6, 7) + pow(*x7, 8) + pow(*x8, 9);
return true;
}
};
struct Residual10Param {
template <typename T>
bool operator()(const T* x0,
const T* x1,
const T* x2,
const T* x3,
const T* x4,
const T* x5,
const T* x6,
const T* x7,
const T* x8,
const T* x9,
T* y) const {
y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
pow(*x5, 6) + pow(*x6, 7) + pow(*x7, 8) + pow(*x8, 9) + pow(*x9, 10);
return true;
}
};
TEST(AutoDiff, VariadicAutoDiff) {
double x[10];
double residual = 0;
double* parameters[10];
double jacobian_values[10];
double* jacobians[10];
for (int i = 0; i < 10; ++i) {
x[i] = 2.0;
parameters[i] = x + i;
jacobians[i] = jacobian_values + i;
}
{
Residual1Param functor;
int num_variables = 1;
EXPECT_TRUE((AutoDiff<Residual1Param, double, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
{
Residual2Param functor;
int num_variables = 2;
EXPECT_TRUE((AutoDiff<Residual2Param, double, 1, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
{
Residual3Param functor;
int num_variables = 3;
EXPECT_TRUE((AutoDiff<Residual3Param, double, 1, 1, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
{
Residual4Param functor;
int num_variables = 4;
EXPECT_TRUE((AutoDiff<Residual4Param, double, 1, 1, 1, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
{
Residual5Param functor;
int num_variables = 5;
EXPECT_TRUE((AutoDiff<Residual5Param, double, 1, 1, 1, 1, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
{
Residual6Param functor;
int num_variables = 6;
EXPECT_TRUE((AutoDiff<Residual6Param,
double,
1, 1, 1, 1, 1, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
{
Residual7Param functor;
int num_variables = 7;
EXPECT_TRUE((AutoDiff<Residual7Param,
double,
1, 1, 1, 1, 1, 1, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
{
Residual8Param functor;
int num_variables = 8;
EXPECT_TRUE((AutoDiff<
Residual8Param,
double, 1, 1, 1, 1, 1, 1, 1, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
{
Residual9Param functor;
int num_variables = 9;
EXPECT_TRUE((AutoDiff<
Residual9Param,
double,
1, 1, 1, 1, 1, 1, 1, 1, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
{
Residual10Param functor;
int num_variables = 10;
EXPECT_TRUE((AutoDiff<
Residual10Param,
double,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1>::Differentiate(
functor, parameters, 1, &residual, jacobians)));
EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
for (int i = 0; i < num_variables; ++i) {
EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
}
}
}
// This is fragile test that triggers the alignment bug on
// i686-apple-darwin10-llvm-g++-4.2 (GCC) 4.2.1. It is quite possible,
// that other combinations of operating system + compiler will