CppADCodeGen  HEAD
A C++ Algorithmic Differentiation Package with Source Code Generation
atomic_external_function_wrapper.hpp
1 #ifndef CPPAD_CG_ATOMIC_EXTERNAL_FUNCTION_INCLUDED
2 #define CPPAD_CG_ATOMIC_EXTERNAL_FUNCTION_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2014 Ciengis
6  * Copyright (C) 2018 Joao Leal
7  *
8  * CppADCodeGen is distributed under multiple licenses:
9  *
10  * - Eclipse Public License Version 1.0 (EPL1), and
11  * - GNU General Public License Version 3 (GPL3).
12  *
13  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
14  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
15  * ----------------------------------------------------------------------------
16  * Author: Joao Leal
17  */
18 
19 namespace CppAD {
20 namespace cg {
21 
22 template<class Base>
24 private:
25  atomic_base<Base>* atomic_;
26 public:
27 
28  inline AtomicExternalFunctionWrapper(atomic_base<Base>& atomic) :
29  atomic_(&atomic) {
30  }
31 
32  inline virtual ~AtomicExternalFunctionWrapper() = default;
33 
35  int q,
36  int p,
37  const Array tx[],
38  Array& ty) override {
39  size_t m = ty.size;
40  size_t n = tx[0].size;
41 
42  CppAD::vector<bool> vx, vy;
43 
44  convert(tx, libModel._tx, n, p, p + 1);
45 
46  size_t ty_size = m * (p + 1);
47  libModel._ty.resize(ty_size);
48 
49  std::fill(&libModel._ty[0], &libModel._ty[0] + ty_size, Base(0));
50 
51  bool ret = atomic_->forward(q, p, vx, vy, libModel._tx, libModel._ty);
52 
53  convertAdd(libModel._ty, ty, m, p, p);
54 
55  return ret;
56  }
57 
59  int p,
60  const Array tx[],
61  Array& px,
62  const Array py[]) override {
63  size_t m = py[0].size;
64  size_t n = tx[0].size;
65 
66  convert(tx, libModel._tx, n, p, p + 1);
67 
68  libModel._ty.resize(m * (p + 1));
69  std::fill(&libModel._ty[0], &libModel._ty[0] + libModel._ty.size(), Base(0));
70 
71  convert(py, libModel._py, m, p, p + 1);
72 
73  size_t px_size = n * (p + 1);
74  libModel._px.resize(px_size);
75 
76  std::fill(&libModel._px[0], &libModel._px[0] + px_size, Base(0));
77 
78 #ifndef NDEBUG
79  if (libModel._evalAtomicForwardOne4CppAD) {
80  // only required in order to avoid an issue with a validation inside CppAD
81  CppAD::vector<bool> vx, vy;
82  if (!atomic_->forward(p, p, vx, vy, libModel._tx, libModel._ty))
83  return false;
84  }
85 #endif
86 
87  bool ret = atomic_->reverse(p, libModel._tx, libModel._ty, libModel._px, libModel._py);
88 
89  convertAdd(libModel._px, px, n, p, 0); // k=0 for both p=0 and p=1
90 
91  return ret;
92  }
93 
94 private:
95 
96  inline void convert(const Array from[],
98  size_t n,
99  size_t p,
100  size_t kmax) {
101  size_t p1 = p + 1;
102  to.resize(n * p1);
103 
104  for (size_t k = 0; k < kmax; k++) {
105  Base* values = static_cast<Base*> (from[k].data);
106  if (from[k].sparse) {
107  if (p == 0) {
108  std::fill(&to[0], &to[0] + n, Base(0));
109  } else {
110  for (size_t j = 0; j < n; j++) {
111  to[j * p1 + k] = Base(0);
112  }
113  }
114 
115  for (size_t e = 0; e < from[k].nnz; e++) {
116  size_t j = from[k].idx[e];
117  to[j * p1 + k] = values[e];
118  }
119  } else {
120  for (size_t j = 0; j < n; j++) {
121  to[j * p1 + k] = values[j];
122  }
123  }
124  }
125  }
126 
127  inline void convertAdd(const CppAD::vector<Base>& from,
128  Array& to,
129  size_t n,
130  size_t p,
131  size_t k) {
132  CPPADCG_ASSERT_KNOWN(!to.sparse, "output must be a dense array")
133  CPPADCG_ASSERT_KNOWN(to.size >= n, "invalid size")
134 
135  Base* values = static_cast<Base*> (to.data);
136 
137  if (p == 0) {
138  std::copy(&from[0], &from[0] + n, values);
139  } else {
140  size_t p1 = p + 1;
141 
142  for (size_t j = 0; j < n; j++) {
143  values[j] += from[j * p1 + k];
144  }
145  }
146 
147  }
148 };
149 
150 } // END cg namespace
151 } // END CppAD namespace
152 
153 #endif
unsigned long nnz
const unsigned long * idx
unsigned long size
bool reverse(FunctorGenericModel< Base > &libModel, int p, const Array tx[], Array &px, const Array py[]) override
bool forward(FunctorGenericModel< Base > &libModel, int q, int p, const Array tx[], Array &ty) override