Just saying. It’s not necessarily a bug, but we don’t have a good way around it. I was looking at math#533 and boiled it down to this (save this in the math library under test/nan_test.cpp
and you can run with ./runTests.py test/nan_test.cpp
):
#include <stan/math/rev/scal.hpp>
#include <gtest/gtest.h>
TEST(foo, bar) {
stan::math::var a = 5;
stan::math::var z = 10;
stan::math::var x;
if (a < sqrt(-z)) {
x = a * z;
} else {
x = a / z;
}
stan::math::print_stack(std::cout);
std::vector<stan::math::var> vars;
vars.push_back(a);
vars.push_back(z);
std::vector<double> grad;
x.grad(vars, grad);
for (size_t n = 0; n < grad.size(); n++)
std::cout << "grad[" << n << "] = " << grad[n] << std::endl;
std::cout << std::endl;
EXPECT_EQ(0.1, grad[0]);
EXPECT_EQ(-0.05, grad[1]);
}
The output is below. Notice the nan
in the 4th position on the stack. That’s from the evaluation of sqrt(-z)
which is just used for the conditional; IEEE math always works out the same, so the conditional will evaluate to false, but there’s no recovery from this:
test/unit/nan_test --gtest_output="xml:test/unit/nan_test.xml"
Running main() from gtest_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from foo
[ RUN ] foo.bar
STACK, size=5
0 5:0 5 : 0
1 10:0 10 : 0
2 -10:0 -10 : 0
3 nan:0 nan : 0
4 0.5:0 0.5 : 0
grad[0] = 0.1
grad[1] = nan
test/unit/nan_test.cpp:26: Failure
Value of: grad[1]
Actual: nan
Expected: -0.05
[ FAILED ] foo.bar (0 ms)
[----------] 1 test from foo (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] foo.bar
1 FAILED TEST