# include <cppad/cppad.hpp>
# include <cctype>
namespace {
void myhandler(
bool known ,
int line ,
const char *file ,
const char *exp ,
const char *msg )
{ // error handler must not return, so throw an exception
std::string message = msg;
throw message;
}
}
bool check_for_nan(void)
{ bool ok = true;
using CppAD::AD;
using std::string;
double eps = 10. * std::numeric_limits<double>::epsilon();
// replace the default CppAD error handler
CppAD::ErrorHandler info(myhandler);
CPPAD_TESTVECTOR(AD<double>) ax(2), ay(2);
ax[0] = 2.0;
ax[1] = 1.0;
CppAD::Independent(ax);
ay[0] = sqrt( ax[0] );
ay[1] = sqrt( ax[1] );
CppAD::ADFun<double> f(ax, ay);
CPPAD_TESTVECTOR(double) x(2), y(2);
x[0] = 2.0;
x[1] = -1.0;
// use try / catch because this causes an exception
// (assuming that NDEBUG is not defined)
f.check_for_nan(true);
try {
y = f.Forward(0, x);
# ifndef NDEBUG
// When compiled with NDEBUG defined,
// CppAD does not spend time checking for nan.
ok = false;
# endif
}
catch(std::string msg)
{
// get and check size of the independent variable vector
string pattern = "vector_size = ";
size_t start = msg.find(pattern) + pattern.size();
string number;
for(size_t i = start; msg[i] != '\n'; i++)
number += msg[i];
size_t vector_size = std::atoi(number.c_str());
ok &= vector_size == 2;
// get and check first dependent variable index that is nan
pattern = "index = ";
start = msg.find(pattern) + pattern.size();
number = "";
for(size_t i = start; msg[i] != '\n'; i++)
number += msg[i];
size_t index = std::atoi(number.c_str());
ok &= index == 1;
// get the name of the file
pattern = "file_name = ";
start = msg.find(pattern) + pattern.size();
string file_name;
for(size_t i = start; msg[i] != '\n'; i++)
file_name += msg[i];
// get and check independent variable vector that resulted in the nan
CppAD::vector<double> vec(vector_size);
CppAD::get_check_for_nan(vec, file_name);
for(size_t i = 0; i < vector_size; i++)
ok &= vec[i] == x[i];
}
// now do calculation without an exception
f.check_for_nan(false);
y = f.Forward(0, x);
ok &= CppAD::NearEqual(y[0], std::sqrt(x[0]), eps, eps);
ok &= CppAD::isnan( y[1] );
return ok;
}