CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
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
19namespace CppAD {
20namespace cg {
21
22template<class Base>
24private:
25 atomic_base<Base>* atomic_;
26public:
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
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
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
94private:
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
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
unsigned long nnz
unsigned long size
const unsigned long * idx