|
Prev
| Next
|
|
|
|
|
|
jit_atomic.cpp |
|
@(@\newcommand{\W}[1]{ \; #1 \; }
\newcommand{\R}[1]{ {\rm #1} }
\newcommand{\B}[1]{ {\bf #1} }
\newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} }
\newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} }
\newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} }
\newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }@)@This is cppad-20221105 documentation. Here is a link to its
current documentation
.
Atomic Callbacks in JIT Function: Example and Test
Source
# include <cppad/cppad.hpp>
# include <cppad/utility/link_dll_lib.hpp>
# if CPPAD_USE_CPLUSPLUS_2017
# include <filesystem>
# endif
// DLL_EXT
# ifndef _WIN32
# define DLL_EXT ".so"
# else
# define DLL_EXT ".dll"
# endif
// ----------------------------------------------------------------------------
namespace { // BEGIN_EMPTY_NAMESPACE
//
// write_c_file
std::string write_c_file(size_t index, const std::string& csrc)
{ //
std::string file_name = "test_to_csrc_" + CppAD::to_string(index) + ".c";
//
// write file_name
std::ofstream os;
os.open(file_name, std::ios::out);
os << csrc;
os.close();
//
return file_name;
}
//
// atomic_fun
class atomic_fun : public CppAD::atomic_four<double> {
private:
const std::string name_;
public:
atomic_fun(const std::string& name) :
CppAD::atomic_four<double>(name),
name_(name)
{}
private:
bool for_type(
size_t call_id ,
const CppAD::vector<CppAD::ad_type_enum>& type_x ,
CppAD::vector<CppAD::ad_type_enum>& type_y ) override
{ type_y[0] = type_x[0];
return true;
}
// forward double
bool forward(
size_t call_id ,
const CppAD::vector<bool>& select_y ,
size_t order_low ,
size_t order_up ,
const CppAD::vector<double>& taylor_x ,
CppAD::vector<double>& taylor_y ) override
{ if( order_up != 0 )
return false;;
taylor_y[0] = 1.0 / taylor_x[0];
return true;
}
public:
// forward_zero
std::string forward_zero(void)
{ std::string csrc =
"# include <stddef.h>\n"
"int cppad_atomic_" + name_ + "(\n";
csrc +=R"_(
size_t call_id,
size_t nx,
const double* x,
size_t ny,
double* y,
size_t* compare_change)
{ if( nx != 1 ) return 1;
if( ny != 1 ) return 2;
y[0] = 1.0 / x[0];
return 0;
}
)_";
return csrc;
}
};
} // END_EMPTY_NAMESPACE
// ---------------------------------------------------------------------------
bool atomic(void)
{ // ok
bool ok = true;
//
// AD
using CppAD::AD;
//
// function_name
std::string function_name = "reciprocal";
//
// reciprocal
atomic_fun reciprocal(function_name);
//
// nx, ax
size_t nx = 2;
CPPAD_TESTVECTOR( AD<double> ) ax(nx);
double x0 = 0.5, x1 = 4.0;
ax[0] = x0;
ax[1] = x1;
CppAD::Independent(ax);
//
// ny, ay
size_t ny = nx;
CPPAD_TESTVECTOR( AD<double> ) ay(ny);
CPPAD_TESTVECTOR( AD<double> ) atom_x(1), atom_y(1);
for(size_t j = 0; j < nx; ++j)
{ atom_x[0] = ax[j];
reciprocal(atom_x, atom_y);
ay[j] = atom_y[0];
}
//
// function_name
function_name = "use_reciprocal";
//
// f
CppAD::ADFun<double> f(ax, ay);
f.function_name_set(function_name);
//
// library_name
std::string library_name = "test_to_csrc";
//
// dll_file
std::string dll_file = "test_to_csrc" DLL_EXT;
//
// csrc_files
CppAD::vector<std::string> csrc_files(2);
csrc_files[0] = write_c_file(0, reciprocal.forward_zero() );
std::string c_type = "double";
std::stringstream ss;
f.to_csrc(ss, c_type);
csrc_files[1] = write_c_file(1, ss.str() );
//
// create_dll_lib
std::map< std::string, std::string > options;
std::string err_msg = CppAD::create_dll_lib(dll_file, csrc_files, options);
if( err_msg != "" )
{ std::cout << "jit_atomic: " << err_msg << "\n";
ok = false;
return ok;
}
//
// dll_linker
CppAD::link_dll_lib dll_linker(dll_file, err_msg);
//
// jit_double
using CppAD::jit_double;
//
// jit_function
jit_double jit_function = nullptr;
if( err_msg != "" )
{ std::cout << "jit_atomic: " << err_msg << "\n";
ok = false;
}
else
{ // jit_function
std::string complete_name = "cppad_jit_" + function_name;
jit_function = reinterpret_cast<jit_double>(
dll_linker(complete_name, err_msg)
);
if( err_msg != "" )
{ std::cout << "jit_atomic: " << err_msg << "\n";
ok = false;
}
}
if( ok )
{ //
// ok
// no change
CppAD::vector<double> x(nx), y(ny);
x[0] = x0;
x[1] = x1;
for(size_t i = 0; i < ny; ++i)
y[i] = std::numeric_limits<double>::quiet_NaN();
size_t compare_change = 0;
int flag = jit_function(
nx, x.data(), ny, y.data(), &compare_change
);
ok &= flag == 0;
ok &= compare_change == 0;
for(size_t i = 0; i < ny; ++i)
ok &= y[i] == 1.0 / x[i];
}
return ok;
}
Input File: example/jit/atomic.cpp