1#ifndef CPPAD_CG_ABSTRACT_ATOMIC_FUN_INCLUDED
2#define CPPAD_CG_ABSTRACT_ATOMIC_FUN_INCLUDED
62 CPPADCG_ASSERT_KNOWN(!name.empty(),
"The atomic function name cannot be empty")
63 this->
option(CppAD::atomic_base<CGB>::set_sparsity_enum);
69 template <
class ADVector>
106 size_t n =
vx.size();
108 for (
size_t j = 0;
j <
n;
j++) {
109 x[
j] =
tx[
j * (
p + 1)];
112 zeroOrderDependency(
vx,
vy, x);
118 if (!evalForwardValues(
q,
p,
tx,
tyb,
ty.size()))
121 CPPADCG_ASSERT_UNKNOWN(
tyb.size() ==
ty.size())
122 for (
size_t i = 0;
i <
ty.size();
i++) {
128 size_t m =
ty.size() / (
p + 1);
139 size_t n =
tx.size() / (
p + 1);
142 for (
size_t j = 0;
j <
n;
j++) {
143 if (!
tx[
j * (
p + 1) + 1].isIdenticalZero())
150 for (
size_t j = 0;
j <
n;
j++) {
151 x[
j] =
tx[
j * (
p + 1)];
155 bool good = this->for_sparse_jac(1,
r, s, x);
164 for (
size_t i = 0;
i < m;
i++) {
178 for (
size_t i = 0;
i <
ty.size();
i++) {
188 if (!evalForwardValues(
q,
p,
tx,
tyb,
ty.size()))
193 CPPADCG_ASSERT_UNKNOWN(
handler !=
nullptr)
198 for (
size_t k = 0;
k <
p1;
k++) {
206 std::vector<Argument<Base> >
args(2 *
p1);
207 for (
size_t k = 0;
k <
p1;
k++) {
213 handler->registerAtomicFunction(*
this);
215 for (
size_t k = 0;
k <
p1;
k++) {
216 for (
size_t i = 0;
i < m;
i++) {
219 ty[
pos] =
CGB(*
handler->makeNode(CGOpCode::ArrayElement, {i}, {*tyArray[k], *atomicOp}));
254 CPPADCG_ASSERT_UNKNOWN(
pxb.size() ==
px.size())
256 for (
size_t i = 0;
i <
px.size();
i++) {
273 size_t m =
ty.size() /
p1;
274 size_t n =
tx.size() /
p1;
277 for (
size_t i = 0;
i < m;
i++) {
278 if (!
py[
i *
p1].isIdenticalZero()) {
284 for (
size_t j = 0;
j <
n;
j++) {
289 bool good = this->rev_sparse_jac(1,
rt,
st, x);
294 for (
size_t j = 0;
j <
n;
j++) {
310 for (
size_t j = 0;
j <
n;
j++) {
312 if (!
tx[
j *
p1 + 1].isIdenticalZero()) {
316 for (
size_t i = 0;
i < m;
i++) {
317 s[
i] = !
py[
i *
p1 + 1].isIdenticalZero();
320 this->rev_sparse_hes(
vx, s,
t, 1,
r,
u, v, x);
322 for (
size_t j = 0;
j <
n;
j++) {
336 for (
size_t j = 0;
j <
px.size();
j++) {
363 CPPADCG_ASSERT_UNKNOWN(
handler !=
nullptr)
366 for (
size_t k = 0;
k <=
p;
k++) {
389 std::vector<Argument<Base> >
args(4 *
p1);
390 for (
size_t k = 0;
k <=
p;
k++) {
398 handler->registerAtomicFunction(*
this);
400 for (
size_t k = 0;
k <
p1;
k++) {
401 for (
size_t j = 0;
j <
n;
j++) {
404 px[
pos] =
CGB(*
handler->makeNode(CGOpCode::ArrayElement, {j}, {*pxArray[k], *atomicOp}));
424 for (
size_t i = 0;
i <
n;
i++)
428 bool good = this->for_sparse_jac(
n,
r, s, x);
430 throw CGException(
"Failed to compute jacobian sparsity pattern for atomic function '", this->
atomic_name(),
"'");
440 for (
size_t i = 0;
i < m;
i++)
444 bool good = this->rev_sparse_jac(m,
rt,
st, x);
446 throw CGException(
"Failed to compute jacobian sparsity pattern for atomic function '", this->
atomic_name(),
"'");
456 for (
size_t i = 0;
i < m; ++
i)
459 return hessianSparsitySet(s, x);
471 for (
size_t j = 0;
j <
n;
j++)
475 for (
size_t i = 0;
i <
n; ++
i)
479 for (
size_t i = 0;
i <
n; ++
i)
485 bool good = this->rev_sparse_hes(
vx, s,
t,
n,
r,
u, v, x);
487 throw CGException(
"Failed to compute Hessian sparsity pattern for atomic function '", this->
atomic_name(),
"'");
497 static size_t count = 0;
546 inline bool evalForwardValues(
size_t q,
554 for (
size_t i = 0;
i <
txb.size();
i++) {
561 inline bool evalReverseValues(
size_t p,
570 pxb.resize(
tx.size());
573 for (
size_t i = 0;
i <
txb.size();
i++) {
576 for (
size_t i = 0;
i <
tyb.size();
i++) {
579 for (
size_t i = 0;
i <
pyb.size();
i++) {
CGAbstractAtomicFun(const std::string &name, bool standAlone=false)
bool forward(size_t q, size_t p, const CppAD::vector< bool > &vx, CppAD::vector< bool > &vy, const CppAD::vector< CGB > &tx, CppAD::vector< CGB > &ty) override
virtual CppAD::vector< std::set< size_t > > hessianSparsitySet(const CppAD::vector< bool > &s, const CppAD::vector< CGB > &x)
static size_t createNewAtomicFunctionID()
bool reverse(size_t p, const CppAD::vector< CGB > &tx, const CppAD::vector< CGB > &ty, CppAD::vector< CGB > &px, const CppAD::vector< CGB > &py) override
virtual bool atomicReverse(size_t p, const CppAD::vector< Base > &tx, const CppAD::vector< Base > &ty, CppAD::vector< Base > &px, const CppAD::vector< Base > &py)=0
virtual bool atomicForward(size_t q, size_t p, const CppAD::vector< Base > &tx, CppAD::vector< Base > &ty)=0
bool isStandAlone() const
bool GreaterThanZero(const cg::CG< Base > &x)
bool IdenticalZero(const cg::CG< Base > &x)